I have built a common error dialog function to get a common look and feel for my dialogs. I call that function from within the $.ajaxSetup.error
function without issue. I have one button added through the call on the dialog. My button will close the dialog and the X in the corner will close the window when called from the ajaxSetup.error
function.
If I attempt to call this same function from within a catch block within my JS (NOT AN AJAX CALL) the dialog opens without issue but when I click my button to close the dialog I get the following error:
0x800a138f - JavaScript runtime error: Unable to get property '_focusTabbable' of undefined or null reference
Here is the code that generates my dialog:
function __renderDialogOK(data) {
// This call renders the div to be displayed within
// the dialog.
var divMessage = __renderDialogBase(data);
$(divMessage).dialog(
{
width: __getDialogWidth(),
resizeable: false,
modal: true,
hide: true,
show: true,
buttons: [
{
text: "OK",
click: function (e) {
e.preventDefault();
$(this).dialog("close");
return false;
}
}
],
open: function (e) {
$(this).parent().find("button:eq(1)").addClass('ui-state-default');
$(this).parent().find("button:eq(1)").focus();
$(this).on("keydown", function (event) {
if (parseInt(event.keyCode) === 13) {
$(this).parent()
.find("button:eq(1)").trigger("click");
return false;
}
if (event.keyCode == 27) {
$(this).parent()
.find("button:eq(1)").trigger("click");
return false;
}
});
},
close: function (e) {
$(this).off("keydown");
}
}
);
}
As you can see in my button I attempt to close the dialog using $(this)
. I have also tried using a variable outside of the function (global) to store the context returned by the call to $(divMessage).dialog(
.
This appears to only be happening within IE11 which is unfortunate for me since my customer has that as their current corporate standard. So finally my question(s).
Is all context lost when you enter a Catch block within JavaScript? Has this issue been exposed previously and I am just not seeing the threads? I have read many of the other threads regarding this similar error message but they don't seem to be as specific as my instance and many of them seem to be because the dialog is not initiated yet. Mine is. The dialog is on the screen. I just can't close it with my button.
Expanding on my comment, I would examine this:
open: function (e) {
$(this).parent().find("button:eq(1)").addClass('ui-state-default');
$(this).parent().find("button:eq(1)").focus();
$(this).on("keydown", function (event) {
if (parseInt(event.keyCode) === 13) {
$(this).parent()
.find("button:eq(1)").trigger("click");
return false;
}
if (event.keyCode == 27) {
$(this).parent()
.find("button:eq(1)").trigger("click");
return false;
}
});
}
In most cases, the value of
this
is determined by how a function is called. It can't be set by assignment during execution, and it may be different each time the function is called. ES5 introduced thebind
method to set the value of a function'sthis
regardless of how it's called, and ES2015 introducedarrow
functions which do provide their ownthis
binding (it remains the this value of the enclosing lexical context).
So, in the open
callback, $(this)
refers to the object that called open
. It is sort of similar to $(e.target)
. So when we then bind a function via .on()
to the keydown
event, $(this)
is no longer the open
callback. It is a reference to the keydown
callback.
To avoid confusion you can do different things. Here is what I would try first:
open: function (e) {
var $me = $(this);
var $parent = $(this).parent();
$parent.find("button:eq(1)").addClass('ui-state-default');
$parent.find("button:eq(1)").focus();
$me.on("keydown", function (event) {
if (parseInt(event.keyCode) === 13) {
$parent
.find("button:eq(1)").trigger("click");
return false;
}
if (event.keyCode == 27) {
$parent
.find("button:eq(1)").trigger("click");
return false;
}
});
}
This will help retain the proper reference to the proper objects.
User contributions licensed under CC BY-SA 3.0