Skip to content

Instantly share code, notes, and snippets.

@akhsiM
Created December 7, 2020 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akhsiM/316d944bef1fe3a2f9fd8469525ecf8c to your computer and use it in GitHub Desktop.
Save akhsiM/316d944bef1fe3a2f9fd8469525ecf8c to your computer and use it in GitHub Desktop.
function showMultilevelDropdownMenu(title, elementId, data, nameKey, valueKey, childrenKey) {
/*
This function can be used to create a multilevel dropdown menu.
It needs the following arguments:
- title: title of the main Dropdown Button
- elementId: Where the dropdown menu will be generated within.
- data: array of JS object, with the following attributes:
- nameKey: this attribute will be used as the displayed innerHTML/ text of the menu option
- valueKey: this attribute will be used as the "value" attribute of the menu option
(useful for form submission)
- childrenKey: this attribute should contain other JS object of same type.
*/
function createDropdownOption(object, containerElement, childrenKey) {
// This function will be nested though the object's children as well
function dropDownItem(value, name) {
// Create <a> dropdown-item element
let item = document.createElement("a");
item.className = "dropdown-item";
item.setAttribute("value", value);
item.innerHTML = name;
return item;
}
var option = dropDownItem(object[valueKey], object[nameKey]);
var listing = document.createElement("li");
listing.appendChild(option);
// Iterate through children and children of children..
let children = object[childrenKey];
if (children.length > 0) {
// add class to parent li element
listing.className += "dropdown-submenu ";
// add fancy arrow element to the right
let caret = document.createElement("span");
var caretClassNames = "text-muted small glyphicon pull-right ",
caretDown = caretClassNames + "glyphicon-triangle-bottom ",
caretRight = caretClassNames + "glyphicon-triangle-right ";
caret.className = caretDown;
option.appendChild(caret);
listing.addEventListener("mouseover", function () {
this.querySelector(".pull-right").className = caretRight;
});
listing.addEventListener("mouseleave", function () {
this.querySelector(".pull-right").className = caretDown;
});
// Create a nested ul element to contain children
let childElement = document.createElement("ul");
childElement.className = "dropdown-menu nested-dropdown-menu";
for (var i = 0; i < children.length; i++) {
createDropdownOption(children[i], childElement, childrenKey);
}
listing.appendChild(childElement);
}
// Add li element to provided ul container element
containerElement.appendChild(listing);
}
// Create Main Elements for the dropdown menu
// First, the button
let mainBtn = document.createElement("button");
mainBtn.className = "btn btn-default dropdown-toggle multi-level-dropdown";
mainBtn.setAttribute("type", "button");
mainBtn.setAttribute("data-toggle", "dropdown");
mainBtn.id = "enquiry-topic-categories-mainBtn";
mainBtn.innerHTML = title;
// Then, the actual dropdown menu
let mainListElement = document.createElement("ul");
mainListElement.className = "dropdown-menu";
mainListElement.id = "enquiry-topics";
// Iterate through the nested array and add elements to the dropdown menu
for (var i = 0; i < data.length; i++) {
createDropdownOption(data[i], mainListElement, childrenKey);
}
document.getElementById(elementId).appendChild(mainBtn);
document.getElementById(elementId).appendChild(mainListElement);
}
@akhsiM
Copy link
Author

akhsiM commented Dec 7, 2020

use it like so:

document.addEventListener("DOMContentLoaded", function () {
  showMultilevelDropdownMenu("Enquiry Topics", "here", data, "name", "id", "children");
});

with the following styles:

      .dropdown-submenu {
        position: relative;
        display: flex;
      }
      
      .dropdown-submenu .nested-dropdown-menu {
        top: 0;
        left: 100%;
        margin-top: -1px;
      }

      .dropdown-submenu:hover > .nested-dropdown-menu {
        display: block;
      }

assuming the data is like so:

var data = [
  {
    id: 1546,
    name: "Coronavirus Support",
    level: 1,
    displayOrder: 1,
    parentId: null,
    children: [
      {
        id: 1548,
        name: "COVID-19 Student Support Grant",
        level: 2,
        displayOrder: 1,
        parentId: 1546,
        children: [],
      },
      {
        id: 1549,
        name: "TESt",
        level: 2,
        displayOrder: 2,
        parentId: 1546,
        children: [
          {
            id: 1550,
            name: "test est test etst",
            level: 3,
            displayOrder: 1,
            parentId: 1549,
            children: [],
          },
        ],
      },
      {
        id: 1551,
        name: "ok",
        level: 2,
        displayOrder: 3,
        parentId: 1546,
        children: [],
      },
    ],
  },
  {
    id: 1526,
    name: "Course application, offer and acceptance",
    level: 1,
    displayOrder: 2,
    parentId: null,
    children: [
      {
        id: 1527,
        name: "My application status",
        level: 2,
        displayOrder: 1,
        parentId: 1526,
        children: [],
      },
      {
        id: 1528,
        name: "Accept my offer",
        level: 2,
        displayOrder: 2,
        parentId: 1526,
        children: [],
      },
      {
        id: 1529,
        name: "Confirmation of Enrolment (CoE)",
        level: 2,
        displayOrder: 3,
        parentId: 1526,
        children: [],
      },
      {
        id: 1530,
        name: "Overseas Student Health Cover (OSHC)",
        level: 2,
        displayOrder: 4,
        parentId: 1526,
        children: [],
      },
      {
        id: 1531,
        name: "Defer my offer",
        level: 2,
        displayOrder: 5,
        parentId: 1526,
        children: [],
      },
      {
        id: 1532,
        name: "Offer lapse date",
        level: 2,
        displayOrder: 6,
        parentId: 1526,
        children: [],
      },
      {
        id: 1533,
        name: "Credit (for prior study)",
        level: 2,
        displayOrder: 7,
        parentId: 1526,
        children: [],
      },
    ],
  },
]

@akhsiM
Copy link
Author

akhsiM commented Dec 7, 2020

Note: the main element needs class="dropdown"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment