Как добавить возможность выпадающего списка?

Я создал список списка, содержащий некоторые данные о странах (сгруппированных по субрегионам, каждая страна содержит следующие данные: название, столица, население и площадь). Теперь я хотел бы добавить возможность скрывать или показывать все страны, входящие в его субрегион. Например, после нажатия на субрегион Северная Америка должны появиться все страны, принадлежащие NA, или скрыться, если они уже были показаны. Прямо сейчас все, что я могу сделать, это показать весь список субрегионов со всеми его странами, и я понятия не имею, как добавить возможность раскрывающегося списка. Буду крайне признателен за помощь.

Ниже приведен исходный код того, что я смог сделать.

let div = document.createElement('div');
document.body.appendChild(div);
let ul = document.createElement('ul');

div.appendChild(ul);

async function f() {
    //fetching and sorting data by regions and subregions
    const res = await fetch("https://restcountries.com/v3.1/all");
    const data = await res.json();
    data.sort((a, b) => {
        if (a.region > b.region) return 1;
        else if (a.region < b.region) return -1
        else {
            if (a.subregion > b.subregion) return 1;
            else return -1;
        }
    })
    //count no of subregions and totals of subregion area and population data
    var prevSR = null;
    var cntSR = 0;
    var subregPop = [];
    var subregArea = [];
    var localPop = 0;
    var localArea = 0;
    for (const x of data) {
        if (prevSR != x.subregion) {
            cntSR += 1;
            prevSR = x.subregion;
            subregPop.push(localPop);
            subregArea.push(localArea);
            localArea = 0;
            localPop = 0;
        }
        localArea += x.area;
        localPop += x.population;
    }
    //loop to upload data to lists
    var i = 0
    prevSubregion = data[0].subregion;
    for (var a = 0; a < cntSR; a++) {
        //creating subregion
        let li = createSubregion(data[i].subregion, subregPop[a + 1], subregArea[a + 1]);
        let subOl = document.createElement('ol');

        while (prevSubregion == data[i].subregion) {
            //creating country
            prevSubregion = data[i].subregion;
            subLi = createCountry(data[i].name.common, data[i].capital, data[i].area, data[i].population);
            subOl.appendChild(subLi);
            i += 1;
        }
        prevSubregion = data[i].subregion;
        li.appendChild(subOl);
        ul.appendChild(li);
    }

}

function createSubregion(name, population, area) {
    var li = document.createElement("li");
    li.setAttribute("class", "subregion");

    var header = document.createElement("div");
    header.setAttribute("class", "subregion-header disp-flex");

    var nameDiv = document.createElement("div");

    var nameh2 = document.createElement("h2");
    nameh2.innerText = name;

    nameDiv.appendChild(nameh2);
    header.append(nameDiv);

    var emptyDiv = document.createElement("div");
    header.appendChild(emptyDiv);

    var populationDiv = document.createElement("div");
    var populationh2 = document.createElement("h3");
    populationh2.innerText = population;

    populationDiv.appendChild(populationh2);
    header.append(populationDiv);

    var areaDiv = document.createElement("div");
    var areah2 = document.createElement("h3");
    areah2.innerText = area;

    areaDiv.appendChild(areah2);
    header.append(areaDiv);

    li.appendChild(header);
    return li;
}

function createCountry(name, capital, area, population) {
    var country = document.createElement("li");
    country.setAttribute("class", "country disp-flex")

    var namediv = document.createElement("div");
    var nameh4 = document.createElement("h4");
    nameh4.innerText = name;
    namediv.appendChild(nameh4);
    country.appendChild(namediv);

    var capitaldiv = document.createElement("div");
    var capitalh4 = document.createElement("h4");
    capitalh4.innerText = capital;
    capitaldiv.appendChild(capitalh4);
    country.appendChild(capitaldiv);

    var popdiv = document.createElement("div");
    var poph4 = document.createElement("h4");
    poph4.innerText = population;
    popdiv.appendChild(poph4);
    country.appendChild(popdiv);

    var areadiv = document.createElement("div");
    var areah4 = document.createElement("h4");
    areah4.innerText = area;
    areadiv.appendChild(areah4);
    country.appendChild(areadiv);


    return country;
}

f();
body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background-color: aliceblue;
    font-family: 'Open Sans', Arial;
    font-size: 18px;
}
header{
    display:flex;
    justify-content: space-between;
    padding: 22px 0;
    color:rgb(5, 5, 5);
}
ul {
    list-style: none;
    list-style-type: none;
    outline: 2px solid #ddd;
    padding: 1rem 2rem;
    border-radius: 0.5rem;
    list-style-position: inside;
    color: blue;
}

ul ol { 
    color: rgb(197, 105, 18);
    list-style: none;
    list-style-type: none;
    font-size: .9em;
    margin: 0.4rem 0;
}
.country{
    display: flex;
    justify-content: space-between;
}
.disp-flex{
    display:flex;
    justify-content: space-between;
}

.disp-flex > div{
    width:23%;
    padding:15px 0px;
}


.subregion-header>div:nth-child(1){
    position: relative;
    left:30px;
}
<!DOCTYPE html>
<html lang = "en">

<head>
    <meta charset = "UTF-8">
    <meta http-equiv = "X-UA-Compatible" content = "IE=edge">
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel = "stylesheet" href = "style.css">
</head>

<body>
    <main class = "container">
        <header>
            <div id = "name">
                <h1>Name-</h1>
            </div>
            <div id = "capital">
                <h1>Capital-</h1>
            </div>
            <div id = "population">
                <h1>Population-</h1>
            </div>
            <div id = "area">
                <h1>Area</h1>
            </div>

        </header>

        <script src = "script.js"></script>
    </main>
</body>

</html>

Во-вторых, но не так важно, как во-первых, мне также нужно было бы добавить функцию сортировки и фильтрации каждого столбца после нажатия элемента div в самом верху. Так, например, после нажатия AREA в разделе заголовка страны должны быть отсортированы по их области. И опция фильтра, позволяющая показывать только страны, которые, например, начинаются с буквы «А».

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете сначала сгруппировать субрегионы, например,

const subRegions = data.reduce((r, a) => {
    r[a.subregion] = r[a.subregion] || [];
    r[a.subregion].push(a);
    return r;
}, {});

А затем создайте элемент выбора и введите текст и значение соответственно.

Затем обработайте onchange и получите данные выбранного субрегиона, а не все сразу, как subRegions[subRegionName] .

Разветвленный пример:

let div = document.createElement('div');
document.body.appendChild(div);
let ul = document.createElement('ul');

div.appendChild(ul);

async function f() {
    //fetching and sorting data by regions and subregions
    const res = await fetch("https://restcountries.com/v3.1/all");
    const data = await res.json();
    data.sort((a, b) => {
        if (a.region > b.region) return 1;
        else if (a.region < b.region) return -1
        else {
            if (a.subregion > b.subregion) return 1;
            else return -1;
        }
    });
    
    const container = document.getElementById('container');
    const select = document.createElement('select');
    const olWrapper = document.getElementById('listWrapper');   
    const subRegionWrapper = document.getElementById('subRegionWrapper');

    const subRegions = data.reduce((r, a) => {
        r[a.subregion] = r[a.subregion] || [];
        r[a.subregion].push(a);
        return r;
    }, {});

   const dropdownValues = Object.keys(subRegions);
    const firstOption = document.createElement('option');
     firstOption.value = -1;
     firstOption.text = "Select a Subregion";
     select.appendChild(firstOption);
    dropdownValues.forEach(item => {
      const option = document.createElement('option');
      option.value = item;
      option.text = item;
      select.appendChild(option);
    });
  
 container.appendChild(select);

 select.onchange = (e) => {
   olWrapper.innerHTML = '';
   const subRegionName = e.target.value;
   const filteredValues = subRegions[subRegionName];
   const totalArea = filteredValues.reduce((acc, curr) => acc+curr.area,0);
   const totalPopulation = filteredValues.reduce((acc, curr) => acc+curr.population,0);
   const li = createSubregion(subRegionName, totalPopulation, totalArea);
   ul.innerHTML = '';
   ul.appendChild(li);
   subRegionWrapper.appendChild(ul);

    filteredValues.forEach(item => {
      const subLi = createCountry(item.name.common, item.capital, item.area, item.population);
      const subOl = document.createElement('ol');
      subOl.appendChild(subLi);
      olWrapper.appendChild(subOl);
    })     
 };

}

function createSubregion(name, population, area) {
    var li = document.createElement("li");
    li.setAttribute("class", "subregion");

    var header = document.createElement("div");
    header.setAttribute("class", "subregion-header disp-flex");

    var nameDiv = document.createElement("div");

    var nameh2 = document.createElement("h2");
    nameh2.innerText = name;

    nameDiv.appendChild(nameh2);
    header.append(nameDiv);

    var emptyDiv = document.createElement("div");
    header.appendChild(emptyDiv);

    var populationDiv = document.createElement("div");
    var populationh2 = document.createElement("h3");
    populationh2.innerText = population;

    populationDiv.appendChild(populationh2);
    header.append(populationDiv);

    var areaDiv = document.createElement("div");
    var areah2 = document.createElement("h3");
    areah2.innerText = area;

    areaDiv.appendChild(areah2);
    header.append(areaDiv);

    li.appendChild(header);
    return li;
}

function createCountry(name, capital, area, population) {
    var country = document.createElement("li");
    country.setAttribute("class", "country disp-flex")

    var namediv = document.createElement("div");
    var nameh4 = document.createElement("h4");
    nameh4.innerText = name;
    namediv.appendChild(nameh4);
    country.appendChild(namediv);

    var capitaldiv = document.createElement("div");
    var capitalh4 = document.createElement("h4");
    capitalh4.innerText = capital;
    capitaldiv.appendChild(capitalh4);
    country.appendChild(capitaldiv);

    var popdiv = document.createElement("div");
    var poph4 = document.createElement("h4");
    poph4.innerText = population;
    popdiv.appendChild(poph4);
    country.appendChild(popdiv);

    var areadiv = document.createElement("div");
    var areah4 = document.createElement("h4");
    areah4.innerText = area;
    areadiv.appendChild(areah4);
    country.appendChild(areadiv);


    return country;
}

f();
body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background-color: aliceblue;
    font-family: 'Open Sans', Arial;
    font-size: 18px;
}
header{
    display:flex;
    justify-content: space-between;
    padding: 22px 0;
    color:rgb(5, 5, 5);
}
ul {
    list-style: none;
    list-style-type: none;
    outline: 2px solid #ddd;
    padding: 1rem 2rem;
    border-radius: 0.5rem;
    list-style-position: inside;
    color: blue;
}

ul ol { 
    color: rgb(197, 105, 18);
    list-style: none;
    list-style-type: none;
    font-size: .9em;
    margin: 0.4rem 0;
}
.country{
    display: flex;
    justify-content: space-between;
}
.disp-flex{
    display:flex;
    justify-content: space-between;
}

.disp-flex > div{
    width:23%;
    padding:15px 0px;
}


.subregion-header>div:nth-child(1){
    position: relative;
    left:30px;
}
<!DOCTYPE html>
<html lang = "en">

<head>
    <meta charset = "UTF-8">
    <meta http-equiv = "X-UA-Compatible" content = "IE=edge">
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel = "stylesheet" href = "style.css">
</head>

<body>
    <main class = "container">
        <header>
            <div id = "name">
                <h1>Name-</h1>
            </div>
            <div id = "capital">
                <h1>Capital-</h1>
            </div>
            <div id = "population">
                <h1>Population-</h1>
            </div>
            <div id = "area">
                <h1>Area</h1>
            </div>

        </header>

      
      <div id = "container"></div>
      <div id = "subRegionWrapper"> </div>
      <div id = "listWrapper"></div>
     </script>
    </main>
</body>

</html>

Обновлять:

Вот обновленная версия, в которой каждый субрегион сгруппирован в виде аккордеона, и при переключении отображаются соответствующие страны в субрегионе.

let div = document.createElement('div');
document.body.appendChild(div);
let ul = document.createElement('ul');

div.appendChild(ul);

async function f() {
    //fetching and sorting data by regions and subregions
    const res = await fetch("https://restcountries.com/v3.1/all");
    const data = await res.json();
    data.sort((a, b) => {
        if (a.region > b.region) return 1;
        else if (a.region < b.region) return -1
        else {
            if (a.subregion > b.subregion) return 1;
            else return -1;
        }
    });
    
    const container = document.getElementById('container');
    const accordion = document.createElement('div');
    const olWrapper = document.getElementById('listWrapper');   
    const subRegionWrapper = document.getElementById('subRegionWrapper');

    const subRegions = data.reduce((r, a) => {
        r[a.subregion] = r[a.subregion] || [];
        r[a.subregion].push(a);
        return r;
    }, {});

   const dropdownValues = Object.entries(subRegions);
    dropdownValues.forEach(subRegion => {
      const accordionWrapper = document.createElement('div');
      const panel = document.createElement('div');
      panel.classList.add('panel');
      accordionWrapper.classList.add('accordion');

      const totalArea = subRegion[1].reduce((acc, curr) => acc+curr.area,0);
      const totalPopulation = subRegion[1].reduce((acc, curr) => acc+curr.population,0);
      const li = createSubregion(subRegion[0], totalPopulation, totalArea);

      accordionWrapper.appendChild(li);
      accordion.appendChild(accordionWrapper);

      subRegion[1].forEach(item => {
          const subLi = createCountry(item.name.common, item.capital, item.area, item.population);
          const subOl = document.createElement('ol');
          subOl.appendChild(subLi);
          panel.appendChild(subOl);
          accordion.appendChild(panel);
      });

     accordionWrapper.addEventListener('click', function() {
        this.classList.toggle("active");
        const panel = this.nextElementSibling;
        if (panel.style.display === "block") {
          panel.style.display = "none";
        } else {
          panel.style.display = "block";
        }
     });
    });
  
  container.appendChild(accordion);
}

function createSubregion(name, population, area) {
    var li = document.createElement("li");
    li.setAttribute("class", "subregion");

    var header = document.createElement("div");
    header.setAttribute("class", "subregion-header disp-flex");

    var nameDiv = document.createElement("div");

    var nameh2 = document.createElement("h2");
    nameh2.innerText = name;

    nameDiv.appendChild(nameh2);
    header.append(nameDiv);

    var emptyDiv = document.createElement("div");
    header.appendChild(emptyDiv);

    var populationDiv = document.createElement("div");
    var populationh2 = document.createElement("h3");
    populationh2.innerText = population;

    populationDiv.appendChild(populationh2);
    header.append(populationDiv);

    var areaDiv = document.createElement("div");
    var areah2 = document.createElement("h3");
    areah2.innerText = area;

    areaDiv.appendChild(areah2);
    header.append(areaDiv);

    li.appendChild(header);
    return li;
}

function createCountry(name, capital, area, population) {
    var country = document.createElement("li");
    country.setAttribute("class", "country disp-flex")

    var namediv = document.createElement("div");
    var nameh4 = document.createElement("h4");
    nameh4.innerText = name;
    namediv.appendChild(nameh4);
    country.appendChild(namediv);

    var capitaldiv = document.createElement("div");
    var capitalh4 = document.createElement("h4");
    capitalh4.innerText = capital;
    capitaldiv.appendChild(capitalh4);
    country.appendChild(capitaldiv);

    var popdiv = document.createElement("div");
    var poph4 = document.createElement("h4");
    poph4.innerText = population;
    popdiv.appendChild(poph4);
    country.appendChild(popdiv);

    var areadiv = document.createElement("div");
    var areah4 = document.createElement("h4");
    areah4.innerText = area;
    areadiv.appendChild(areah4);
    country.appendChild(areadiv);


    return country;
}

f();
body {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    background-color: aliceblue;
    font-family: 'Open Sans', Arial;
    font-size: 18px;
}
header{
    display:flex;
    justify-content: space-between;
    padding: 22px 0;
    color:rgb(5, 5, 5);
}
ul {
    list-style: none;
    list-style-type: none;
    outline: 2px solid #ddd;
    padding: 1rem 2rem;
    border-radius: 0.5rem;
    list-style-position: inside;
    color: blue;
}

ul ol { 
    color: rgb(197, 105, 18);
    list-style: none;
    list-style-type: none;
    font-size: .9em;
    margin: 0.4rem 0;
}
.country{
    display: flex;
    justify-content: space-between;
}
.disp-flex{
    display:flex;
    justify-content: space-between;
}

.disp-flex > div{
    width:23%;
    padding:15px 0px;
}


.subregion-header>div:nth-child(1){
    position: relative;
    left:30px;
}

.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
  margin: 15px 2px;
}

.accordion li {
  list-style-type: none;
}

.active, .accordion:hover {
  background-color: #ccc; 
}

.panel {
  padding: 0 18px;
  display: none;
  background-color: white;
  overflow: hidden;
}
<!DOCTYPE html>
<html lang = "en">

<head>
    <meta charset = "UTF-8">
    <meta http-equiv = "X-UA-Compatible" content = "IE=edge">
    <meta name = "viewport" content = "width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel = "stylesheet" href = "style.css">
</head>

<body>
    <main class = "container">
        <header>
            <div id = "name">
                <h1>Name-</h1>
            </div>
            <div id = "capital">
                <h1>Capital-</h1>
            </div>
            <div id = "population">
                <h1>Population-</h1>
            </div>
            <div id = "area">
                <h1>Area</h1>
            </div>

        </header>

      
      <div id = "container"></div>
      <div id = "subRegionWrapper"> </div>
      <div id = "listWrapper"></div>
     </script>
    </main>
</body>

</html>

ОК, это действительно приятно и прекрасно работает. Но мне нужно, чтобы это вело себя так, как на картинке, связанной здесь:codehim.com/menu/… Чтобы вы могли открывать пару субрегионов одновременно. Конечно, имея разные субрегионы вместо профиля, сообщения, настроек и т. д.

fantomx775 15.11.2022 19:09

@ fantomx775, смотрите обновленный ответ вместе с примером.

Maniraj Murugan 16.11.2022 03:43

это выглядит действительно хорошо, спасибо. Можно ли добавить возможность сортировки и фильтрации? Например, щелчок по области в разделе заголовка отсортирует страны по области, а затем щелчок по имени отсортирует их по областям и именам, потому что были нажаты обе страны. Я имею в виду одновременное использование разных параметров сортировки и фильтрации. Параметр фильтрации может позволить отображать только страны, соответствующие выражению в фильтре, поэтому, например, при вводе «Eth» в фильтре имен должна отображаться только Эфиопия в Восточной Африке, а при вводе «Par» в столицах должна отображаться Франция в Западной Европе.

fantomx775 17.11.2022 10:02

@ fantomx775, это выходит за рамки вашего текущего вопроса. Если вам нужны дополнительные вещи, поднимите для этого новый вопрос. Удачного кодирования!

Maniraj Murugan 17.11.2022 10:05

Хорошо, тогда я задам новый вопрос, спасибо

fantomx775 17.11.2022 10:41

@ fantomx775, пожалуйста, примите ответ, если он решит вашу проблему в этом вопросе.

Maniraj Murugan 17.11.2022 10:43

Я попытался добавить возможность сортировки и фильтрации в Ваш код выше, но не могу этого сделать. Данные не сортируются для меня, и кажется, что единственный раз, когда мне разрешено сортировать, это в начале скрипта, когда вызывается функция f. Ты поможешь мне с этим? Заранее спасибо.

fantomx775 20.11.2022 12:57

@ fantomx775, не могли бы вы добавить более подробную информацию о том, где вы хотите добавить функцию сортировки?

Maniraj Murugan 21.11.2022 08:54

Функциональность сортировки должна быть назначена каждому из 4 элементов в разделе заголовка (Имя, Столица, Население и Площадь). Я хочу сделать так, чтобы после однократного щелчка, например, по имени, данные сортировались (по возрастанию) по имени, а после повторного щелчка по имени данные должны быть отсортированы в обратном порядке к предыдущей сортировке (по убыванию) и т. д. . И я хотел бы сделать возможным сортировку по паре столбцов одновременно, поэтому, например, после нажатия «Область» и «Столица» данные должны быть отсортированы как по площади, так и по столице.

fantomx775 21.11.2022 16:22

@ fantomx775, вы спрашиваете больше, и Stackoverflow не является бесплатной службой кодирования. Возможно, некоторые другие могут помочь вам в этой функциональности здесь, в SO. Удачного кодирования!

Maniraj Murugan 22.11.2022 03:46

Другие вопросы по теме