Reputation: 4104
TL:DR I have a textbox which has an OnBlur
event. This event selects an item in a combobox and sets it to read only. If the textbox has focus and then I click on the combobox, I can expand the drop down menu and select an item. If the textbox has focus and I press Tab once to select the combobox, the javascript in the OnBlur
event successfully selects the item and disables the control. This only happens in IE. How can I fix this?
And furthermore, setting a breakpoint in the OnBlur
code causes the software to behave correctly regardless of whether I use the mouse or Tab, but that could be due to the browser window trading focus with my debugger.
I have an ASP.NET web application using MVC, RazorViews, and uses jquery + Telerik's Kendo UI controls.
View file code with the textbox:
<td colspan="2" class="qicolumn-width-88 textalign-right">
@(Html.Kendo().TextBoxFor(m => m.V14_Adm_C0500).HtmlAttributes(new
{
id = "cmbV14_C0500",
class = "width-85",
tabIndex = "11",
style = "width:149px",
onfocus = "FocusC0500()",
onblur = "BlurC0500(false);FinalizeColor(this);"
}))
</td>
The form has an array of textbox and drop down menus on it. Depending on the values they enter for C0100 - C0400, the software will either automatically determine a value for C0500 (the textbox defined above) and disable it, or enable it for user input. When the user inputs a value and then navigates out of this textbox, a method fires and updates the data source of the combo box C0600.
This is handled by the following lengthy javascript method:
function BlurC0500(isFromDropDown)
{
//Get the drop down menu object that C0500 manpiulates.
var cmb = $("#cmbV14_C0600").data("kendoDropDownList");
//Get the value from C0500. It should be a number between 0 - 10, 99, or a hyphen.
var val = $("#cmbV14_C0500").val();
if (val == '99' || val == '-')
{
cmb.select(0); //select '0 - No'
cmb.readonly(true); // disable the control
cmb.wrapper.find('.k-input').css('background', '#DDDDDD'); // set bg to gray to indicate its RO status
SetTabIndexVals("cmbV14_C0600", "DROPDOWN", -1); //Set tab index for control
}
else
{
if (val != sumC0100C0400 && sumC0100C0400 > 0 && isFromDropDown != true)
{
//Show an error to the user if the value they entered into C0500
// does not equal the sum of the values entered in C0100 - C0400, if that sum is greater than 0.
}
//Create new data source to assign to C0600
var ZeroToOneAndDashData = [{ "Text": "0 - No", "Value": "0" }, { "Text": "1 - Yes", "Value": "1" }, { "Text": "-", "Value": "-" }];
cmb.dataSource.data(ZeroToOneAndDashData);
//If the value they entered IS equal to the sum of C0100 - C0400
if (val == sumC0100C0400)
{
//Mantis#16646 Changes : Added below condition to set C0600 field empty and disable
if ($("#cmbV14_C0100").val() == "" || $("#cmbV14_C0100").val() == '0')
{
//Select the "0 - No" option for C0600 when C0100 is empty / zero,
// then set the readonly state + tabindex + bg color...
}
else if (val == "" && $("#cmbV14_C0100").val() == '1')
{
//Select "0 - No" option for C0600 when C0100 is 1
// then set different readonly + tabindex + bgcolor values
}
else
{
//Select "1 - Yes" option for C0600
// then assign yet a different set of values for readonly / tabindex / bgcolor
}
}
else //executes when the value they entered IS NOT equal to the sum of C0100 - C0400
{
//Select "0 - No" option for C0600 when C0100 is 1
// then set different readonly + tabindex + bgcolor values
}
//If a change in C0100 - C0400 values prompted a change in C0500 + C0600's behavior
// we call OnChangeC0600.
// This changes the values / readonly states of yet another set of controls
if (isFromDropDown === false)
OnChangeC0600(false);
}
var chkBIMval = $("#cmbV14_C0500").val().trim();
//Prepends a 0 to the value entered in C0500 if the value is greater than 0 and less than 10
// because the value 99 valid, we want the value to always be two characters long. "06" instead of simply "6".
if (chkBIMval != '' && chkBIMval != '01' && chkBIMval != '02' && chkBIMval != '03' && chkBIMval != '04' && chkBIMval != '05' && chkBIMval != '06' && chkBIMval != '07' && chkBIMval != '08' && chkBIMval != '09')
{
if ($("#cmbV14_C0500").val() > 0 && $("#cmbV14_C0500").val() < 10)
{
$("#cmbV14_C0500").val('0' + val);
}
}
}
And here's the function for setting tab indices:
function SetTabIndexVals(controlID, controltype, tabIndex)
{
try
{
var _eTabIndex;
//If we're assigning tabIndex = -1, get the current tab index
// and store it into a custom attribute to be re-assigned later
if (tabIndex == -1)
{
if (controltype == 'DROPDOWN')
{
_eTabIndex = $("span[aria-owns=" + controlID + "_listbox]").attr('tabindex');
$("span[aria-owns=" + controlID + "_listbox]").attr('Oldtabindex', _eTabIndex);
$("span[aria-owns=" + controlID + "_listbox]").attr('tabindex', tabIndex);
}
else if (controltype == 'TEXTBOX')
{
_eTabIndex = $("#" + controlID).attr('tabindex');
if (_eTabIndex > 0)
{
$("#" + controlID).attr('Oldtabindex', _eTabIndex);
$("#" + controlID).attr('tabindex', tabIndex);
}
}
}
else
{
if (controltype == 'DROPDOWN')
{
_eTabIndex = $("span[aria-owns=" + controlID + "_listbox]").attr('Oldtabindex');
if (_eTabIndex == undefined || _eTabIndex < 0 || _eTabIndex == null)
_eTabIndex = $("span[aria-owns=" + controlID + "_listbox]").attr('tabindex');
$("span[aria-owns=" + controlID + "_listbox]").attr('Oldtabindex', _eTabIndex);
$("span[aria-owns=" + controlID + "_listbox]").attr('tabindex', _eTabIndex);
}
else if (controltype == 'TEXTBOX')
{
_eTabIndex = $("#" + controlID).attr('Oldtabindex');
if (_eTabIndex == undefined || _eTabIndex < 0 || _eTabIndex == null)
_eTabIndex = $("#" + controlID).attr('tabindex');
$("#" + controlID).attr('Oldtabindex', _eTabIndex);
$("#" + controlID).attr('tabindex', _eTabIndex);
}
}
} catch (err)
{
logError(err, arguments.callee.trace());
}
}
Using Internet Explorer (v11.0.9600.18537CO), the software behaves incorrectly:
0 - No
, 1 - Yes
, or -
The drop down menu should NOT be expandable. The software should select 0 - No
and disable it.
If I perform the same steps in Chrome (v55.0.2883.87) or Firefox (v51.0.1) it behaves correctly when I use the mouse to click on the C0600 combox. It immediately becomes disabled and selects 0 - No
, as described above.
If I perform the same steps but use the Tab key instead of the mouse, it works correctly in IE, Chrome and Firefox.
I'm guessing maybe IE's JS engine is a little slower than FF / Chrome which allows the user to do things they shouldn't, but I have no idea how to confirm this, or how to "deal" with it.
How can I make it so that the user is not able to click into a control which gets disabled by the one they're leaving in Internet Explorer?
According to MSDN
The onblur event fires on the original object before the onfocus or onclick event fires on the object that is receiving focus.
But that is clearly not the case in my situation. I see it also mentions that a control must have a tab index. When I set the combobox to ReadOnly, I assign tabIndex = -1
, but it seems like negatives should be fine. If I assign it a non-negative number, then this read-only control will get focus instead of the next control which is NOT read-only.
I also tried just immediately setting cmb.readonly(true)
as the very first action in the JS, hoping maybe I just need to disable it sooner, but this did not fix the problem.
EDIT: I also just tried removing the onblur
attribute from the razor code in my view. Instead, I added this:
$("#cmbV14_C0500").focusout(function ()
{
BlurC0500(false);FinalizeColor(this);
});
To the $(document).ready(function () { }
script at the end of my view. Per the jquery documentation:
The
focusout
event is sent to an element when it, or any element inside of it, loses focus. This is distinct from theblur
event in that it supports detecting the loss of focus on descendant elements (in other words, it supports event bubbling).
However it resulted in the exact same (incorrect) behavior.
Upvotes: 2
Views: 905
Reputation: 2190
I did some tests and I could reproduce the issue in IE, but looks like a bug since this only happens in IE. It is definitely a Kendo issue. Note that you're not even dealing with an actual select. Kendo can do whatever it wants with the events regardless of how the browser triggers them.
You could do cmb.close()
to force it to close the dropdown if it opened.
Upvotes: 1