Search code examples
javascripthtmllistfirefox-addon-sdk

Show/Hide child list only when item it is appended to is clicked


I have a parent list and each li of that list has an appended child list. Each child list item is a radio button with an associated label. This allows the user to click the label to set the radio button.

When the page with the content is loaded the parent list is shown and the child lists are set to display:none by default.

This all works except for two things. one thing

1) Initially the parent list elements have to be clicked twice to show the appended child list.

I would like to click it once to open

I fixed this by setting element.style.display ="none" ;

2) When clicking anywhere except the label in a child list it hides the list.

so if you select the radio button or click beside the label the list collapses. The intended behavior is that this should only occur when the list item of the parent which it is anchored to is clicked.

List structure below

ParentList
    PItem0   <-------- This should only show / hide the child list
        ChildList0
            CItem0 - RadioButton + Label
            CItem1 - RadioButton + Label
            CitemN - RadioButton + Label
    PItem1
        ChildList1
            CItem0 - RadioButton + Label
            CItem1 - RadioButton + Label
            CitemN - RadioButton + Label
      .
      .
      .
    PItemN
        ChildListN
            CItem0 - RadioButton + Label
            CItem1 - RadioButton + Label
            CitemN - RadioButton + Label

The html page is the contents of a firefox panel and the code to build the lists are in a content script.

The list is built dynamically from a json file.

The showing/hiding of the lists are done by the function toggleList which is in another js file linked in the head of the html file. It consists of one function

        function toggleList(listid) {
          var list = document.getElementById(listid);
          if (list.style.display == "none"){
              list.style.display = "block";
          }else{
              list.style.display = "none";
          }
      }

The CSS which is embedded in the head of the html page is

<style type="text/css" media="all">
    body{
        font-size: 12px;
    }   
    ul{   
        list-style-type:none;
        padding:0px;
        margin:0px;
    }   
    ul .innerlist{
        padding:5px;
        display: none;
    }   
</style>    

The list is built dynamically with the following code. This is in a firefox content script

var alist_div  = document.getElementById('alist');  

//outer list
var listElement = document.createElement("ul");
listElement.setAttribute("class","outerlist");

alist_div.appendChild(listElement);

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

  var listItem = document.createElement("li");
  listItem.innerHTML = '<b>'+data.adata[i].description+'</b>';

  //inner List  
  var innerListElement = document.createElement("ul");
  innerListElement.setAttribute("class","innerlist");
  innerListElement.setAttribute("id","innerlist"+i);

  //show or hide inner list element when the list item it is appended to is clicked
  listItem.onclick = function(x) { return function() { toggleList(x); console.log(x); }; }(innerListElement.id);

  for (var j=0; j< data.adata[i].entry.length; j++){

    var innerListItem = document.createElement("li");


    //pass the item index for the parent and for child as the value and id
    innerListItem.innerHTML =  '<input type="radio" name="aradio" id="'+ i+','+j+'" value="'+ i+','+j+'"><label for="'+ i+','+j+'">' +data.adata[i].entries[j].description+ '</label>';
    innerListElement.appendChild(innerListItem);

  }   

  listItem.appendChild(innerListElement);
  listElement.appendChild(listItem);

}   

If anyone could help me with the two issues issue above I would greatly appreciate it. I would prefer a non jQuery solution if possible. Thank you


Solution

  • I solved issue 1 by setting

    innerListElement.style.display ="none" ; 
    

    I solved issue 2 by

    innerListItem.onclick= function stopProp (event){
        event.stopPropagation(); 
    }