Kyle Underhill
Kyle Underhill

Reputation: 109

HTML main category dropdown selection and sub-category list

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

Upvotes: 3

Views: 4934

Answers (3)

Sally CJ
Sally CJ

Reputation: 15620

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

Upvotes: 1

Tunna182
Tunna182

Reputation: 343

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>

Upvotes: 1

Thomas Valadez
Thomas Valadez

Reputation: 1747

    <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.

Upvotes: 0

Related Questions