在 Mobile Safari 下拉列表项选择框上使用“下一步"时,选择/下拉的 onchange() JS 事件的奇怪行为 [英] Strange behavior of select/dropdown's onchange() JS event when using 'Next' on Mobile Safari Dropdown list item select box

查看:17
本文介绍了在 Mobile Safari 下拉列表项选择框上使用“下一步"时,选择/下拉的 onchange() JS 事件的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这很难说清楚,我是移动网络开发的新手,所以请耐心等待:

This is a hard one to articulate and I am new to mobile web development so please bear with me:

在我的网页上,我有 3 个嵌套下拉列表(区域、城镇、街道).

On my webpage, I have 3 Nested dropdown lists (Area, Town, Street).

嵌套,当其上方下拉列表中的选择更改时,每个下拉列表的项目都会被修改.例如选择一个区域会改变城镇街道列表,选择一个城镇会改变街道em> 列表.

Nested as in, each dropdown's items are modified when the selection in the dropdown above it changes. e.g selecting an Area changes the Town and Street lists and selecting a Town changes the Street list.

我在下拉列表的 onchange() javascript 事件中使用 XMLHTTPRequests 来获取和填充其他下拉列表.这适用于 Android 和桌面浏览器.

I use XMLHTTPRequests in the onchange() javascript event of the dropdowns to fetch and populate the other downdowns. This works fine on Android and Desktop browsers.

在 Mobile Safari 上,当触摸下拉菜单时,会显示一个列表,用户可以在其中选择项目.此外,选择框还有上一个/下一个/自动填充/完成"按钮,可以导航到其他表单元素.

On Mobile Safari, when a drowdown is touched, a list is shown where the user can select items. In addition the selection box has the "Previous/Next/Autofill/Done" buttons to navigate to other form elements.

因此用户触摸第一个下拉菜单,选择一个值并按下 Next 按钮.这会导致两个问题:

So the user touches the first dropdown, selects a value and presses the Next button. This causes two problems:

第一,在这个动作中,第一个下拉菜单的 oncange() 事件没有被可靠地触发!有时它会触发有时不会.

First, On this action the first dropdown's oncange() event is not triggered reliably! Sometimes it fires sometimes not.

如果在选择一个区域后,用户触摸网页上的其他地方或按下完成"按钮,则 onchange() 正常触发,城镇和街道正常填充.

If after selecting an Area, the user touches somewhere else on the webpage or presses the "Done" button then the onchange() is fired normally and the Towns and Streets are populated normally.

第二,按下下一步"按钮时进入焦点的元素是下拉列表,其元素在获取后需要更改.当上一个下拉菜单的 onchange() 被触发时,要么列表没有更新,要么选择框中的项目变成蓝色,并且所有项目都有一个刻度线,表明它们都被选中了..

Second, the element that comes into focus when pressing then "Next" button is the dropdown whos elements need to be changed after being fetched. When the onchange() of the previous dropdown does get fired then, either the list is no updated or the items in the select box turn blue and all of them have a tick mark showing that they are all selected..

据我所知,如果我可以禁用选择框中的下一个/上一个"按钮,或者以某种方式修复 onchange() 的触发方式,并且在焦点下拉列表中的下一个列表项重新填充时,问题将得到解决重点.

From what i can tell the problem would be solved if i can disable the Next/Previous buttons in the selection box or somehow fix how the onchange() is fired and the next in focus dropdown's list items are repopulated while it is in focus.

这是代码(简化):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no" />

    <title></title>
</head>
<body onload="AppStart();">
    <form action="#">
    Area:
    <select id="ddlArea">
        <option value="">-- Select Area -- </option>
        <option value="1">Area 1</option>
        <option value="2">Area 2</option>
        <option value="3">Area 3</option>
        <option value="4">Area 4</option>
        <option value="5">Area 5</option>
    </select>
    <br />
    Town:
    <select id="ddlTown">
        <option value="">Please wait ...</option>
    </select>
    <br />
    Street:
    <select id="ddlStreet">
        <option value="">-- Select Area or Town -- </option>
    </select>
    <br />
    Unit:
    <select id="ddlUnit">
        <option value="">-- No Street Selected -- </option>
    </select>

    <script type="text/javascript">

        var ddlArea, ddlTown, ddlStreet, ddlUnit;
        function AppStart() {
            ddlArea = document.getElementById("ddlArea");
            ddlTown = document.getElementById("ddlTown");
            ddlStreet = document.getElementById("ddlStreet");
            ddlUnit = document.getElementById("ddlUnit");

            ddlArea.onchange = areaChanged;
            ddlTown.onchange = townChanged;
            ddlStreet.onchange = streetChanged;

            setTimeout(function() { updateTown(""); }, 250);
        }

        var areaId = "", townId = "", streetId = "", unitId = "";
        function areaChanged(e) {
            areaId = ddlArea.options[ddlArea.selectedIndex].value
            ddlClear(ddlTown, createOption("Please Wait...", ""));
            ddlClear(ddlStreet, createOption("Please Wait...", ""));
            ddlClear(ddlUnit, createOption("-- No Street Selected --", ""));
            setTimeout(function() { updateTown(areaId); }, 500);
            setTimeout(function() { updateStreet(areaId, ""); }, 700);
        }

        function townChanged(e) {
            townId = ddlTown.options[ddlTown.selectedIndex].value
            ddlClear(ddlStreet, createOption("Please Wait...", ""));
            ddlClear(ddlUnit, createOption("-- No Street Selected --", ""));
            setTimeout(function() { updateStreet(areaId, townId); }, 400);
        }

        function streetChanged(e) {
            streetId = ddlStreet.options[ddlStreet.selectedIndex].value
            ddlClear(ddlUnit, createOption("Please Wait...", ""));
            setTimeout(function() { updateUnit(streetId); }, 600);
        }

        function updateTown(areaID) {
            ddlClear(ddlTown, createOption("-- Select Town --", ""));
            var items = isNaN(parseInt(areaID)) ? 10 : parseInt(areaID);
            if (areaID == "") areaID = "ALL";
            for (var i = 0; i < items; i++) {
                ddlTown.appendChild(createOption("Town " + (i+1) + ", Area " + areaID, i));
            }
        }

        function updateStreet(areaID, townID) {
            ddlClear(ddlStreet, createOption("-- Select Street --", ""));
            var items1 = isNaN(parseInt(areaID)) ? 10 : parseInt(areaID);
            var items2 = isNaN(parseInt(townID)) ? 10 : parseInt(townID);
            var items = items1 + items2;
            if (areaID == "") areaID = "ALL";
            if (townID = "") townId = "ALL";
            for (var i = 0; i < items; i++) {
                ddlStreet.appendChild(createOption("Street " + (i + 1) + ", Area " + areaID + ", Town " + townID, i));
            }
        }

        function updateUnit(streetID) {
            ddlClear(ddlUnit, createOption("-- Select Unit --", ""));
            var items = isNaN(parseInt(streetID)) ? 10 : parseInt(streetID);
            if (streetID == "") streetID = "ALL";
            for (var i = 0; i < items; i++) {
                ddlUnit.appendChild(createOption("Unit " + (i + 1) + ", Street " + streetID, i));
            }
        }

        function ddlClear(Dropdown, option) {
            while (Dropdown.options.length > 0) {
                try { Dropdown.options[0] = null; } catch (e) { };
            }
            if (option != null) {
                Dropdown.appendChild(option);
            }
        }

        function createOption(text, value) {
            var oOption = document.createElement("OPTION");
            oOption.innerHTML = text;
            oOption.value = value;
            return oOption;
        }

    </script>

    </form>
</body>
</html>

帮助.:/

推荐答案

我在我的网站上遇到了同样的问题.我能够通过手动轮询选择控件上的 selectedIndex 属性来修复它.这样它就会在您检查"列表中的项目时立即触发.这是我为此编写的 jQuery 插件:

I had the same problem on my site. I was able to fix it by manually polling the selectedIndex property on the select control. That way it fires as soon as you "check" the item in the list. Here's a jQuery plugin I wrote to do this:

$.fn.quickChange = function(handler) {
    return this.each(function() {
        var self = this;
        self.qcindex = self.selectedIndex;
        var interval;
        function handleChange() {
            if (self.selectedIndex != self.qcindex) {
                self.qcindex = self.selectedIndex;
                handler.apply(self);
            }
        }
        $(self).focus(function() {
            interval = setInterval(handleChange, 100);
        }).blur(function() { window.clearInterval(interval); })
        .change(handleChange); //also wire the change event in case the interval technique isn't supported (chrome on android)
    });
};

您可以像使用change"事件一样使用它.例如:

You use it just like you would use the "change" event. For instance:

$("#mySelect1").quickChange(function() { 
    var currVal = $(this).val();
    //populate mySelect2
});

编辑:当您点击选择一个新值时,Android 不会聚焦选择,但它也没有与 iphone 相同的问题.因此,通过连接旧的 change 事件来修复它.

Edit: Android does not focus the select when you tap it to select a new value, but it also does not have the same problem that iphone does. So fix it by also wiring the old change event.

这篇关于在 Mobile Safari 下拉列表项选择框上使用“下一步"时,选择/下拉的 onchange() JS 事件的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆