Problema de Javascript com o IE11

A minha aplicação estava a funcionar bem até ao ano 9, agora deixou de funcionar quando a alterei para o ano 11. Aqui está uma amostra de html e js .

Edição

na primeira corrida ie. Em carga funciona bem. Mas quando seleccionar PDA brand, as opções da segunda queda ficaram em branco.

na consola houve um erro de script Invalid Calling Object error no objecto clonedOptions.

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>

LINHA DE EMISSÃO

em baixo de loc, para clonedopções eu sou a obter um erro de chamada inválido do objecto de chamada.

for (var i = 0; i < clonedOptions.length; i++) {
Author: Amit Ranjan, 2016-03-17

2 answers

Posso pôr isto a funcionar no IE-11, por favor, tente sozinho. Pelo que sei, a questão é:
var clone = sel2.cloneNode(true);
var clonedOptions = clone.getElementsByTagName("option");

clonedOptions é provavelmente uma referência a crianças de clone com nome de marca option

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

Nesta função existe uma referência a clonedOptions, mas nenhuma referência a clone. Então clone é provavelmente garbageCollected porque IE não conseguiu encontrar nenhuma razão para mantê-lo. Mantém uma referência a uma colecção que não existe.

Podes corrigir à tua maneira, Eu estou apenas passando em vez de clonedOptions e funciona para mim em 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>
 1
Author: sabithpocker, 2016-03-17 13:14:28

Eu acho que o problema é que você está usando getElementsByTagName que retorna um live lista, o que significa que, se um item é removido do DOM, ele também é removido da lista e, portanto, elegíveis para a coleta de lixo. Ver https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName

A lista devolvida está ao vivo, o que significa que se actualiza com a árvore DOM automaticamente.

O seguinte exemplo explicará o que eu média

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>

Eu Não tenho o último IE, mas tenho um forte sentimento de que se você usar clone.querySelectorAll("option"), Você não terá o mesmo problema porque os nós não serão elegíveis para a coleta de lixo, uma vez que a lista que ele retorna não é ao vivo.

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>
 1
Author: Juan Mendes, 2016-03-17 13:38:57