prgrm
prgrm

Reputation: 3833

Javascript code is executed twice after using it three times

I am trying to make a javascript command that creates dropdowns successively. However, if I change a dropdown, the child dropdown should dissapear. This is the javascript:

var categorycount = 0;

function categorygenerate() {

    //for testing purposes
        var categoryarray = new Array(), i;
        for (i = 0; i < 2; i++) {
            categoryarray[i] = Math.random();
        }
        return categoryarray;
    }
    function delete_category(selectedcategory){
        restar = categorycount - selectedcategory;
        categoria = "category" + restar;
        var element = document.getElementById(categoria);
        element.parentNode.removeChild(element);
        categorycount = restar;
    }

function dropdowngenerate(divname) {
    comparelevel = divname.slice(-1);
    if (comparelevel != categorycount){
        delete_category(comparelevel)
    }
    else{
    ++categorycount;
    var categoria = "category" + categorycount;
    var newDiv=document.createElement('div');
    var html = '<select>', categories = categorygenerate(), i;
    for(i = 0; i < categories.length; i++) {
        html += "<option value='"+categories[i]+"'>"+categories[i]+"</option>";
    }
    html += '</select>';
    newDiv.innerHTML= html;
    document.getElementById(divname).appendChild(newDiv);
    newDiv.setAttribute("id",categoria);
    newDiv.setAttribute('onchange', "dropdowngenerate('"+categoria+"');");
    }
}

And this is the HTML:

<div id="category0">
<select onchange="dropdowngenerate('category0');">
    <option>test1</option>
    <option>test2</option>
    <option>test3</option>
</select>
<br>
</div>

The script works well the first 3 times, but in the fourth dropdown, the script is called twice. The first time it's called, it works properly. The second time, it is executed as if the second dropdown (category1) had been changed and deletes the rest of the dropdowns.

Any clue?

Upvotes: 0

Views: 101

Answers (2)

Aks
Aks

Reputation: 395

if you want to keep your code, a simple way to do this, is using a function like

("#category0").lastChild.remove()

That'll delete the last child (which is category1) and also the child of this one. I don't truely understand your thinking but I hope that'll help. :P

Upvotes: 0

JonSG
JonSG

Reputation: 13067

EDITED:

This code will look for an existing sibling that is a container for nested children. If it finds one it removes it. Then a new such container is created with the event handler attached.

document.getElementById("selectCategory_0").addEventListener("change", handle_onChange);

function handle_onChange(event){
  var parentContainer = this.parentNode;

  // ---------------------------
  // if a child dropdown exist, remove it
  // ---------------------------
  var childContainer = parentContainer.querySelector(".selectContainer");
  if (childContainer) { parentContainer.removeChild(childContainer); }
  // ---------------------------

  // ---------------------------
  // create a new child dropdown
  // ---------------------------
  var categories = categorygenerate();
  childContainer = generateChild(document, categories);
  // ---------------------------

  // ---------------------------
  // add the new childContainer to the DOM "after" the current dropdown
  // ---------------------------
  parentContainer.insertBefore(childContainer, this.nextSibling);
  // ---------------------------
}

function generateChild(root, categories){
  // ---------------------------
  // build an html string
  // ---------------------------
  var html = "<div class='selectContainer'><select>";
  for (var i = 0; i < categories.length; i++) {
    html += "<option value='" + categories[i] + "'>" + categories[i] + "</option>";
  }
  html += '</select></div>';
  // ---------------------------

  // ---------------------------
  // create an element from the html string
  // ---------------------------
  var tplt = root.createElement('template');
  tplt.innerHTML = html;
  var el = tplt.content.firstChild;
  // ---------------------------

  // ---------------------------
  // attach the change handler
  // ---------------------------
  el.firstChild.addEventListener("change", handle_onChange);
  // ---------------------------
  
  return el;
}

function categorygenerate() {
  var categoryarray = new Array()

  // ---------------------------
  // for testing purposes
  // ---------------------------
  for (var i = 0; i < 2; i++) {
    categoryarray[i] = Math.random();
  }
  // ---------------------------

  return categoryarray;
}
.selectContainer { padding: 1em;}
<div id="category0" class="selectContainer">
  <select id="selectCategory_0">
    <option>test1</option>
    <option>test2</option>
    <option>test3</option>
  </select>
</div>

Upvotes: 1

Related Questions