jqueryjquery-uidrop-down-menujquery-ui-selectmenu

How to create a fixed header of the dropdown list created by the selectMenu widget?


I created a dropdown list using the selectMenu jQuery widget. Here is the code for that.

$(function() {
  
  $.widget("custom.mySelectMenu", $.ui.selectmenu, {
    
    _renderMenu: function(ul, items) {
      var that = this,
        currentCategory = "";
      ul.append("<li class='ui-header'>" + "CODE" +"&nbsp;&nbsp;&nbsp;"+"DESCRIPTION"+"</li>" + "<br>");
      
      
      
      $.each(items, function(index, item) {
        var li, name, short, price;
        if (item.optgroup != currentCategory) {
          ul.append(
            "<li class='ui-selectmenu-category'>"  +item.optgroup + "</li>"
          );
          currentCategory = item.optgroup;
        }
        li = that._renderItemData(ul, item);
        console.log(ul);
        name = li.text();
        short = item.element.data("short");
        price = item.element.data("price");
        // console.log(li, short, price);
        li.prepend(
          $("<span>", {
            class: "short"
          }).html(short)
        );

        li.append(
          $("<span>", {
            class: "price"
          }).html(price)
        );
        if (item.optgroup) {
          li.attr("aria-label", item.optgroup + " : " + item.label);
        }
      });
    }
  });

  $("#options").mySelectMenu({
    width: 300
  });
  $("#options")
    .mySelectMenu("menuWidget")
    .addClass("overflow");
});
.ui-menu .ui-menu-item {
  display: table;
  width: 100%;
}
.ui-selectmenu-category {
  color: #5f5f5f;
  padding: 0.5em 0.25em;
  min-width: 290px;
  font-style: italic;
}

.ui-header {
  font-weight: bold;
  position: absolute;
  background-color: #004600;
  color: white;
  z-index: 1;
}
.ui-header::after {
  content: "PRICE";
  float: right;
  padding-right: 70px;
}
/* .ui-selectmenu-category::after {
  content: "PRICE";
  float:right;
  padding-right: 50px;
} */

.ui-menu-item .ui-menu-item-wrapper {
  display: table-cell;
  vertical-align: top;
  padding: 1em 2px;
}

.ui-menu-item .ui-menu-item-wrapper.ui-state-active {
  margin: 0;
  border-width: 1px 0px 1px 0px;
  border-color: #cccccc;
  background-color: #e4ebf1;
  color: #000;
}

.ui-menu-item .ui-menu-item-wrapper.ui-state-active.short {
  color: #2e6d99;
}

.ui-menu-item div.ui-menu-item-wrapper {
  width: 290px;
}

.ui-menu-item .short {
  color: #2e6d99;
  font-weight: strong;
  width: 30px;
  padding-left: 0.5em;
  position: relative;
}

.ui-menu-item .price {
  font-weight: strong;
  width: 75px;
  margin-right: -6px;
}

.overflow {
  height: 150px;
}
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Selectmenu - Custom Rendering</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>

<body>
  <label for="options">Select an Option:</label>
    <select id="options">
  <optgroup label="PREFERRED OPTIONS">
    <option data-short="L" data-price="$0.00">Standard Screw Adjustment dkjsahdksajd sdhsdl sdshad ;sldh sd;lsa d;lsajd</option>
    <option data-short="K" data-price="$0.00">Standard Screw Adjustment</option>
  </optgroup>
  <optgroup label="STANDARD OPTIONS">
    <option data-short="C" data-price="$5.00" >Tamper Resistant - Factory Set</option>
    <option data-short="K" data-price="$6.00" >Handknob</option>
  </optgroup>
  <optgroup label="ADDITIONAL OPTIONS">
    <option data-short="F" data-price="$4.00">Hex Head Screw with Locknut</option>
    <option data-short="G" data-price="$4.00">Hex Head Screw with Locknut</option>
    <option data-short="H" data-price="$4.00" >Hex Head Screw with Locknut</option>
  </optgroup>
</select>

</body>

</html>

Now, the problem is that I want to make a fixed header as it is shown on the top of the dropdown list. But the problem is that this header is overlapping the scroll-bar. I tried giving the position: fixed to this header but this created a fixed header covering the entire width of the page. Along with that, when I changed the position to relative, the header was shown exactly as what I want but it was not fixed. So, is there any way to fix the position of this header? I'll also be able to accomplish my task if the header is totally above the dropdown list i.e. not covering/overlapping the scroll-bar. Please help.


Solution

  • Prepending your header to ul element containing the real dropdown and with appropriate CSS you can achieve your goal:

      ul.parent().prepend("<ul class='ui-header ui-menu ui-corner-bottom ui-widget ui-widget-content'><li class='ui-menu-item'><span class='ui-menu-item-wrapper'>" + "CODE" + "</span><span class='ui-menu-item-wrapper'>" + "DESCRIPTION" + "</span><span class='ui-menu-item-wrapper'>"+ "PRICE" + "</span></li></ul>");
    

    CSS:

    .ui-header {
      font-weight: bold;
      position: absolute;
      background-color: #004600;
      color: white;
      z-index: 1;
      height: 25px;
      width: 100%;
    }
    
    .ui-header .ui-menu-item .ui-menu-item-wrapper {
      padding: 0px;
    }
    
    #options-menu {
      margin-top: 25px;
    }
    

    Code snippet:

    $(function() {
      $.widget("custom.mySelectMenu", $.ui.selectmenu, {
        _renderMenu: function(ul, items) {
          var that = this,
            currentCategory = "";
          ul.parent().prepend("<ul class='ui-header ui-menu ui-corner-bottom ui-widget ui-widget-content'><li class='ui-menu-item'><span class='ui-menu-item-wrapper'>" + "CODE" + "</span><span class='ui-menu-item-wrapper'>" + "DESCRIPTION" + "</span><span class='ui-menu-item-wrapper'>"+ "PRICE" + "</span></li></ul>");
          $.each(items, function(index, item) {
            var li, name, short, price;
            if (item.optgroup != currentCategory) {
              ul.append(
                "<li class='ui-selectmenu-optgroup ui-menu-divider ui-selectmenu-category'>" + item.optgroup + "</li>"
              );
              currentCategory = item.optgroup;
            }
            li = that._renderItemData(ul, item);
            console.log(ul);
            name = li.text();
            short = item.element.data("short");
            price = item.element.data("price");
            // console.log(li, short, price);
            li.prepend(
              $("<span>", {
                class: "short"
              }).html(short)
            );
            li.append(
              $("<span>", {
                class: "price"
              }).html(price)
            );
            if (item.optgroup) {
              li.attr("aria-label", item.optgroup + " : " + item.label);
            }
          });
        }
      });
    
      $("#options").mySelectMenu({
        width: 300
      });
      $("#options")
        .mySelectMenu("menuWidget")
        .addClass("overflow");
    });
    .ui-menu .ui-menu-item {
      display: table;
      width: 100%;
    }
    
    .ui-selectmenu-category {
      color: #5f5f5f;
      padding: 0.5em 0.25em;
      min-width: 290px;
      font-style: italic;
    }
    
    .ui-header {
      font-weight: bold;
      position: absolute;
      background-color: #004600;
      color: white;
      z-index: 1;
      height: 25px;
      width: 100%;
    }
    
    .ui-header .ui-menu-item .ui-menu-item-wrapper {
      padding: 0px;
    }
    
    #options-menu {
      margin-top: 25px;
    }
    
    .ui-menu-item .ui-menu-item-wrapper {
      display: table-cell;
      vertical-align: top;
      padding: 1em 2px;
    }
    
    .ui-menu-item .ui-menu-item-wrapper.ui-state-active {
      margin: 0;
      border-width: 1px 0px 1px 0px;
      border-color: #cccccc;
      background-color: #e4ebf1;
      color: #000;
    }
    
    .ui-menu-item .ui-menu-item-wrapper.ui-state-active.short {
      color: #2e6d99;
    }
    
    .ui-menu-item div.ui-menu-item-wrapper {
      width: 290px;
    }
    
    .ui-menu-item .short {
      color: #2e6d99;
      font-weight: strong;
      width: 30px;
      padding-left: 0.5em;
      position: relative;
    }
    
    .ui-menu-item .price {
      font-weight: strong;
      width: 75px;
      margin-right: -6px;
    }
    
    .overflow {
      height: 150px;
    }
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    
    <div class="container">
      <label for="options">Select an Option:</label>
      <select id="options">
        <optgroup label="PREFERRED OPTIONS">
          <option data-short="L" data-price="$0.00">Standard Screw Adjustment dkjsahdksajd sdhsdl sdshad ;sldh sd;lsa d;lsajd</option>
          <option data-short="K" data-price="$0.00">Standard Screw Adjustment</option>
        </optgroup>
        <optgroup label="STANDARD OPTIONS">
          <option data-short="C" data-price="$5.00">Tamper Resistant - Factory Set</option>
          <option data-short="K" data-price="$6.00">Handknob</option>
        </optgroup>
        <optgroup label="ADDITIONAL OPTIONS">
          <option data-short="F" data-price="$4.00">Hex Head Screw with Locknut</option>
          <option data-short="G" data-price="$4.00">Hex Head Screw with Locknut</option>
          <option data-short="H" data-price="$4.00">Hex Head Screw with Locknut</option>
        </optgroup>
      </select>
    </div>

    or fiddle: http://jsfiddle.net/beaver71/h5s8o0kb/