Home > Net >  Mimic the behavior of a <select>, <option> with a <ul>, <li>
Mimic the behavior of a <select>, <option> with a <ul>, <li>

Time:04-08

Actually i'm stuck on my dropdown menu. I want to imitate the behavior of a select, option with a ul, li.

If I click on the second li I want it to take the place of the first li without deleting the latter.

Like the behavior of the method appendChild() but without removing the old element.

const listMenu = Array.from(document.querySelectorAll('ul li'))
const menu = document.querySelector('ul')

const arrow = document.querySelector('ul')

let isDisplay = true

function openMenu() {
    listMenu.slice(1).forEach(list => {
        list.style.display = 'block'
        arrow.classList.add('arrow-up')
        isDisplay = false
    })
}

function closeMenu() {
    listMenu.slice(1).forEach(list => {
        list.style.display = 'none'
        arrow.classList.remove('arrow-up')
        isDisplay = true
    })
}

function displayMenu() {
    if (isDisplay) {
        openMenu()
    } else {
        closeMenu()
    }
}

closeMenu()

menu.addEventListener('click', displayMenu)
ul {
    width: 170px;
    list-style-type: none;
    display: flex;
    flex-direction: column;
    color: #fff;
    font-weight: bold;
    font-size: 1.1em;
    position: relative;
    border: 1px solid #901c1c;
    border-radius: 5px;
    padding: 0;
    cursor: pointer;
}

li {
    background-color: #901c1c;
    padding: 20px 20px;
}

li:not(:first-child) {
    position: relative;
}

li:not(:first-child)::before {
    content: "";
    position: absolute;
    top: 0px;
    left: 5px;
    width: 90%;
    height: 1px;
    background-color: rgb(255, 255, 255);
}

ul::after {
    content: "";
    position: absolute;
    right: 25px;
    top: 22px;
    width: 0.6em;
    height: 0.6em;
    border-left: 0.2rem solid rgb(255, 255, 255);
    border-bottom: 0.2rem solid rgb(255, 255, 255);
    transform: rotate(315deg);
}

.arrow-up::after {
    transform: rotate(135deg);
    top: 28px;
}
<ul>
    <li id="popularity">Popularité</li>
    <li id="date">Date</li>
    <li id="title">Titre</li>
</ul>

CodePudding user response:

I hope you were seeking for a way to automate the job of option and select tags by using ul li tags. And I found this helpful when I was attempting to accomplish something similar.And it was accomplished with the use of the jQuery library.

$('.select ul li.option').click(function() {
    $(this).siblings().addBack().children().remove();
    var a = $(this).siblings().toggle();
    $(this).parent().prepend(this);
  })
.select ul li.option {
  background-color: #DEDEDE;
  box-shadow: 0px 1px 0 #DEDEDE, 0px -1px 0 #DEDEDE;
  -webkit-box-shadow: 0px 1px 0 #DEDEDE, 0px -1px 0 #DEDEDE;
  -moz-box-shadow: 0px 1px 0 #DEDEDE, 0px -1px 0 #DEDEDE;
}

.select ul li.option:hover {
  background-color: #B8B8B8;
}

.select ul li.option {
  z-index: 1;
  padding: 5px;
  display: none;
  list-style: none;
}

.select ul li:first-child {
  display: block;
}

.select ul li {
  cursor: default;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
  <ul style="width:150px;">
    <li values="1" >Dropdown one</li>
    <li values="2" >Dropdown two</li>
    <li values="3" >Dropdown three</li>
  </ul>
</div>

CodePudding user response:

Without jQuery you can do something like this, where you toggle a class .open and show specify it in css.

Whenever one clicks on a list item, this item will be prepended to the list and the class .open will be removed from the parent and css specifies to only show the first item of the list:

ul:not(.open) li:not(:first-of-type) {
  display: none;
}

const menu = document.querySelector('.menu');

menu.addEventListener('click', (e)=>{

  let listItem = e.target;
  
  if(menu.classList.contains('open'))
    menu.prepend(listItem);
  
  listItem.closest('ul').classList.toggle('open');
  
})
ul {
    width: 170px;
    list-style-type: none;
    display: flex;
    flex-direction: column;
    color: #fff;
    font-weight: bold;
    font-size: 1.1em;
    position: relative;
    border: 1px solid #901c1c;
    border-radius: 5px;
    padding: 0;
    cursor: pointer;
}

li {
    background-color: #901c1c;
    padding: 20px 20px;
}

li:not(:first-child) {
    position: relative;
}

li:not(:first-child)::before {
    content: "";
    position: absolute;
    top: 0px;
    left: 5px;
    width: 90%;
    height: 1px;
    background-color: rgb(255, 255, 255);
}

ul::after {
    content: "";
    position: absolute;
    right: 25px;
    top: 22px;
    width: 0.6em;
    height: 0.6em;
    border-left: 0.2rem solid rgb(255, 255, 255);
    border-bottom: 0.2rem solid rgb(255, 255, 255);
    transform: rotate(315deg);
    transition: transform .3s;
}

ul.open::after {
  transform: rotate(135deg);
}

.arrow-up::after {
    transform: rotate(135deg);
    top: 28px;
}

ul:not(.open) li:not(:first-of-type) {
  display: none;
}
<ul >
    <li id="popularity">Popularité</li>
    <li id="date">Date</li>
    <li id="title">Titre</li>
</ul>

  • Related