0

I wrote a function in javascript. It works perfectly to show and hide list items on click action. I have other 5 lists items that I want to use this function for them also. However, When I tried to generalize the function by passing parameters as IDs it did not work.

the following part of the html:

function toggle_att_menu() {

  var att_list = document.getElementById("att-list");
  var plus = document.getElementById("plus");
  var minus = document.getElementById("minus");

  att_list.style.display= 
((att_list.style.display!='block')?'block':'none');
  plus.style.display= 
((plus.style.display!='none')?'none':'inline');
  minus.style.display= 
((minus.style.display!='inline')?'inline':'none');

}

// what I want to do is passing parameter as following:
function toggle_att_menu(x,y,z) {

  var att_list = document.getElementById(x);
  var plus = document.getElementById(y);
  var minus = document.getElementById(z);

  att_list.style.display= 
  ((att_list.style.display!='block')?'block':'none');
  plus.style.display= 
  ((plus.style.display!='none')?'none':'inline');
  minus.style.display= 
  ((minus.style.display!='inline')?'inline':'none');
}

//and use the function five times with different IDs each time as following:

        toggle_att_menu('att-list-1','plus-1','minus-1')
        toggle_att_menu('att-list-2','plus-2','minus-2')  
        toggle_att_menu('att-list-3','plus-3','minus-3')  
        toggle_att_menu('att-list-4','plus-4','minus-4')  
        toggle_att_menu('att-list-5','plus-5','minus-5') 
<div class="title linklike">
<span id="plus-1" class="plus" >&#9656;</span><span id="minus-1" class="minus">&#9662;</span> <a id="linklike" onclick="toggle_att_menu()" href="#"> condition </a>
</div>

<ul id= "att-list-1" class="att-list">
  <li class="checkbox ">
      <label>
          <input id="condition_1" name="condition" class="multi_checkbox" value="1" type="checkbox"
           />
          new
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_2" name="condition" class="multi_checkbox" value="2" type="checkbox"
           />
          like new
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_3" name="condition" class="multi_checkbox" value="3" type="checkbox"
           />
          excellent
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_4" name="condition" class="multi_checkbox" value="4" type="checkbox"
           />
          good
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_5" name="condition" class="multi_checkbox" value="5" type="checkbox"
           />
          fair
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_6" name="condition" class="multi_checkbox" value="6" type="checkbox"
           />
          damegaed
      </label>
  </li>
</ul>

</div>



<div class="search-attribute hide-list" data-attr="condition">
  <div class="title linklike">
<span id="plus-2" class="plus" >&#9656;</span><span id="minus-2" class="minus">&#9662;</span> <a id="link" onclick="toggle_att_menu()" href="#">condition</a>
</div>

<ul id= "att-list-2" class="att-list">
  <li class="checkbox ">
      <label>
          <input id="condition_1" name="condition" class="multi_checkbox" value="1" type="checkbox"
           />
          new
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_2" name="condition" class="multi_checkbox" value="2" type="checkbox"
           />
          like new
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_3" name="condition" class="multi_checkbox" value="3" type="checkbox"
           />
          excellent
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_4" name="condition" class="multi_checkbox" value="4" type="checkbox"
           />
          good
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_5" name="condition" class="multi_checkbox" value="5" type="checkbox"
           />
          fair
      </label>
  </li>
  <li class="checkbox ">
      <label>
          <input id="condition_6" name="condition" class="multi_checkbox" value="6" type="checkbox"
           />
          damaged
      </label>
  </li>
</ul>

</div>

any idea or solution will be highly appreciated.I am not so familiar with jQuery. so please I need help using only pure java script.

3
  • Well, first, your ids have duplicates; an id can only be used once. Second, I don't see att-list-1, att-list-2, etc anywhere. Third, the onclick attributes on your condition anchor tags don't have parameters. Commented Mar 2, 2018 at 7:21
  • Could you run code snippet so we could see how really you implement the work? Commented Mar 2, 2018 at 7:26
  • You have abstracted it just fine, your errors as mentioned above is not using unique id's, if you have multiple things that need the same action you use class in your html, and would change your javascript to get DOM nodes by class name, but it returns Html lists, so you need to throughly familiarize yourself with the return types and how to work with them. Here is a link Commented Mar 2, 2018 at 7:27

4 Answers 4

3

Try it like this:

https://jsfiddle.net/bertdireins/dtmdod15/6/

function toggle_att_menu(elem) {

       var container = elem.parentElement.parentElement;

       var att_list = container.querySelector(".att-list");
       var plus = container.querySelector(".plus");
       var minus = container.querySelector(".minus");

       att_list.style.display = ((att_list.style.display!='block')?'block':'none');
       plus.style.display =((plus.style.display!='none')?'none':'inline');
       minus.style.display = ((minus.style.display!='inline')?'inline':'none');
}

You first have to get the parent parent's container of your anker and then you can query the underlying elements.

Your ankers should then look like this:

<div class="title linklike">
    <span id="plus" class="plus">&#9656;</span>
    <span id="minus" class="minus">&#9662;</span>
    <a id="linklike" onclick="toggle_att_menu(this)" href="#"> condition </a>
</div>

<ul id="att-list" class="att-list"> ... </ul>

Please be aware the fiddle is missing the initial CSS, so it looks little weird.

Query would make life much easier here.

Sign up to request clarification or add additional context in comments.

4 Comments

thank you for your response. the function is working fine. the problem when I tried to generalize it to reuse it with different IDs It did not work . I do not know why?. I do not want to write the function five times. it is unprofessional
You dont need ids for above version anymore.
Here is a version with the ids in use: jsfiddle.net/bertdireins/dtmdod15/11
Thank you so much. I tried your code and It worked the way I want. I really appreciate your help.
1

The reason for this is your function calls, and your element IDs. You have no elements with id "att-list-1", "att-list-2" etc. You have two elements with the same id: "att-list". Two elements should never have the same id. Switch the ids to "att-list-1", "att-list-2" and so forth, and it probably should work. The same goes for "plus-1" ... and "minus-1" ..., you have no elements with those IDs in HTML, you use the same IDs "minus" and "plus" for several elements.

5 Comments

sorry i was in a herry and I did not pay attention to html code. even with different IDs. It did not work.
well I think the HTML here is important, because th JS code makes sence. So if it does not work with correct IDs, i think this is your problem: att_list.style.display= ((att_list.style.display!='block')?'block':'none'); since you have no style="display:block" on your ul element initially, the ul will not be hidden the first time its called, it will get the display block style. But the second time you call it, it should hide. Could you test?
thank you for your response. the function is working fine. the problem when I tried to generalize it to reuse it with different IDs It did not work . I do not know why?. I do not want to write the function five times. it is unprofessional
Did you test to add style="display:block" to your ul elements initially? I think you should provide me with a jsfiddle or some working code for me to easier help you further :)
Yes I did. sorry for the missing css. Gerry solution is perfect. It works the way I want. thank you again
1

You are not using unique IDs for your elements - it's better to use classes for repeated elements. Anyway, you probably want something like that:

/*
function toggle_att_menu(x,y,z) {
    var att_list = document.getElementById(x);
    var plus = document.getElementById(y);
    var minus = document.getElementById(z);

    att_list.style.display = ((att_list.style.display!='block')?'block':'none');
    plus.style.display = ((plus.style.display!='none')?'none':'inline');
    minus.style.display = ((minus.style.display!='inline')?'inline':'none');
}
*/

function toggle_att_menu(element) {
   var parent = element.parentElement.parentElement;
   var att_list = parent.querySelector(".att-list");
   var plus = parent.querySelector(".plus");
   var minus = parent.querySelector(".minus");
     
    att_list.style.display = ((att_list.style.display!='block')?'block':'none');
    plus.style.display = ((plus.style.display!='none')?'none':'inline');
    minus.style.display = ((minus.style.display!='inline')?'inline':'none');
}
<div class="search-attribute hide-list" data-attr="condition">
<div class="title linklike">
    <span id="plus-1" class="plus">&#9656;</span><span id="minus-1" class="minus">&#9662;</span><a id="link-1" onclick="toggle_att_menu(this)" href="#"> condition </a>
</div>
<ul id="att-list-1" class="att-list">
    <li class="checkbox ">
        <label>
            <input id="condition_1_1" name="condition" class="multi_checkbox" value="1" type="checkbox"/>
            new
        </label>
    </li>
    <li class="checkbox ">
        <label>
            <input id="condition_1_2" name="condition" class="multi_checkbox" value="2" type="checkbox"/>
            like new
        </label>
    </li>
    <li class="checkbox ">
        <label>
            <input id="condition_1_3" name="condition" class="multi_checkbox" value="3" type="checkbox"/>
            excellent
        </label>
    </li>
    <li class="checkbox ">
        <label>
            <input id="condition_1_4" name="condition" class="multi_checkbox" value="4" type="checkbox"/>
            good
        </label>
    </li>
    <li class="checkbox ">
        <label>
            <input id="condition_1_5" name="condition" class="multi_checkbox" value="5" type="checkbox"/>
            fair
        </label>
    </li>
    <li class="checkbox ">
        <label>
            <input id="condition_1_6" name="condition" class="multi_checkbox" value="6" type="checkbox"/>
            damegaed
        </label>
    </li>
</ul>
</div>



<div class="search-attribute hide-list" data-attr="condition">
    <div class="title linklike">
        <span id="plus-2" class="plus" >&#9656;</span><span id="minus-2" class="minus">&#9662;</span> <a id="link-2" onclick="toggle_att_menu(this)" href="#">condition</a>
    </div>
    <ul id="att-list-2" class="att-list">
        <li class="checkbox ">
            <label>
                <input id="condition_2_1" name="condition" class="multi_checkbox" value="1" type="checkbox"/>
                new
            </label>
        </li>
        <li class="checkbox ">
            <label>
                <input id="condition_2_2" name="condition" class="multi_checkbox" value="2" type="checkbox"/>
                like new
            </label>
        </li>
        <li class="checkbox ">
            <label>
                <input id="condition_2_3" name="condition" class="multi_checkbox" value="3" type="checkbox"/>
                excellent
            </label>
        </li>
        <li class="checkbox ">
            <label>
                <input id="condition_2_4" name="condition" class="multi_checkbox" value="4" type="checkbox"/>
                good
            </label>
        </li>
        <li class="checkbox ">
            <label>
                <input id="condition_2_5" name="condition" class="multi_checkbox" value="5" type="checkbox"/>
                fair
            </label>
        </li>
        <li class="checkbox ">
            <label>
                <input id="condition_2_6" name="condition" class="multi_checkbox" value="6" type="checkbox"/>
                damaged
            </label>
        </li>
    </ul>
</div>

1 Comment

Thank you for your solution
1

As a general piece of advice, try:

  • not using the same id multiple times, because that's not how the id is supposed to work. Ids ought to be unique, otherwise, you're going to have problems with CSS and JavaScript in particular.

  • getting your elements by class, or some other non-unique selector, instead of id, using a function that can do that, such as getElementsByClassName orquerySelectorAll so that you can use your function just once.

  • using window.getComputedStyle(el).getPropertyValue as a fallback, when getting the current display to check against, in case the style is not defined yet (if you don't the first click will do nothing).

Now, regarding your problem, since you can't use jQuery, getting the elements will get kind of ugly and will depend vastly on how you position them relatively to each other. Since, you are using inline JavaScript to call your function, be sure to pass this as an argument to be able to use the link to get the required elements.

Snippet:

/* ----- JavaScript ----- */
function toggle_att_menu(a) {
  var
    /* Cache all desired elements. */
    elements = {
      att_list: a.parentElement.nextElementSibling.children[0],
      plus: a.previousElementSibling.previousElementSibling,
      minus: a.previousElementSibling
    },
    
    /* Store the wanted displays for each element type. */
    displays = {
      att_list: {from: "block", to: "none"},
      plus: {from: "inline", to: "none"},
      minus: {from: "none", to: "inline"}
    };
    
  /* Iterate over every property of the elements object. */
  for (var type in elements) {
    var
      /* Cache the current element. */
      element = elements[type],

      /* Get the current display of the element. */
      d = element.style.display ||
        getComputedStyle(element, null).getPropertyValue("display");

    /* Set the element's display to the appropriate one. */
    element.style.display = (d != displays[type].from)
      ? displays[type].from
      : displays[type].to;
  }
}
/* ----- CSS ----- */
.plus { display: inline }
.minus { display: none }
<!----- HTML ----->
<div class="title linklike">
  <span class="plus">&#9656;</span>
  <span class="minus">&#9662;</span>
  <a class="linklike" onclick="toggle_att_menu(this)" href="#">condition</a>
</div>

<div class="search-attribute hide-list" data-attr="condition">
  <ul class="att-list">
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="1" type="checkbox"/>
        new
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="2" type="checkbox"/>
        like new
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="3" type="checkbox"/>
        excellent
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="4" type="checkbox"/>
        good
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="5" type="checkbox"/>
        fair
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="6" type="checkbox"/>
        damaged
      </label>
    </li>
  </ul>
</div>

<div class="title linklike">
  <span class="plus">&#9656;</span>
  <span class="minus">&#9662;</span>
  <a class="linklike" onclick="toggle_att_menu(this)" href="#">condition</a>
</div>

<div class="search-attribute hide-list" data-attr="condition">
  <ul class="att-list">
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="1" type="checkbox"/>
        new
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="2" type="checkbox"/>
        like new
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="3" type="checkbox"/>
        excellent
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="4" type="checkbox"/>
        good
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="5" type="checkbox"/>
        fair
      </label>
    </li>
    <li class="checkbox">
      <label>
        <input name="condition" class="multi_checkbox" value="6" type="checkbox"/>
        damaged
      </label>
    </li>
  </ul>
</div>

2 Comments

thank you. and thank you for your advice regarding using window.getComputedStyle(el).getPropertyValue. I face this problem before. I did not use it and the first click did nothing.
You're welcome @SalehAlomari; I'm glad I could help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.