I have a fully ajaxed website, which uses jQuery’s $.get calls to fetch the central content of the website upon header clicks.
One of the “screens” (views, actually, using Zend) has a hidden div which is “dialoged” when a user clicks a certain button. This is what happens to me:
- I get to the desired screen, and click the open dialog button.
- Dialog opens fine. Closing and reopening works as expected.
- I go to another screen (mind you, this is ajax, which simply replaces the main content with new content – the hidden div is inside this content, however, and gets replaced along with the main content)
- I come back to the previous screen (still ajaxing), and click the open dialog button again. Now all of a sudden, there are two of those hidden divs, both with the identical ID (I can see that if I do a console.log($(“div#hiddenDiv”).length); ) and they are both spawned in dialog form – I have them on top of each other.
The dialogs get duplicated for as many times as I redo this. If I go to another screen, come back, and open dialog again – I get 3, etc.
I took a lot of precautions – I empty the memory at every ajax click, setting all variables I have nothing to do with anymore to null. I also take care to replace the entire content, the hidden divs as well, on every new ajax call, i.e. screen-transition. I checked and made sure that the function which summons the dialog isn’t called more than once – it simply dupes the dialog upon returning to the screen which contains it by default, and I have no idea why. Mind you – no other element is duped. Only this hidden soon-to-be-dialog div.
Also worth noting is the fact that the duping process never begins until I open the dialog for the first time. From that moment on, every ajax [departure/return/dialog-opening]-scheme dupes the invisible div.
Does anyone have any idea why this is happening?
Edit: Code example:
// This causes the screen change when it detects a hash change
// ... stuff ...
if(window.location.hash){
ajaxData(newhash);
}
// ... stuff ...
// This causes the actual change of on-screen content (i.e. this is the ajax call)
function ajaxData(value) {
// ... stuff ...
$.ajax({
url: "/siteexample/"+value,
type: "GET",
mode: "abort",
dataType: type,
success: function(data){
$("#main_content").html(data); // the hidden div is always inside this "data", so it always gets removed when a new screen loads
loaderdisplay('hide');
// Clean Memory
data = null;
},
data: ({ajax : 'Y'})
});
// ... stuff ....
// And finally, this is the part that summons the dialog
function summonDialog() {
console.log("here"); // this shows up only once, so I know this function is not called multiple times.
var dialogBox = $("div#new_window"); // this is the infamous div
$(dialogBox).dialog({
modal: true,
title: "Some title",
resizable: false,
zIndex: 22000,
width: 800,
buttons: {
"Save": function(){
// some function, ends with:
$(dialogBox).dialog("close"); // destroy doesn't change anything
dialogBox = null;
},
Cancel: function(){
$(this).dialog("close"); // destroy doesn't change anything
dialogBox = null;
}
}
});
}
So the sequence of events is:
1. ajaxData to the location where the div is.
2. ajaxData away from it.
3. ajaxData back, and open dialog, everything fine.
4. ajaxData away from it.
5. ajaxData back and open dialog, duped.
Rinse and repeat, from now on they’re getting duped.
Edit2:
I was able to temporarily hack this into a fix with this in the summonDialog function:
var dialogBox = $("div#new_window");
var usableDialog = dialogBox[0];
$(dialogBox).remove();
$(usableDialog).dialog({
// ... dialog code as usual ...
But I don’t like the solution much. Marc’s explanation makes sense, but since I have many different hidden divs with the potential to become dialogs scattered across many different views, removing each one in such a way would be tedious, since they tend to have different context-appropriate IDs and removing by “ui-dialog-content” class (which all divs get once they’re dialog-opened) could produce some issues in other parts of the site, since it’s a too general scope.
I believe the div that is the dialog will be attached and hidden on the body. Thus, when you replace the
#main_contenthtml, you’re not really removing it. I would recommend removing the div and re-enabling the.dialogplugin on eachhtml(data)reload.Something like this:
And easy way to test this is to simply
console.log($("#new_window").length);when you get dupes.