Javascript - IE11 - void results with querySelectAll()

169 views Asked by At

I have an issue with a simple js function on IE (11 and lower). When I use document.querySelector('#id').querySelectorAll('option') where #id is linked to a element, it return an array of options, but "void" like

<option id="id"></options>

my very simple JS :

var projectsList = document.querySelector('#taskproject').querySelectorAll('option');
console.dirxml(projectsList);

and my HTML code (an exemple) :

<select id="taskproject" name="newproject">
    <option id="1">Project1</option>
    <option id="2">Project2</option>
    [...]
    <option id="99">Project99</option>
</select>

This will return, with the console.dirxml function in the IE11 console

<NodeList lenght="99">
    <option id="1"></option>
    [....]
    <option id="99"></option>
</NodeList>

This works on chrome, the text inside options is written on the console. Thanks for your help!


Edit with runnable example

var projectsList = document.querySelector('#taskproject').querySelectorAll('option');

  function giveSelection(appId)
  {
      var appSelector = document.querySelector('#taskapp');
      var projectSelector = document.querySelector('#taskproject');
      projectSelector.innerHTML = '';
      if(projectSelector != null)
      {
        for(var i=0; i<projectsList.length; i++)
        {
          if(projectsList[i].id.split('_')[1] === appId)
          {
            projectSelector.appendChild(projectsList[i]);
          } 
        }
      }      
  }
<select id="taskapp" name="new_app_id" onchange="giveSelection(this.value)">
    <option value="55" >Proj1</option>
    <option value="33" >Proj2</option>
    <option value="62" >Proj3</option>
    <option value="69" >Proj4</option>
</select>

<select id="taskproject" name="new_project_id">
    <option id="appWithProject_55" value="239" >Proj1 - a</option>
    <option id="appWithProject_55" value="273" >Proj1 - b</option>
    <option id="appWithProject_55" value="289" >Proj1 - c</option>
    <option id="appWithProject_33" value="106" >Proj2 - a</option>
    <option id="appWithProject_33" value="105" >Proj2 - b</option>
    <option id="appWithProject_62" value="263" >Proj3 - a</option>
    <option id="appWithProject_62" value="264" >Proj3 - b</option>
    <option id="appWithProject_69" value="285" >Proj4 - a</option>
    <option id="appWithProject_69" value="286" >Proj4 - b</option>
</select>

Here, if I choose Proj2 on first select, it will show me only Proj2 - a and Proj2 - b on the second select (on chrome). On IE11, it will show me 2 "options" with no text inside.

1

There are 1 answers

0
T.J. Crowder On BEST ANSWER

The problem is that IE has a very strange behavior when you set innerHTML. It removes the text nodes of the elements it's removing. This is non-standard, and arguably a bug. (In fact, I seem to recall reporting it as a bug at one point.)

You can work around it by not using innerHTML = '' to clear the select, but instead using removeChild:

var projectsList = document.querySelector('#taskproject').querySelectorAll('option');

function giveSelection(appId)
{
    var appSelector = document.querySelector('#taskapp');
    var projectSelector = document.querySelector('#taskproject');
    if(projectSelector != null)
    {
      // Not this: projectSelector.innerHTML = '';
      while (projectSelector.firstChild) {
        projectSelector.removeChild(projectSelector.firstChild);
      }
      for(var i=0; i<projectsList.length; i++)
      {
        if(projectsList[i].id.split('_')[1] === appId)
        {
          projectSelector.appendChild(projectsList[i]);
        } 
      }
    }      
}
<select id="taskapp" name="new_app_id" onchange="giveSelection(this.value)">
    <option value="55" >Proj1</option>
    <option value="33" >Proj2</option>
    <option value="62" >Proj3</option>
    <option value="69" >Proj4</option>
</select>

<select id="taskproject" name="new_project_id">
    <option id="appWithProject_55" value="239" >Proj1 - a</option>
    <option id="appWithProject_55" value="273" >Proj1 - b</option>
    <option id="appWithProject_55" value="289" >Proj1 - c</option>
    <option id="appWithProject_33" value="106" >Proj2 - a</option>
    <option id="appWithProject_33" value="105" >Proj2 - b</option>
    <option id="appWithProject_62" value="263" >Proj3 - a</option>
    <option id="appWithProject_62" value="264" >Proj3 - b</option>
    <option id="appWithProject_69" value="285" >Proj4 - a</option>
    <option id="appWithProject_69" value="286" >Proj4 - b</option>
</select>


Side note: You also had the innerHTML thing before the if (projectSelector != null) check. I've put it inside that if's body instead.