13

這是一個很難闡明,我是移動web開發的新手,所以請耐心等待:移動Safari上使用'下一個'時,選擇/下拉的onchange()JS事件的奇怪行爲下拉列表項選擇框

在我的網頁,我有3名嵌套的下拉列表(區,鎮,街道)。

嵌套如,當在下拉選擇上述它改變每個下拉的項目將被修改。 e.g選擇改變列表和選擇改變名單。

我在下拉菜單的onchange()javascript事件中使用XMLHTTPRequests來獲取並填充其他下拉菜單。這適用於Android和桌面瀏覽器。

在移動Safari上,當觸摸下降時,會顯示一個列表,用戶可以選擇項目。此外,選擇框具有「上一個/下一個/自動填充/完成」按鈕以導航到其他表單元素。

因此,用戶觸摸第一下拉,選擇一個值,並按下Next按鈕。這會導致兩個問題:

第一個,在此操作上,第一個下拉的oncange()事件不會被可靠地觸發!有時它有時會失火。

如果選擇一個區域後,用戶觸摸網頁上的其他地方或按下「完成」按鈕,然後onchange()正常啓動,城鎮和街道正常填充。

第二個,當按下然後「下一步」按鈕進入焦點的元素是下拉whos元素被取出後需要更改。當先前的下拉列表的的onchange()不被解僱的話,要麼名單沒有更新,或者在選擇框中的項目變爲藍色和所有的人都表示,他們都選擇了刻度..

從如果我可以禁用選擇框中的Next/Previous按鈕,或者以某種方式修復onchange()如何觸發,並且下一個焦點下拉列表項在重點時重新填充,我可以告訴問題將得到解決。

下面是代碼(簡化):

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

幫助。 :/

回答

28

我在我的網站上遇到了同樣的問題。我能夠通過在選擇控件上手動輪詢selectedIndex屬性來修復它。這樣,只要你「檢查」列表中的項目,它就會啓動。這裏有一個jQuery插件,我寫這樣做:

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

您可以使用它就像你會用「改變」事件。例如:

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

編輯:Android不集中的選擇,當你點擊它選擇一個新的價值,但它也沒有說iphone做了同樣的問題。所以通過連接舊的change事件來修復它。

+0

感謝您的支持。我通過調用下一個下拉列表中的blur()來解決此問題,當第一個選擇被更改並返回XMLHttpRequest數據時,選擇框消失,用戶必須觸摸第二個下拉訪問它,這會導致項目刷新列表..這是一個黑客,我不喜歡太多.. – 2011-09-03 05:10:56

+0

這是一個很好的解決方案,它確實解決了Safari移動Web瀏覽器(這是一階失敗仍然存在於iOS 5上)。但它似乎留下了另一個次要影響。現在,「微調器」正在填充,但在點擊「下一個」或「完成」後,實際下拉似乎不會隨着選擇而更新,也不會進行註冊。任何見解?此外,修復似乎暫時破壞了Android的界面版本。但它然後工作。 – iJames 2011-10-13 20:12:47

+0

我發佈了這個之後發現了android問題。查看我的編輯和上面的新代碼以獲得修復。你能爲第一個問題創建一個jsfiddle嗎? – InvisibleBacon 2011-10-14 19:33:13