0
votes

Basically the function below empties out the select field and re-populates it with the updated options when there are changes in the chrome.storage.local. This is also when I want to add on event listeners to the options, so that I can implement custom actions.

But I'm at my wits end on this, for some reason I cannot add an event listener to the options. I have a setTimeout function that prints out the options after they're rendered, and the options are there but the onclick is null. I've also tried adding on event listeners with a setTimeout to double check if they were being overwritten in another step, but that didn't work either.

Edited to clarify from feedback: Console does not show the event listener callback console.log('working'), therefore it's not working. And I'm already using a select onchange listener. But I need to re-focus to the 'info' field, even if they re-select the same option.

Any help would be greatly appreciated!

function updateSelectOptions(selectID){
    var selectList = document.getElementById(selectID);
    while (selectList.length > 0) {
        selectList.remove(selectList.length -1);
    }

    var storage = chrome.storage.local;
    storage.get(['settingsArray', 'selectedPage'], function(data) {
        var settingsArray = data.settingsArray;
        var settingsNameArray = settingsArray.map(function(ele) {
            return ele.pageName;
        });
        if (selectID === 'pageSelectDropdown') {
            settingsNameArray.push('Add New Page');
        }

        var selectedPage = data.selectedPage;
        //Create and append the options
        for (var i = 0; i < settingsNameArray.length; i++) {
            var option = document.createElement("option");
            option.setAttribute("value", i);
            option.setAttribute("class", 'optionClass');
            option.text = settingsNameArray[i];
            option.addEventListener('click', ()=>{
                console.log('working')
                document.getElementById('info').focus();
            });
            selectList.appendChild(option);
        }

        document.getElementById(selectID).value = selectedPage;
    })
}

Actually even this toy example doesn't work, what's wrong here? Mouseup, click neither produces the console.log event.

   <select id='pageSelectDropdown'>
        <option value='Add New Page'>Add New Page</option>
        <option value='Great Page'>Great Page</option>
        <option value='Family Page'>Family Page</option>
      </select>

      <script type="text/javascript">
      opts = document.getElementsByTagName('option');
      console.log(opts)
      for (i = 0; i < opts.length; i++) {
        opts[i].addEventListener('click', ()=>{
          console.log('clicked')
        })
      }
      </script>
2
but the onclick is null adding an event listener using addEventListener does not change an event listener that is "added" using .onclick = - so it's perfectly fine that .onclick is null - the event listener should have been added correctly regardlessJaromanda X
BTW, you can remove all the options by simply setting selectList.options.length = 0.RobG
Is this a multi-select list? If not, it seems to me it would be easier to add the listener to the select itself and just test the current value within the handler.nnnnnn
Thank you very much for your feedback thus far! So it's actually not firing the console.log in the eventlistener callback, so it's still broken somehow. And it's a single select list, but I need to be able to re-focus to the info field even if I reselected the same option, which is why an onChange listener doesn't work. Really appreciate the information though, had no idea about those details :)Shinjitsu

2 Answers

2
votes

Do not rely on clicks! Listen to select change instead. So you will know what the real value is selected.

1
votes

Edit: Sorry, but I've missed that you want to call that function even thought user has selected the same option.

You can have a look at this, this does help me to answer your question:

Run change event for select even when same option is reselected

For your toy example, you can do this:

var isopen = false;
var sel = document.getElementById('pageSelectDropdown');
sel.addEventListener('mouseup', () => {
  if (isopen) {
    console.log("changed to " + sel.value);
    isopen = false;
  } else {
    isopen = true;
  }
});
sel.addEventListener('blur', () => {
  isopen = false;
});
<select id='pageSelectDropdown'>
  <option value='Add New Page'>Add New Page</option>
  <option value='Great Page'>Great Page</option>
  <option value='Family Page'>Family Page</option>
</select>

I tried your question and results in the following:

function updateSelectOptions(selectID){
    var isopen = false;
    var selectList = document.getElementById(selectID);
    while (selectList.length > 0) {
        selectList.remove(selectList.length -1);
    }

    // settingsNameArray is get from chrome.storage.local
    var settingsNameArray = ["Great Page", "Family Page", "Test Page", "fooo"];
    if (selectID === 'pageSelectDropdown') {
        settingsNameArray.unshift('Add New Page');
    }

    // selectedPage is get from chrome.storage.local
    var selectedPage = "Family Page";
    var selectedPageIndex = settingsNameArray.indexOf(selectedPage);
    // deleted the event handler for each option
    for (var i = 0; i < settingsNameArray.length; i++) {
        var option = document.createElement("option");
        option.setAttribute("value", i);
        option.setAttribute("class", 'optionClass');
        option.text = settingsNameArray[i];
        selectList.appendChild(option);
    }
    // add the event listener to the list
    selectList.addEventListener('mouseup', ()=>{
        if (isopen) {
            console.log("working! change to " + selectList.value + " : " + settingsNameArray[selectList.value]);
            document.getElementById('info').focus();
            // variable isopen automatically turn to false when blur
        } else {
            isopen = true;
        }
    });
    selectList.addEventListener('blur', ()=>{
        isopen = false;
    });
    selectList.value = selectedPageIndex;
}
<select id='pageSelectDropdown'>
    <option value='Add New Page'>Add New Page</option>
    <option value='Great Page'>Great Page</option>
    <option value='Family Page'>Family Page</option>
</select>
<br>
<button onclick="updateSelectOptions('pageSelectDropdown');this.remove();">Call the function</button>
<br>
<textarea id="info"></textarea>

Actually, this will also work with the option value with strings, which is more readable.

function updateSelectOptions(selectID){
    var isopen = false;
    var selectList = document.getElementById(selectID);
    while (selectList.length > 0) {
        selectList.remove(selectList.length -1);
    }

    // settingsNameArray is get from chrome.storage.local
    var settingsNameArray = ["Great Page", "Family Page", "Test Page", "fooo"];
    if (selectID === 'pageSelectDropdown') {
        settingsNameArray.unshift('Add New Page');
    }

    // selectedPage is get from chrome.storage.local
    var selectedPage = "Family Page";
    // deleted the event handler for each option
    for (var i in settingsNameArray) {
        var option = document.createElement("option");
        option.setAttribute("value", settingsNameArray[i]);
        option.setAttribute("class", 'optionClass');
        option.text = settingsNameArray[i];
        selectList.appendChild(option);
    }
    // add the event listener to the list
    selectList.addEventListener('mouseup', ()=>{
        if (isopen) {
            console.log("working! change to " + selectList.value);
            document.getElementById('info').focus();
            // variable isopen automatically turn to false when blur
        } else {
            isopen = true;
        }
    });
    selectList.addEventListener('blur', ()=>{
        isopen = false;
    });
    selectList.value = selectedPage;
}
<select id='pageSelectDropdown'>
    <option value='Add New Page'>Add New Page</option>
    <option value='Great Page'>Great Page</option>
    <option value='Family Page'>Family Page</option>
</select>
<br>
<button onclick="updateSelectOptions('pageSelectDropdown');this.remove();">Call the function</button>
<br>
<textarea id="info"></textarea>