代码之家  ›  专栏  ›  技术社区  ›  Millhorn

如何重置自定义下拉列表,以便在附加转义事件后显示菜单?

  •  0
  • Millhorn  · 技术社区  · 5 年前

    我有一个自定义的下拉菜单。除了一个区域外,我已经能够处理大部分的无障碍性。当菜单打开时,我按了escape键,如果我使用键盘导航回菜单,我就无法将其恢复。

    此外,当我按下escape键时,伪before类不会被删除。我不知道如何瞄准那个伪类。

    如果该菜单被导航回,我如何将其带回?

    如何针对before伪类?

    for (const dropdown of document.querySelectorAll(
      ".custom__select-wrapper:not(.clearFilter)"
    )) {
      dropdown.addEventListener("click", function () {
        this.querySelector(".custom__select").classList.toggle("open");
      });
    }
    
    for (const option of document.querySelectorAll(".custom__option")) {
      option.addEventListener("click", function () {
        if (!this.classList.contains("selected")) {
          this.parentNode
            .querySelector(".custom__option.selected")
            .classList.remove("selected");
          this.classList.add("selected");
          this.closest(".custom__select").querySelector(
            ".custom__select-trigger h6"
          ).textContent = this.textContent;
          if (this.getAttribute("data-type")) {
            current_story = this.dataset["type"];
          }
        }
      });
    }
    
    window.addEventListener("click", function (e) {
      for (const select of document.querySelectorAll(".custom__select")) {
        if (!select.contains(e.target)) {
          select.classList.remove("open");
        }
      }
    });
    
    let dropdownMenu = document.querySelectorAll('.custom__options');
    let i;
    window.onkeyup = function (event) {
      if (event.keyCode == 27) {
        for (let i = 0; i < dropdownMenu.length; i++) {
          dropdownMenu[i].style.visibility = 'hidden';
        }
      }
    }
    @charset "UTF-8";
    nav ul {
      list-style-type: none;
      display: flex;
      flex-direction: row;
      width: 100%;
      justify-content: space-evenly;
    }
    
    .content {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    button.clear {
      border: 0;
      background: #fff;
    }
    
    #selectedFilter {
      color: #005fec;
    }
    
    ul {
      padding-left: 0;
      margin: 0;
    }
    
    .filter {
      padding-right: 15px;
      padding-left: 15px;
      margin-bottom: 2rem;
      display: flex;
      flex-direction: column;
    }
    @media (min-width: 768px) {
      .filter__settings {
        display: flex;
        flex-direction: row;
        border-top: 1px solid #E0E5EC;
        border-bottom: 1px solid #E0E5EC;
      }
    }
    
    .custom__select {
      position: relative;
      display: flex;
      flex-direction: column;
    }
    @media (min-width: 768px) {
      .custom::before, .custom__options {
        transition: all 0.2s ease-in;
      }
    }
    .custom__select-wrapper {
      position: relative;
      user-select: none;
      padding: 0;
      border-bottom: 1px solid #E0E5EC;
    }
    .custom__select-wrapper:last-child {
      border: 0;
    }
    .custom__select-wrapper.clearFilter {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    .custom__select-wrapper .selected-clearFilter {
      position: relative;
      user-select: none;
      padding: 1rem 0 !important;
    }
    @media (min-width: 768px) {
      .custom__select-wrapper {
        padding: 0 2em;
        border: 0;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .custom__select-wrapper:first-child, .custom__select-wrapper:last-child {
        padding: 0;
      }
    }
    .custom__select-wrapper h6 {
      padding: 20px 3px;
      color: #62668C;
      font-weight: 300;
    }
    .custom__select-trigger {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: space-between;
      cursor: pointer;
    }
    @media (min-width: 768px) {
      .custom__select-trigger {
        justify-content: space-evenly;
        margin-right: auto;
      }
    }
    .custom__select-wrapper h6, .custom__select-trigger h6 {
      font-size: 0.75rem;
      line-height: 0.75rem;
      letter-spacing: 1px;
      text-transform: uppercase;
      padding: 20px 0;
    }
    .custom__select-trigger h6 {
      color: #005fec;
      font-weight: 900;
    }
    .custom__select-wrapper #selectedFilter {
      font-size: 12px;
      line-height: 12px;
      letter-spacing: 1px;
      text-transform: uppercase;
      color: #005fec;
      font-weight: 800;
      padding: 0;
    }
    .custom__select button, .custom__option button {
      background: transparent;
      border-radius: 4px;
      border: 0;
    }
    .custom__select button *, .custom__option button * {
      position: relative;
    }
    .custom__select button:focus, .custom__option button:focus {
      outline: none;
    }
    .custom__select button:before, .custom__option button:before {
      content: "";
      position: absolute;
      border: solid 0px #005fec;
      top: 0px;
      bottom: 0px;
      left: 0px;
      right: 0px;
      opacity: 0;
      transition: all 150ms;
      transition-timing-function: ease-in-out;
      border-radius: 4px;
      filter: blur(4px);
    }
    .custom__select button:focus-visible:before, .custom__option button:focus-visible:before {
      content: "";
      position: absolute;
      border: solid 2px #005fec;
      top: -8px;
      bottom: -8px;
      left: -8px;
      right: -8px;
      opacity: 1;
      filter: blur(0px);
    }
    @media (min-width: 768px) {
      .custom__select button, .custom__option button {
        color: white;
      }
    }
    .custom__option button::before {
      border: solid 0px white;
    }
    .custom__option button:focus-visible::before {
      border: solid 2px white;
    }
    .custom__options {
      display: none;
      top: 100%;
      left: 0;
      right: 0;
      border-top: 0;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      z-index: 2;
      color: #E0E5EC;
    }
    @media (min-width: 768px) {
      .custom__options {
        display: unset;
        position: absolute;
        background-color: #005fec;
        max-height: 320px;
        overflow-y: scroll;
      }
      .custom__options#storyFilter {
        overflow: hidden;
      }
    }
    .custom__options.active {
      display: block;
      visibility: visible;
      opacity: 1;
      z-index: 10;
    }
    .custom__select-trigger, .custom__option {
      letter-spacing: 1px;
      font-weight: 800;
      color: #005fec;
      border: 0;
      background: transparent;
    }
    @media (min-width: 768px) {
      .custom__select.open::before {
        content: "";
        position: absolute;
        bottom: 0;
        left: 11px;
        border-left: 11px solid transparent;
        border-right: 11px solid transparent;
        border-bottom: 11px solid #005fec;
      }
    }
    .custom__select .custom__options {
      min-width: 15rem;
    }
    .custom__select.open .custom__options {
      display: block;
      opacity: 1;
      visibility: visible;
      pointer-events: all;
      color: #fff;
      min-width: 15rem;
    }
    @media (min-width: 768px) {
      .custom__select.open .custom__options {
        display: unset;
        box-shadow: 0px 12px 30px rgba(0, 0, 0, 0.12);
      }
    }
    .custom__option {
      position: relative;
      display: block;
      padding: 0 22px 0 12px;
      font-weight: 400;
      color: #62668C;
      cursor: pointer;
      font-size: 1rem;
      line-height: 1rem;
      margin: 1.5rem 0;
    }
    @media (min-width: 768px) {
      .custom__option {
        font-size: 1.25rem;
        line-height: 1.25rem;
        color: white;
        font-weight: 300;
        padding: 0 22px 0 20px;
      }
    }
    .custom__option:hover {
      cursor: pointer;
    }
    .custom__option.selected {
      color: #005fec;
    }
    @media (min-width: 768px) {
      .custom__option.selected {
        color: #ffffff;
      }
    }
    .custom__option.selected::before {
      content: "•";
      margin-left: -12px;
      padding-right: 8px;
    }
    
    .empty-state {
      width: 100%;
      display: flex;
      background: #005fec;
      padding: 1rem;
      border-radius: 4px;
      align-items: center;
      margin: 2rem 0.5rem;
    }
    .empty-state h4 {
      color: white;
      font-size: 1rem;
      line-height: 1.5rem;
      font-weight: 300;
      margin-left: 0.5rem;
    }
    .empty-state h4 span {
      color: white;
      text-decoration: underline;
      cursor: pointer;
    }
    
    .arrow {
      position: relative;
      height: 5px;
      width: 3px;
      margin-left: 0.5rem;
      margin-bottom: 0.1rem;
    }
    .arrow::before, .arrow::after {
      content: "";
      position: absolute;
      bottom: 0px;
      width: 0.1rem;
      height: 100%;
      transition: all 0.45s;
    }
    .arrow::before {
      left: 0px;
      transform: rotate(45deg);
      background-color: #005fec;
    }
    @media (min-width: 768px) {
      .arrow::before {
        left: 7px;
      }
    }
    .arrow::after {
      left: -2.5px;
      transform: rotate(-45deg);
      background-color: #005fec;
    }
    @media (min-width: 768px) {
      .arrow::after {
        left: 4.5px;
      }
    }
    
    .open .arrow::before {
      left: 0px;
      transform: rotate(-45deg);
    }
    @media (min-width: 768px) {
      .open .arrow::before {
        left: 7px;
      }
    }
    .open .arrow::after {
      left: -2.5px;
      transform: rotate(45deg);
    }
    @media (min-width: 768px) {
      .open .arrow::after {
        left: 4.5px;
      }
    }
    <div class="container">
      <nav>
        <ul>
          <li><a href="#">Home</a></li>
          <li><a href="#">About</a></li>
          <li><a href="#">Products</a></li>
          <li><a href="#">Sales</a></li>
          <li><a href="#">Contact</a></li>
        </ul>
      </nav>
      <section class="content">
        <h2 class="title">Hello World</h2>
        <h6 class="subtitle">Lorem ipsum dolor sit amet.</h6>
      </section>
      <section class="filter">
        <div class="filter__settings">
          <div class="custom__select-wrapper">
            <h6>filter by</h6>
          </div>
          <div class="custom__select-wrapper">
            <div class="custom__select story-sel selector" role="menubar">
              <button class="custom__select-trigger" aria-haspopup="true" aria-expanded="false" id="storySelector">
                <h6>Story Type</h6>
                <div class="arrow"></div>
              </button>
              <ul class="custom__options dropdown story-selector" id="storyFilter" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
                <li role="menuitem" class="custom__option selected" data-type="all" id="storyItem_all"><button>All</button>
                </li>
                <li role="menuitem" class="custom__option" data-type="news" id="storyItem_nm"><button>News and
                    media</button></li>
                <li role="menuitem" class="custom__option" data-type="analysis" id="storyItem_analysis"><button>Analysis</button></li>
                <li role="menuitem" class="custom__option" data-type="press" id="storyItem_pr"><button>Press
                    releases</button></li>
              </ul>
            </div>
          </div>
          <div class="custom__select-wrapper">
            <div class="custom__select year-sel selector">
              <button type="button" class="custom__select-trigger" id="yearSelector">
                <h6>Year</h6>
                <div class=" arrow"></div>
              </button>
              <ul class="custom__options dropdown year-selector" id="yearSelection" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
                <li role="menuitem" class="custom__option selected" data-year="all"><a>All</a></li>
                <li role="menuitem" class="custom__option" data-year="2021"><button>2021</button></li>
                <li role="menuitem" class="custom__option" data-year="2020"><button>2020</button></li>
                <li role="menuitem" class="custom__option" data-year="2019"><button>2019</button></li>
              </ul>
            </div>
          </div>
        </div>
      </section>
    </div>
    1 回复  |  直到 5 年前
        1
  •  1
  •   Spectric amamoto    5 年前

    你应该循环所有的选择并移除 open 类,而不是将所有选项的可见性设置为“隐藏”。

    for (const dropdown of document.querySelectorAll(
      ".custom__select-wrapper:not(.clearFilter)"
    )) {
      dropdown.addEventListener("click", function () {
        this.querySelector(".custom__select").classList.toggle("open");
      });
    }
    
    for (const option of document.querySelectorAll(".custom__option")) {
      option.addEventListener("click", function () {
        if (!this.classList.contains("selected")) {
          this.parentNode
            .querySelector(".custom__option.selected")
            .classList.remove("selected");
          this.classList.add("selected");
          this.closest(".custom__select").querySelector(
            ".custom__select-trigger h6"
          ).textContent = this.textContent;
          if (this.getAttribute("data-type")) {
            current_story = this.dataset["type"];
          }
        }
      });
    }
    
    window.addEventListener("click", function (e) {
      for (const select of document.querySelectorAll(".custom__select")) {
        if (!select.contains(e.target)) {
          select.classList.remove("open");
        }
      }
    });
    
    let dropdownMenu = document.querySelectorAll('.custom__select');
    let i;
    window.onkeyup = function (event) {
      if (event.keyCode == 27) {
        for (let i = 0; i < dropdownMenu.length; i++) {
          dropdownMenu[i].classList.remove("open");
        }
      }
    }
    @charset "UTF-8";
    nav ul {
      list-style-type: none;
      display: flex;
      flex-direction: row;
      width: 100%;
      justify-content: space-evenly;
    }
    
    .content {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    button.clear {
      border: 0;
      background: #fff;
    }
    
    #selectedFilter {
      color: #005fec;
    }
    
    ul {
      padding-left: 0;
      margin: 0;
    }
    
    .filter {
      padding-right: 15px;
      padding-left: 15px;
      margin-bottom: 2rem;
      display: flex;
      flex-direction: column;
    }
    @media (min-width: 768px) {
      .filter__settings {
        display: flex;
        flex-direction: row;
        border-top: 1px solid #E0E5EC;
        border-bottom: 1px solid #E0E5EC;
      }
    }
    
    .custom__select {
      position: relative;
      display: flex;
      flex-direction: column;
    }
    @media (min-width: 768px) {
      .custom::before, .custom__options {
        transition: all 0.2s ease-in;
      }
    }
    .custom__select-wrapper {
      position: relative;
      user-select: none;
      padding: 0;
      border-bottom: 1px solid #E0E5EC;
    }
    .custom__select-wrapper:last-child {
      border: 0;
    }
    .custom__select-wrapper.clearFilter {
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    .custom__select-wrapper .selected-clearFilter {
      position: relative;
      user-select: none;
      padding: 1rem 0 !important;
    }
    @media (min-width: 768px) {
      .custom__select-wrapper {
        padding: 0 2em;
        border: 0;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .custom__select-wrapper:first-child, .custom__select-wrapper:last-child {
        padding: 0;
      }
    }
    .custom__select-wrapper h6 {
      padding: 20px 3px;
      color: #62668C;
      font-weight: 300;
    }
    .custom__select-trigger {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: space-between;
      cursor: pointer;
    }
    @media (min-width: 768px) {
      .custom__select-trigger {
        justify-content: space-evenly;
        margin-right: auto;
      }
    }
    .custom__select-wrapper h6, .custom__select-trigger h6 {
      font-size: 0.75rem;
      line-height: 0.75rem;
      letter-spacing: 1px;
      text-transform: uppercase;
      padding: 20px 0;
    }
    .custom__select-trigger h6 {
      color: #005fec;
      font-weight: 900;
    }
    .custom__select-wrapper #selectedFilter {
      font-size: 12px;
      line-height: 12px;
      letter-spacing: 1px;
      text-transform: uppercase;
      color: #005fec;
      font-weight: 800;
      padding: 0;
    }
    .custom__select button, .custom__option button {
      background: transparent;
      border-radius: 4px;
      border: 0;
    }
    .custom__select button *, .custom__option button * {
      position: relative;
    }
    .custom__select button:focus, .custom__option button:focus {
      outline: none;
    }
    .custom__select button:before, .custom__option button:before {
      content: "";
      position: absolute;
      border: solid 0px #005fec;
      top: 0px;
      bottom: 0px;
      left: 0px;
      right: 0px;
      opacity: 0;
      transition: all 150ms;
      transition-timing-function: ease-in-out;
      border-radius: 4px;
      filter: blur(4px);
    }
    .custom__select button:focus-visible:before, .custom__option button:focus-visible:before {
      content: "";
      position: absolute;
      border: solid 2px #005fec;
      top: -8px;
      bottom: -8px;
      left: -8px;
      right: -8px;
      opacity: 1;
      filter: blur(0px);
    }
    @media (min-width: 768px) {
      .custom__select button, .custom__option button {
        color: white;
      }
    }
    .custom__option button::before {
      border: solid 0px white;
    }
    .custom__option button:focus-visible::before {
      border: solid 2px white;
    }
    .custom__options {
      display: none;
      top: 100%;
      left: 0;
      right: 0;
      border-top: 0;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      z-index: 2;
      color: #E0E5EC;
    }
    @media (min-width: 768px) {
      .custom__options {
        display: unset;
        position: absolute;
        background-color: #005fec;
        max-height: 320px;
        overflow-y: scroll;
      }
      .custom__options#storyFilter {
        overflow: hidden;
      }
    }
    .custom__options.active {
      display: block;
      visibility: visible;
      opacity: 1;
      z-index: 10;
    }
    .custom__select-trigger, .custom__option {
      letter-spacing: 1px;
      font-weight: 800;
      color: #005fec;
      border: 0;
      background: transparent;
    }
    @media (min-width: 768px) {
      .custom__select.open::before {
        content: "";
        position: absolute;
        bottom: 0;
        left: 11px;
        border-left: 11px solid transparent;
        border-right: 11px solid transparent;
        border-bottom: 11px solid #005fec;
      }
    }
    .custom__select .custom__options {
      min-width: 15rem;
    }
    .custom__select.open .custom__options {
      display: block;
      opacity: 1;
      visibility: visible;
      pointer-events: all;
      color: #fff;
      min-width: 15rem;
    }
    @media (min-width: 768px) {
      .custom__select.open .custom__options {
        display: unset;
        box-shadow: 0px 12px 30px rgba(0, 0, 0, 0.12);
      }
    }
    .custom__option {
      position: relative;
      display: block;
      padding: 0 22px 0 12px;
      font-weight: 400;
      color: #62668C;
      cursor: pointer;
      font-size: 1rem;
      line-height: 1rem;
      margin: 1.5rem 0;
    }
    @media (min-width: 768px) {
      .custom__option {
        font-size: 1.25rem;
        line-height: 1.25rem;
        color: white;
        font-weight: 300;
        padding: 0 22px 0 20px;
      }
    }
    .custom__option:hover {
      cursor: pointer;
    }
    .custom__option.selected {
      color: #005fec;
    }
    @media (min-width: 768px) {
      .custom__option.selected {
        color: #ffffff;
      }
    }
    .custom__option.selected::before {
      content: "•";
      margin-left: -12px;
      padding-right: 8px;
    }
    
    .empty-state {
      width: 100%;
      display: flex;
      background: #005fec;
      padding: 1rem;
      border-radius: 4px;
      align-items: center;
      margin: 2rem 0.5rem;
    }
    .empty-state h4 {
      color: white;
      font-size: 1rem;
      line-height: 1.5rem;
      font-weight: 300;
      margin-left: 0.5rem;
    }
    .empty-state h4 span {
      color: white;
      text-decoration: underline;
      cursor: pointer;
    }
    
    .arrow {
      position: relative;
      height: 5px;
      width: 3px;
      margin-left: 0.5rem;
      margin-bottom: 0.1rem;
    }
    .arrow::before, .arrow::after {
      content: "";
      position: absolute;
      bottom: 0px;
      width: 0.1rem;
      height: 100%;
      transition: all 0.45s;
    }
    .arrow::before {
      left: 0px;
      transform: rotate(45deg);
      background-color: #005fec;
    }
    @media (min-width: 768px) {
      .arrow::before {
        left: 7px;
      }
    }
    .arrow::after {
      left: -2.5px;
      transform: rotate(-45deg);
      background-color: #005fec;
    }
    @media (min-width: 768px) {
      .arrow::after {
        left: 4.5px;
      }
    }
    
    .open .arrow::before {
      left: 0px;
      transform: rotate(-45deg);
    }
    @media (min-width: 768px) {
      .open .arrow::before {
        left: 7px;
      }
    }
    .open .arrow::after {
      left: -2.5px;
      transform: rotate(45deg);
    }
    @media (min-width: 768px) {
      .open .arrow::after {
        left: 4.5px;
      }
    }
    <div class="container">
      <nav>
        <ul>
          <li><a href="#">Home</a></li>
          <li><a href="#">About</a></li>
          <li><a href="#">Products</a></li>
          <li><a href="#">Sales</a></li>
          <li><a href="#">Contact</a></li>
        </ul>
      </nav>
      <section class="content">
        <h2 class="title">Hello World</h2>
        <h6 class="subtitle">Lorem ipsum dolor sit amet.</h6>
      </section>
      <section class="filter">
        <div class="filter__settings">
          <div class="custom__select-wrapper">
            <h6>filter by</h6>
          </div>
          <div class="custom__select-wrapper">
            <div class="custom__select story-sel selector" role="menubar">
              <button class="custom__select-trigger" aria-haspopup="true" aria-expanded="false" id="storySelector">
                <h6>Story Type</h6>
                <div class="arrow"></div>
              </button>
              <ul class="custom__options dropdown story-selector" id="storyFilter" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
                <li role="menuitem" class="custom__option selected" data-type="all" id="storyItem_all"><button>All</button>
                </li>
                <li role="menuitem" class="custom__option" data-type="news" id="storyItem_nm"><button>News and
                    media</button></li>
                <li role="menuitem" class="custom__option" data-type="analysis" id="storyItem_analysis"><button>Analysis</button></li>
                <li role="menuitem" class="custom__option" data-type="press" id="storyItem_pr"><button>Press
                    releases</button></li>
              </ul>
            </div>
          </div>
          <div class="custom__select-wrapper">
            <div class="custom__select year-sel selector">
              <button type="button" class="custom__select-trigger" id="yearSelector">
                <h6>Year</h6>
                <div class=" arrow"></div>
              </button>
              <ul class="custom__options dropdown year-selector" id="yearSelection" aria-label="submenu" role="menu" aria-labelledby="custom-dropdown">
                <li role="menuitem" class="custom__option selected" data-year="all"><a>All</a></li>
                <li role="menuitem" class="custom__option" data-year="2021"><button>2021</button></li>
                <li role="menuitem" class="custom__option" data-year="2020"><button>2020</button></li>
                <li role="menuitem" class="custom__option" data-year="2019"><button>2019</button></li>
              </ul>
            </div>
          </div>
        </div>
      </section>
    </div>