3

I have seen other questions asked where select and optgroup were given, but where more CSS styling is needed, is there a way to show the sub-categories from a menu created using radio inputs?

The snippet shows the menu animation that is required so select won't work here. I changed the HTML markup to radio inputs. Is it possible to toggle the associated sub-category div when the main-category is select?

$(".cat-dropdown .title :input").click(function() {
  var $menu = $(this)
    .parent()
    .siblings(".cat-dropdown-menu");
  if ($menu.height() > 0) {
    closeMenu($menu);
  } else {
    openMenu($menu);
  }
});
$(".cat-dropdown-menu .cat-item").click(function() {
  var $menu = $(this).closest(".cat-dropdown-menu");
  closeMenu($menu);
  $menu
    .closest(".cat-dropdown")
    .find(".title span")
    .text($(this).text())
    .css("color", this.style.color);
});

function closeMenu($menu) {
  $list = $menu.children(".cat-list");
  $menu.closest(".cat-dropdown").toggleClass("closed");
  $menu.css("height", 0);
  $list.css("top", 0);
}

function openMenu($menu) {
  $list = $menu.children(".cat-list");
  $menu.closest(".cat-dropdown").toggleClass("closed");
  $menu.css({
    height: 75
  });
}
* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.cat-list input {
  display: none;
}

.sub-list {
  display: flex;
  flex-direction: column;
}

.main1 {
  border: 2px solid blue;
}

.main2 {
  border: 2px solid red;
}

.cat-dropdown {
  margin: 25px;
  text-align: left;
  color: #343c3f;
  border: 1px solid #a2acb0;
}

.cat-dropdown.closed .cat-dropdown-menu {
  margin-top: 0px;
}

.cat-dropdown.closed .cat-dropdown-menu .cat-item {
  height: 0px;
}

.cat-dropdown.closed .title {
  border-bottom: none;
}

.cat-dropdown.closed .title:after {
  margin-top: -16px;
  -webkit-transform: rotate(0deg);
  -moz-transform: rotate(0deg);
  -ms-transform: rotate(0deg);
  -o-transform: rotate(0deg);
  transform: rotate(0deg);
}

.cat-dropdown .title {
  width: 100%;
  position: relative;
  height: 40px;
  padding: 12px;
  cursor: pointer;
  border-bottom: 1px solid #d9e1e4;
}

.cat-dropdown .title:after {
  display: block;
  content: "▾";
  position: absolute;
  right: 14px;
  margin-top: -16px;
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  -ms-transform: rotate(180deg);
  -o-transform: rotate(180deg);
  transform: rotate(180deg);
}

.cat-dropdown .cat-dropdown-menu {
  position: relative;
  overflow: hidden;
  max-height: 200px;
  -webkit-transition: all 0.2s;
  -moz-transition: all 0.2s;
  transition: all 0.2s;
  -webkit-box-sizing: "border-box";
  -moz-box-sizing: "border-box";
  box-sizing: "border-box";
}

.cat-dropdown .cat-list {
  position: absolute;
  top: 0;
  width: 100%;
}

.cat-dropdown .cat-list .cat-item {
  width: 100%;
  height: 40px;
  line-height: 40px;
  border-bottom: 1px solid #d9e1e4;
  padding: 0 12px;
  vertical-align: top;
  overflow: hidden;
  cursor: pointer;
  -webkit-transition: margin-top 0.5s, height 0.5s;
  -moz-transition: margin-top 0.5s, height 0.5s;
  transition: margin-top 0.5s, height 0.5s;
}

.cat-dropdown .cat-list .cat-item:hover {
  background-color: #d9e1e4;
  color: #343c3f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="cat-dropdown closed">
  <div class="edit">
    <label class="title">
<input class="edit-input1" type="checkbox"><span> Choose...</span>
</label>
    <div class="cat-dropdown-menu">
      <div class="cat-list" id="category">
        <label class="cat-item" style="color:blue">
<input type="radio" name="cat1">Main 1</label>
        <label class="cat-item" style="color:red">
<input type="radio" name="cat2">Main 2</label>
      </div>
    </div>
  </div>
</div>
Sub Category:
<div id="subcategory">
  <div class="sub-list main1" for="cat1">
    <input type="radio" name="sub1" value="opt1">main1 opt1
    <input type="radio" name="sub1" value="opt2">main1 opt2
    <input type="radio" name="sub1" value="opt3">main1 opt3
  </div>
  <div class="sub-list main2" for="cat2">
    <input type="radio" name="sub2" value="opt1">main2 opt1
    <input type="radio" name="sub2" value="opt2">main2 opt2
    <input type="radio" name="sub2" value="opt3">main1 opt3
  </div>
</div>

https://codepen.io/moofawsaw/pen/LmLZeM

Kyle Underhill
  • 89
  • 15
  • 43

3 Answers3

1

I once had to do something similar, this was what I came up with:

<script>
  function subselect(cat){
    var select = "";
    if (cat == 1) {
      select = "<select><option value='a1'>a1</ooption><option value='a2'>a2</ooption></select>"
    }else if (cat == 2) {
      select = "<select><option value='b1'>b1</ooption><option value='b2'>b2</ooption></select>"
    }
   document.getElementById("subcategory").innerHTML = select;
  }

</script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="cat-dropdown closed">
  <div class="edit">
    <label class="title">
<input class="edit-input1" type="checkbox"><span> Choose...</span>
</label>
    <div class="cat-dropdown-menu">
      <div class="cat-list" id="category">
        <label class="cat-item" style="color:blue">
<input type="radio" name="cat" onclick='subselect(1)'>Main 1</label>
        <label class="cat-item" style="color:red">
<input type="radio" name="cat" onclick='subselect(2)'>Main 2</label>
      </div>
    </div>
  </div>
</div>
Sub Category:
<div id="subcategory">
</div>
Tunna182
  • 343
  • 3
  • 16
1

Is it possible to toggle the associated sub-category div when the main-category is select?

Yes, and this what worked for me:

function toggleSubcatDiv( input ) {
  var name = $( input ).attr( 'name' );

  $( '.sub-list[for="' + name + '"]' )
    .siblings( '.sub-list' )
      .filter( '.active' )
        .removeClass( 'active' )
      .end()
    .end().addClass( 'active' );
}

Where I used the function in this closure:

$(".cat-dropdown-menu .cat-item").click(function() {
  var $menu = $(this).closest(".cat-dropdown-menu");
  closeMenu($menu);
  // ... your code here.

  toggleSubcatDiv( $( ':radio', this ) ); // <- here's where I used that function
});

Then I added this custom CSS:

.sub-list:not(.active) {
  display: none;
}

So toggleSubcatDiv() will either add or remove active from the class attribute of the sub-category div (i.e. .sub-list).

See demo on https://codepen.io/anon/pen/NMyKvp (PS: I did not change the HTML markup; however, you could pre-select the Main 1 div by adding active to the class of that div.)

UPDATE

In reply to your comment, this should work so long as the sub-category divs are placed in (or added to) the same .container div:

function toggleSubcatDiv( input ) {
  var name = $( input ).attr( 'name' );

  $( '.sub-list[for="' + name + '"]' )
    .closest( '.container' )
      .find( '.sub-list.active' )
        .removeClass( 'active' )
      .end()
    .end().addClass( 'active' );
}

So what changed is, that we now find the closest parent/container which is shared by the sub-category divs.

Demo: https://codepen.io/anon/pen/LmQoRg

Sally CJ
  • 15,362
  • 2
  • 16
  • 34
  • 1
    Thanks Sally. Your solution works great. I'm having trouble at site level however because in my markup I have to have the `sub-list` in dynamic wrappers so they are no longer `siblings` and now they compile instead of radio. https://codepen.io/moofawsaw/pen/vjdVZq – Kyle Underhill May 09 '18 at 19:18
  • 1
    Working. It would be great to be able to select one of the inputs under an instance of `for="catx"` to show initially. Could we add a `data-attribute` to one of the `sub-list input` with the name of the specific sub-category we want to select? – Kyle Underhill May 10 '18 at 01:27
  • Actually that feature already exists. =) Just add `active` to the `class` of the `.sub-list` `div`. See the updated [Pen](https://codepen.io/anon/pen/LmQoRg). And secondly, you should use `$( '.sub-list[for="' + name + '"]', '.container' )` (i.e. provide a context) so that we're only 'activating' the `.sub-div` in `.container`. Or you can try this version: https://codepen.io/anon/pen/NMyVYb (see the notes at the bottom of the page) – Sally CJ May 10 '18 at 01:45
0

    <html lang="en" dir="ltr">
      <head>
        <meta charset="utf-8">
        <title></title>
        <style media="screen">
          select optgroup{
            display: none;
          }
          input.a:checked + input + select optgroup[label=a]{
            display: block !important;
          }
          
          input.b:checked + select optgroup[label=b]{
            display: block !important;
          }
        </style>
      </head>
      <body>
        a<input class="a" type="checkbox" name="sel" value="a">
        b<input class="b" type="checkbox" name="sel" value="b">
        <select class="" name="">
          <optgroup label="a">
            <option value="a1">a1</option>
            <option value="a2">a2</option>
          </optgroup>
          <optgroup label="b">
            <option value="b1">b1</option>
            <option value="b2">b2</option>
          </optgroup>
        </select>
      </body>
    </html>

This is an example of how you could alter a list using the :checked psuedo selector. When using psuedo selectors you need to be able to navigate to the element you want to alter. Our input.a has to traverse to its second sibling, but input.b only has to travers to its first.

Thomas Valadez
  • 1,697
  • 2
  • 22
  • 27