【问题标题】:Javascript issue with IE11IE11 的 Javascript 问题
【发布时间】:2016-03-17 21:38:57
【问题描述】:

我的应用程序在 IE9 之前运行良好,现在当我将它升级到 IE11 时它停止运行。这是一个示例 html 和 js。

问题

在第一次运行时,即。 加载时效果很好。但是当我选择 PDA 品牌时,第二个下拉菜单的所有选项都变为空白。

在控制台中,对象 clonedOptions 上出现脚本错误 Invalid Calling Object error

function dynamicSelect(id1, id2) {
  //alert("Everytime")
  // Browser and feature tests to see if there is enough W3C DOM support

  // Obtain references to both select boxes
  var sel1 = document.getElementById(id1);
  var sel2 = document.getElementById(id2);
  // Clone the dynamic select box
  var clone = sel2.cloneNode(true);
  // Obtain references to all cloned options
  var clonedOptions = clone.getElementsByTagName("option");
  // Onload init: call a generic function to display the related options in the dynamic select box
  refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
  // Onchange of the main select box: call a generic function to display the related options in the dynamic select box

  sel1.onchange = function() {
    refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
  };
}

function refreshDynamicSelectOptions(sel1, sel2, clonedOptions) {
  while (sel2.options.length) {
    sel2.remove(0);
  }

  //alert(sel1.options[sel1.selectedIndex].value)

  // Create regular expression objects for "select" and the value of the selected option of the main select box as class names
  var pattern1 = /( |^)(select)( |$)/;
  var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
  // Iterate through all cloned options
  //alert(clonedOptions.length);
  for (var i = 0; i < clonedOptions.length; i++) {
    // If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box

    if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
      // Clone the option from the hidden option pool and append it to the dynamic select box
      //alert("Did match")

      sel2.appendChild(clonedOptions[i].cloneNode(true));
      //alert(sel2.options[1]);
    }
  }
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

<head>
  <title>dynamic selectbox example</title>
  <script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>

<body>
  <form action="#">
    <div>
      <select id="pda-brand">
        <option value="select">Select PDA brand...</option>
        <option value="dell">Dell</option>
        <option value="hp">HP</option>
        <option value="palmone">PalmOne</option>
      </select>
      <select id="pda-type">
        <option class="select" value="select">Select PDA type...</option>
        <option class="dell" value="aximx30">Axim X30</option>
        <option class="dell" value="aximx50">Axim X50</option>
        <option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
        <option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
        <option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
        <option class="palmone" value="tungstene2">Tungsten E2</option>
        <option class="palmone" value="tungstent5">Tungsten T5</option>
        <option class="palmone" value="zire72">Zire 72</option>
      </select>
      <script type="text/javascript">
        window.onload = function(e) {
          dynamicSelect("pda-brand", "pda-type");
        }
      </script>
    </div>
  </form>
</body>

</html>

问题行

在下面的位置,对于 clonedOptions,我收到 Invalid Calling Object 错误。

for (var i = 0; i < clonedOptions.length; i++) {

【问题讨论】:

  • 我猜这是因为clonedOptions 中的一些options 不再存在,而您每次都使用clonedOptions 的原始版本
  • @Haketo,它适用于除 IE11 以外的所有浏览器
  • 是的,我阅读了代码,它应该可以工作,但我们正在谈论 IE ^^,抛出错误的行是什么?
  • @Haketo,查看我更新的问题
  • @Haketo 在 IE 更改列表指南中,我在 google 某处遇到说 IE 11 不再支持全局变量。

标签: javascript html internet-explorer cross-browser internet-explorer-11


【解决方案1】:

我认为问题在于您使用的是getElementsByTagName,它返回一个活动列表,这意味着如果一个项目从 DOM 中删除,它也会从列表中删除,因此有资格进行垃圾收集。见https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName

返回的列表是实时的,这意味着它会自动使用 DOM 树进行自我更新。

下面的例子将解释我的意思

var ps = document.body.getElementsByTagName('p');
var ps2 = document.body.querySelectorAll('p');
console.log(ps.length); // 3
document.body.removeChild(ps[0]);
console.log(ps.length);  // 2
console.log(ps2.length);  // 3
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>

我没有最新的IE,但是我有一种强烈的感觉,如果你使用clone.querySelectorAll("option"),你不会有同样的问题,因为节点不会有资格进行垃圾回收,因为它返回的列表是没有直播。

function dynamicSelect(id1, id2) {
  //alert("Everytime")
  // Browser and feature tests to see if there is enough W3C DOM support

  // Obtain references to both select boxes
  var sel1 = document.getElementById(id1);
  var sel2 = document.getElementById(id2);
  // Clone the dynamic select box
  var clone = sel2.cloneNode(true);
  // Obtain references to all cloned options
  var clonedOptions = clone.querySelectorAll("option");
  // Onload init: call a generic function to display the related options in the dynamic select box
  refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
  // Onchange of the main select box: call a generic function to display the related options in the dynamic select box

  sel1.onchange = function() {
    refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
  };
}

function refreshDynamicSelectOptions(sel1, sel2, clonedOptions) {
  while (sel2.options.length) {
    sel2.remove(0);
  }

  //alert(sel1.options[sel1.selectedIndex].value)

  // Create regular expression objects for "select" and the value of the selected option of the main select box as class names
  var pattern1 = /( |^)(select)( |$)/;
  var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
  // Iterate through all cloned options
  //alert(clonedOptions.length);
  for (var i = 0; i < clonedOptions.length; i++) {
    // If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box

    if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
      // Clone the option from the hidden option pool and append it to the dynamic select box
      //alert("Did match")

      sel2.appendChild(clonedOptions[i].cloneNode(true));
      //alert(sel2.options[1]);
    }
  }
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

<head>
  <title>dynamic selectbox example</title>
  <script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>

<body>
  <form action="#">
    <div>
      <select id="pda-brand">
        <option value="select">Select PDA brand...</option>
        <option value="dell">Dell</option>
        <option value="hp">HP</option>
        <option value="palmone">PalmOne</option>
      </select>
      <select id="pda-type">
        <option class="select" value="select">Select PDA type...</option>
        <option class="dell" value="aximx30">Axim X30</option>
        <option class="dell" value="aximx50">Axim X50</option>
        <option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
        <option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
        <option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
        <option class="palmone" value="tungstene2">Tungsten E2</option>
        <option class="palmone" value="tungstent5">Tungsten T5</option>
        <option class="palmone" value="zire72">Zire 72</option>
      </select>
      <script type="text/javascript">
        window.onload = function(e) {
          dynamicSelect("pda-brand", "pda-type");
        }
      </script>
    </div>
  </form>
</body>

</html>

【讨论】:

  • OP 在克隆上使用了getElementsByTagName ,“cloneNode() 返回的重复节点不是文档的一部分,直到它被添加到作为文档一部分的另一个节点”这是否意味着克隆节点上的getElementsByTagName 没有意义?
  • 他不会在任何地方从clone 中删除项目。知道为什么 clone 会被垃圾收集吗?
  • 没错,它似乎确实可以解决它...希望有人可以接受我开始并运行它,我必须开始:)
  • 感谢您解释实时列表和普通列表之间的区别。
  • @sabithpocker 这可能与克隆节点永远不会附加到 DOM 的事实有关?
【解决方案2】:

我可以在 IE-11 中使用它,请自行尝试。

据我了解,问题是:

var clone = sel2.cloneNode(true);
var clonedOptions = clone.getElementsByTagName("option");

clonedOptions 可能是对 clone 的子代的引用,标签名称为 option

  sel1.onchange = function() {
    refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
  };

在此函数中,有对clonedOptions 的引用,但没有对clone 的引用。所以clone 可能是garbageCollected,因为IE 找不到任何保留它的理由。 clonedOptions 保留对不存在的集合的引用。

你可以用你自己的方式更正,我只是通过clone而不是clonedOptions,它在IE11中对我有用

function dynamicSelect(id1, id2) {
  //alert("Everytime")
  // Browser and feature tests to see if there is enough W3C DOM support

  // Obtain references to both select boxes
  var sel1 = document.getElementById(id1);
  var sel2 = document.getElementById(id2);
  // Clone the dynamic select box      // Obtain references to all cloned options
  var clone = sel2.cloneNode(true);
  // Onload init: call a generic function to display the related options in the dynamic select box
  refreshDynamicSelectOptions(sel1, sel2, clone);
  // Onchange of the main select box: call a generic function to display the related options in the dynamic select box

  sel1.onchange = function() {
    refreshDynamicSelectOptions(sel1, sel2, clone);
  };
}

function refreshDynamicSelectOptions(sel1, sel2, clone) {
  var clonedOptions = clone.getElementsByTagName("option");
  while (sel2.options.length) {
    sel2.remove(0);
  }

  //alert(sel1.options[sel1.selectedIndex].value)

  // Create regular expression objects for "select" and the value of the selected option of the main select box as class names
  var pattern1 = /( |^)(select)( |$)/;
  var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
  // Iterate through all cloned options
  //alert(clonedOptions.length);
  for (var i = 0; i < clonedOptions.length; i++) {
    // If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box

    if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
      // Clone the option from the hidden option pool and append it to the dynamic select box
      //alert("Did match")

      sel2.appendChild(clonedOptions[i].cloneNode(true));
      //alert(sel2.options[1]);
    }
  }
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">

<head>
  <title>dynamic selectbox example</title>
  <script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>

<body>
  <form action="#">
    <div>
      <select id="pda-brand">
        <option value="select">Select PDA brand...</option>
        <option value="dell">Dell</option>
        <option value="hp">HP</option>
        <option value="palmone">PalmOne</option>
      </select>
      <select id="pda-type">
        <option class="select" value="select">Select PDA type...</option>
        <option class="dell" value="aximx30">Axim X30</option>
        <option class="dell" value="aximx50">Axim X50</option>
        <option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
        <option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
        <option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
        <option class="palmone" value="tungstene2">Tungsten E2</option>
        <option class="palmone" value="tungstent5">Tungsten T5</option>
        <option class="palmone" value="zire72">Zire 72</option>
      </select>
      <script type="text/javascript">
        window.onload = function(e) {
          dynamicSelect("pda-brand", "pda-type");
        }
      </script>
    </div>
  </form>
</body>

</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 2014-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多