Connecting menu options to dialog windows
Up until this point, none of the menu options in the application actually do anything. Similarly, there are a series of dialog windows that never appear. In this section, you will connect the menus to open these dialog windows accordingly.
Creating functions for configuring dialog windows
First up, create the functions given in Listing 21, which will configure the dialog windows correctly for the selected operation.
Listing 21. Functions for configuring dialog windows for selected operation
function renameGroup() {
var group = groupsTree.get("selectedItem");
var groupId = group.id;
var groupName = group.name;
dojo.byId("edit_group_id").value = groupId;
dijit.byId("edit_group_old").set("value", groupName);
editGroupDialog.show();
}
function refreshGroupDropDown() {
var theStore = dijit.byId("edit_contact_group").store;
theStore.close();
theStore.url = "data/groups.php";
theStore.fetch();
}
function newContact() {
var contact = contactsGrid.selection.getSelected()[0];
refreshGroupDropDown();
dojo.byId("edit_contact_real_id").value = "";
dojo.byId("edit_contact_id").value = "[NEW]";
dijit.byId("edit_contact_group").reset();
dijit.byId("edit_contact_first_name").reset();
dijit.byId("edit_contact_last_name").reset();
dijit.byId("edit_contact_email_address").reset();
dijit.byId("edit_contact_home_phone").reset();
dijit.byId("edit_contact_work_phone").reset();
dijit.byId("edit_contact_twitter").reset();
dijit.byId("edit_contact_facebook").reset();
dijit.byId("edit_contact_linkedin").reset();
dijit.byId("editContactDialog").set("title", "New Contact");
dijit.byId("editContactDialog").show();
}
function editContact() {
refreshGroupDropDown();
var contact = contactsGrid.selection.getSelected()[0];
dojo.byId("edit_contact_real_id").value = contact.id;
dojo.byId("edit_contact_id").value = contact.id;
dijit.byId("edit_contact_group").set("value", contact.group_id);
dojo.byId("edit_contact_first_name").value = contact.first_name;
dojo.byId("edit_contact_last_name").value = contact.last_name;
dojo.byId("edit_contact_email_address").value = contact.email_address;
dojo.byId("edit_contact_home_phone").value = contact.home_phone;
dojo.byId("edit_contact_work_phone").value = contact.work_phone;
dojo.byId("edit_contact_twitter").value = contact.twitter;
dojo.byId("edit_contact_facebook").value = contact.facebook;
dojo.byId("edit_contact_linkedin").value = contact.linkedin;
dijit.byId("editContactDialog").set("title", "Edit Contact");
dijit.byId("editContactDialog").show();
}
function moveContact() {
var contact = contactsGrid.selection.getSelected()[0];
var contactName = contact.first_name+" "+contact.last_name;
var groupName = contact.name;
dojo.byId("move_contact_id").value = contact.id;
dojo.byId("move_contact_name").value = contactName;
dojo.byId("move_contact_old").value = groupName;
dijit.byId("moveContactDialog").show();
}
|
Next, you need to connect these functions to the relevant menu options using dojo.connect (see Listing 22).
Listing 22. Connecting menu options to functions
dojo.connect(mnuNewGroup, "onClick", null, function(e) {
newGroupDialog.show();
});
dojo.connect(mnuRenameGroup, "onClick", null, renameGroup);
dojo.connect(ctxMnuRenameGroup, "onClick", null, renameGroup);
dojo.connect(mnuNewContact, "onClick", null, newContact);
dojo.connect(mnuEditContact, "onClick", null, editContact);
dojo.connect(ctxMnuEditContact, "onClick", null, editContact);
dojo.connect(mnuMoveContact, "onClick", null, moveContact);
dojo.connect(ctxMnuMoveContact, "onClick", null, moveContact);
|
In Listing 22, the New Group menu option is connected to an anonymous function, as it only has a single line to open the New Group dialog, so it doesn't really warrant a function of its own. Of course, if you prefer, you could put all of the functions used here in anonymous blocks like this, but I've separated them out, as it's easier to explain this way.
You can now reload the application and load any menu (except for the Delete options) and see the relevant dialog window open and load as appropriate. You'll probably notice right away that none of the buttons in these dialogs (except the hide "X" icon in the top right) actually do anything yet. You'll implement those features shortly. Figure 8 shows an example of the Move Contact window in action.
Figure 8. Move Contact dialog window working
In the previous section, you learned how to connect all menus to their relevant dialogs, except for the delete actions. That is because the delete actions do not have a dialog window. Instead, the application should prompt the user to confirm that they want to delete a group or contact, and if they click the appropriate button, it should proceed with the deletion.
Dojo's shortcomings are few and far between, but, unfortunately, one of them is an out-of-the-box confirmation dialog box. Luckily, it's quite simple to build a custom dialog that does just that. To create a confirmation dialog box, add the function shown in Listing 23 to the script.js file.
Listing 23. Function to create a confirmation dialog box
function confirmDialog(title, body, callbackFn) {
var theDialog = new dijit.Dialog({
id: 'confirmDialog',
title: title,
draggable: false,
onHide: function() {
theDialog.destroyRecursive();
}
});
var callback = function(mouseEvent) {
theDialog.hide();
theDialog.destroyRecursive(false);
var srcEl = mouseEvent.srcElement ? mouseEvent.srcElement : mouseEvent.target;
if(srcEl.innerHTML == "OK") callbackFn(true);
else callbackFn(false);
};
var message = dojo.create("p", {
style: {
marginTop: "5px"
},
innerHTML: body
});
var btnsDiv = dojo.create("div", {
style: {
textAlign: "center"
}
});
var okBtn = new dijit.form.Button({label: "OK", id: "confirmDialogOKButton",
onClick: callback });
var cancelBtn = new dijit.form.Button({label: "Cancel",
id: "confirmDialogCancelButton", onClick: callback });
theDialog.containerNode.appendChild(message);
theDialog.containerNode.appendChild(btnsDiv);
btnsDiv.appendChild(okBtn.domNode);
btnsDiv.appendChild(cancelBtn.domNode);
theDialog.show();
}
|
This function accepts three arguments: the title to display in the dialog, the message
to show, and the function that should be called back after the user clicks
OK or Cancel. This function is called with a true value if OK is pressed and a false value if Cancel is pressed.
You can now use this function to create confirmation dialogs for the Delete Group and
Delete Contact menu options. The results of deleting (and other CRUD operations you'll
see in the next section) cause the okDialog box to be
shown. So, let's get a handle to the message in that box now, while also getting the
OK button to hide the dialog (see Listing 24).
Listing 24. Use the OK button to hide the dialog
var okDialogMsg = dojo.byId("okDialogMessage");
dojo.connect(okDialogOK, "onClick", null, function(e) {
dijit.byId("okDialog").hide();
});
|
Listing 25 contains the code for the function that handles deleting groups.
Listing 25.
deleteGroup function
function deleteGroup() {
confirmDialog("Confirm delete", "Are you sure you wish to delete this group?
This will also delete any contacts in this group.<br />This action cannot
be undone.", function(btn) {
if(btn) {
var group = groupsTree.get("selectedItem");
var groupId = group.id;
var groupName = group.name;
dojo.xhrPost({
url: "data/delete_group.php",
handleAs: "json",
content: {
"group_id": groupId
},
load: function(data) {
if(data.success) {
groupsStore.fetch({
query: {"id": groupId.toString()},
onComplete: function (items, request) {
if(items) {
var len=items.length;
for(var i=0;i<len;i++) {
var item = items[i];
groupsStore.deleteItem(item);
}
}
},
queryOptions: { deep: true}
});
groupsStore.save();
groupsTree.set("selectedItem", groupsModel.root);
updateDataGrid(groupsModel.root);
okDialog.set("title","Group deleted successfully");
okDialogMsg.innerHTML = "The group <strong>"+groupName+"
</strong> was deleted successfully.";
okDialog.show();
}
else {
okDialog.set("title","Error deleting group");
okDialogMsg.innerHTML = data.error;
okDialog.show();
}
},
error: function(data) {
okDialog.set("title","Error deleting group");
okDialogMsg.innerHTML = data;
okDialog.show();
}
});
}
});
}
|
There's a bit of new ground to cover here, but the deleteContact function is very similar, so let's add that now too, and I'll discuss both in tandem.
Listing 26.
deleteContact function
function deleteContact() {
var confirmed = false;
confirmDialog("Confirm delete", "Are you sure you wish to delete this
contact?<br />This action cannot be undone.", function(btn) {
if(btn) {
var contact = contactsGrid.selection.getSelected()[0];
var contactId = contact.id;
var contactName = contact.first_name+" "+contact.last_name;
dojo.xhrPost({
url: "data/delete_contact.php",
handleAs: "json",
content: {
"contact_id": contactId
},
load: function(data) {
if(data.success) {
var treeSel = groupsTree.get("selectedItem");
var groupId;
if(treeSel) {
groupId = treeSel.id;
} else {
groupId = 0;
}
var url = contactsStore.url+"?group_id="+groupId;
var newStore = new dojo.data.ItemFileReadStore({url:url});
contactsGrid.setStore(newStore);
refreshGrid();
okDialog.set("title","Contact deleted successfully");
okDialogMsg.innerHTML = "The contact <strong>"
+contactName+"</strong> was deleted successfully.";
okDialog.show();
}
else {
okDialog.set("title","Error deleting contact");
okDialogMsg.innerHTML = data.error;
okDialog.show();
}
},
error: function(data) {
okDialog.set("title","Error deleting contact");
okDialogMsg.innerHTML = data;
okDialog.show();
}
});
}
});
}
|
Both of these functions use the new confirmation dialog function to ask the user to
confirm the deletion. Deleting a group will cascade delete any contacts in that group,
so the user is warned about that in the case of attempting to delete a group. If the
user confirms, the functions go to either the group's tree or contacts grid as required and gets the detail of the item that needs to be deleted. An Ajax dojo.xhrPost function call is then used to asynchronously call the relevant server-side PHP API. The JSON response received from this is then parsed and used to display a relevant success or error message.
Finally, you need to connect these functions to the relevant events (that is, the menu options). The code in Listing 27 does just that.
Listing 27. Connecting menu options to
delete functionsdojo.connect(mnuDeleteContact, "onClick", null, deleteContact); dojo.connect(ctxMnuDeleteContact, "onClick", null, deleteContact); dojo.connect(mnuDeleteGroup, "onClick", null, deleteGroup); dojo.connect(ctxMnuDeleteGroup, "onClick", null, deleteGroup); |
You can now save and reload your application. If you try to delete a contact, you should see the message shown in Figure 9.
Figure 9. Delete confirmation dialog box
Pressing OK will actually go ahead and delete the contact, and the following message will subsequently be displayed (see Figure 10).
Figure 10. Deletion successful message
You'll also notice that the relevant contact has been removed from the underlying grid. If you delete a group, you should see similar functionality (except that deleting a group also deletes all the contacts in that group).





