Funkcja rekurencyjna

Funkcja rekurencyjna wykorzystana do przedstawienia danych w postaci drzewiastej.

Przejdź do artykułu

Wybrany element to: Nic jeszcze nie wybrano

Kod użyty w przykładzie.

Pokaż kod HTML
 <!-- W  <head> impor pliku js -->
<script type="module" defer src="script.js"></script>
<!-- ---- -->

<div class="content">
<p>Wybrany element to: <span class="choice">Nic jeszcze nie wybrano</span></p>
<div class="list js-category-tree"></div>
</div>
Pokaż kod CSS
.content {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 50px;
}

.list {
  width: 40%;
  text-align: left;
}

@media (max-width: 900px) {
  .list {
    width: 90%;
  }
}

.list ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.list ul li > ul {
  padding-left: 25px;
}

.list li {
  padding: 5px 8px;
  cursor: pointer;
}

.list li > span {
  padding: 5px 8px;
  border-radius: 5px;
}

.list li:hover > span {
  background-color: var(--secondary-dark-alpha);
}

.list li .empty {
  margin: 5px;
  padding-left: 40px;
  color: var(--secondary);
}

.list li span::before {
  content: "";
  display: inline-block;
  width: 30px;
  height: 30px;
  margin-right: 8px;
  margin-bottom: -6px;
  background-size: contain;
  background-repeat: no-repeat;
}

.list li:has(> .show) span::before {
  background-image: url("folder_open.png");
}

.list li:has(> .hidden) span::before {
  background-image: url("folder_close.png");
}

.list .show {
  display: block;
}

.list .hidden {
  display: none;
}

.list .object {
  padding-left: 15px;
  color: var(--white);
  text-decoration: none;
}

.list .object:hover {
  color: var(--secondary);
  text-decoration: underline;
}
Pokaż kod JavaScript - dane
export const data = [
{
  category: "Elektronika",
  subcategories: [
    {
      category: "Komputery",
      subcategories: [
        {
          category: "Laptopy",
          subcategories: [],
        },
        {
          category: "Komputery stacjonarne",
          subcategories: [],
        },
        {
          category: "Tablety",
          subcategories: [
            {
              category: "8 cali",
              subcategories: [],
              objects: [
                { name: "Model 8-1" },
                { name: "Model 8-2" },
                { name: "Model 8-3" },
              ],
            },
            {
              category: "10 cali",
              subcategories: [],
              objects: [
                { name: "Model 10-1" },
                { name: "Model 10-2" },
                { name: "Model 10-3" },
                { name: "Model 10-4" },
                { name: "Model 10-5" },
              ],
            },
            {
              category: "12 cali",
              subcategories: [],
            },
          ],
          objects: [
            { name: "Promocyjne" }, 
            { name: "Powystawowe" }
          ],
        },
      ],
    },
    {
      category: "Telefony",
      subcategories: [
        {
          category: "Smartfony",
          subcategories: [],
        },
        {
          category: "Telefony stacjonarne",
          subcategories: [],
        },
      ],
    },
    {
      category: "Telewizory",
      subcategories: [
        {
          category: "Telewizory LED",
          subcategories: [],
          objects: [
            { name: "Samsung" }, 
            { name: "LG" }, 
            { name: "Sharp" }
          ],
        },
        {
          category: "Telewizory OLED",
          subcategories: [],
        },
      ],
    },
  ],
},
{
  category: "Rowery",
  subcategories: [],
},
];
Pokaż kod JavaScript
import { data } from "./data.js";

const renderCategoryTree = (list) => {
const ul = document.createElement("ul");

list.forEach((item) => {
  const li = document.createElement("li");
  li.innerHTML = `${item.category}`;
  li.classList.add("js-sublist");
  ul.appendChild(li);

  if (item.subcategories?.length || item.objects?.length) {
    const subUl = renderCategoryTree(item.subcategories);
    li.appendChild(subUl);
    subUl.classList.add("hidden");
  } else {
    const empty = document.createElement("p");
    empty.innerText = "Brak elementów";
    empty.classList.add("hidden", "empty");
    li.appendChild(empty);
  }

  if (item.objects?.length) {
    const ulObject = document.createElement("ul");
    item.objects.forEach((subject, index) => {
      const liObject = document.createElement("li");
      liObject.innerHTML = `${index + 1}. ${
        subject.name
      }`;
      liObject.classList.add("js-object");
      ulObject.appendChild(liObject);
      li.appendChild(ulObject);
      ulObject.classList.add("hidden");
    });
  }
});

return ul;
};

const toggleCategoryTree = () => {
  const sublist = document.querySelectorAll(".js-sublist");
  sublist.forEach((item) => {
    item.addEventListener("click", (event) => {
      event.stopPropagation();
      const subListAll = item.querySelectorAll(":scope > ul, :scope > p");

      subListAll.forEach((subItem) => {
        if (subItem) {
          subItem.classList.toggle("hidden");
          subItem.classList.toggle("show");
        }
      });
    });
  });
};

const clickObiect = (choice) => {
const objectslist = document.querySelectorAll(".js-object");
objectslist.forEach((item) => {
  item.addEventListener("click", (event) => {
    event.stopPropagation();
    choice.innerText = item.textContent;
  });
});
};

const init = () => {
const rootElement = document.querySelector(".js-category-tree");
const choiceElement = document.querySelector(".choice");
rootElement.appendChild(renderCategoryTree(data));
toggleCategoryTree();
clickObiect(choiceElement);
};

init();