由于鼠标在 IE 中不起作用,OnBlur 和失去焦点

OnBlur and losing focus due to the mouse isn't working in IE

TL:DR 我有一个包含 OnBlur 事件的文本框。此事件 select 组合框中的一个项目并将其设置为只读。如果文本框有焦点,然后我单击组合框,我可以展开下拉菜单和 select 一个项目。如果文本框有焦点并且我按 Tab 一次到 select 组合框,OnBlur 事件中的 javascript 成功 selects该项目并禁用控件。这只发生在 IE 中。我该如何解决这个问题?

此外,在 OnBlur 代码中设置断点会导致软件正常运行,无论我是使用鼠标还是 Tab,但这可能是由于到浏览器 window 与我的调试器交换焦点。


我有一个使用 MVC、RazorViews 的 ASP.NET 网络应用程序,并使用 jquery + Telerik 的 Kendo UI 控件。

使用文本框查看文件代码:

<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>

表单有一组文本框和下拉菜单。根据他们为 C0100 - C0400 输入的值,软件将自动确定 C0500(上面定义的文本框)的值并禁用它,或者为用户输入启用它。当用户输入一个值然后导航出此文本框时,将触发一个方法并更新组合框 C0600 的数据源。

这由以下冗长的 javascript 方法处理:

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);
        }
    }
}

这里是设置标签索引的函数:

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());
    }
}

使用 Internet Explorer (v11.0.9600.18537CO),软件行为不正确:

下拉菜单不应展开。该软件应该 select 0 - No 并禁用它。

如果我在 Chrome (v55.0.2883.87) 或 Firefox (v51.0.1) 中执行相同的步骤,当我使用鼠标单击 C0600 组合框时它会正常运行。如上所述,它立即被禁用并且 selects 0 - No

如果我执行相同的步骤但使用 Tab 键而不是鼠标,它在 IE、Chrome 和 Firefox 中可以正常工作。

我猜也许 IE 的 JS 引擎比 FF 慢一点 / Chrome 这允许用户做他们不应该做的事情,但我不知道如何确认这一点,或者如何"deal"用它。

我怎样才能让用户无法点击一个被他们在 Internet Explorer 中离开的控件禁用的控件?

根据MSDN

The onblur event fires on the original object before the onfocus or onclick event fires on the object that is receiving focus.

但我的情况显然不是这样。我看到它还提到控件必须有一个选项卡索引。当我将组合框设置为 ReadOnly 时,我分配 tabIndex = -1,但似乎底片应该没问题。如果我给它分配一个非负数,那么这个只读控件将获得焦点,而不是下一个非只读控件。

我也尝试过立即将 cmb.readonly(true) 设置为 JS 中的第一个操作,希望我可能只需要尽快禁用它,但这并没有解决问题。

编辑:我也只是尝试从我看来的剃须刀代码中删除 onblur 属性。相反,我添加了这个:

    $("#cmbV14_C0500").focusout(function ()
    {
        BlurC0500(false);FinalizeColor(this);
    });

到我认为最后的 $(document).ready(function () { } 脚本。根据 jquery documentation:

The focusout event is sent to an element when it, or any element inside of it, loses focus. This is distinct from the blur event in that it supports detecting the loss of focus on descendant elements (in other words, it supports event bubbling).

然而,它导致了完全相同(不正确)的行为。

我做了一些测试,我可以在 IE 中重现该问题,但看起来像是一个错误,因为这只发生在 IE 中。这绝对是一个 Kendo 问题。请注意,您甚至没有处理实际的 select。 Kendo 可以对事件做任何想做的事,而不管浏览器如何触发它们。

您可以cmb.close()强制关闭打开的下拉菜单。