Custom Menu
Goal
Examples

Setting the scene

Adding the markup
Adding the scripts
Putting it all together
Last updated


Last updated
<cm-configurator-main ui-style="default" template-uuid="fb825772-66cd-4001-ae46-d537f194d6a2" use-external-menu="true"></cm-configurator-main><div class="menu-controls" id="menu-container">
<!-- Container holds the dynamically rendered menu elements -->
</div>async function initializeMenu() {
// clear the menu container
menuContainer.innerHTML = ""
// load all available parameters
parameterList = cmConfigurator.getParameterList()
for (const parameter of parameterList) {
// create a container element for each parameter
const parameterContainer = htmlToNode(`
<div class="menu-section">
<h3>${parameter.name}</h3>
<div class="parameter-flex" id="menu-parameter-values-container"></div>
</div>
`)
for (const parameterValue of parameter.values) {
// create a button for each possible parameter value
const parameterValueButton = htmlToNode(`
<button class="${parameterValue.id === parameter.value ? "active" : ""}">
${parameterValue.name}
</button>
`)
parameterValueButton.onclick = async (event) => {
updateParameterMenuActiveStates(event.currentTarget)
await cmConfigurator.setParameter(parameter.id, parameter.parameterType, parameterValue.id)
}
parameterContainer.querySelector("#menu-parameter-values-container").appendChild(parameterValueButton)
}
menuContainer.appendChild(parameterContainer)
}
}let cmConfigurator, menuContainer, parameterList
customElements.whenDefined("cm-configurator-main").then(() => {
cmConfigurator = document.querySelector("cm-configurator-main")
// Initialize UI elements
menuContainer = document.getElementById("menu-container")
// Once the configurator has loaded, the menu can be rendered based on the available parameters
cmConfigurator.addEventListener("loadingCompleted", initializeMenu)
// Update the menu when available parameter values changed.
cmConfigurator.addEventListener("configurationLoaded", initializeMenu)
// Update the menu when available parameter values changed through the setParameter API
cmConfigurator.addEventListener("changeCompleted", initializeMenu)
})<!DOCTYPE html>
<html style="height: 100%">
<head>
<link rel="preconnect" href="https://configurator.colormass.com" />
<!-- Load the colormass configurator styles -->
<link href="https://configurator.colormass.com/styles.css" rel="stylesheet" />
<!-- Load the colormass configurator web components -->
<script src="https://configurator.colormass.com/cm-configurator.js" type="module"></script>
<link rel="stylesheet" href="../styles/sample.css" />
<link rel="stylesheet" href="../styles/ui.css" />
<title>Custom Menu | Example</title>
<meta charset="UTF-8" />
<script>
let cmConfigurator, menuContainer, parameterList
customElements.whenDefined("cm-configurator-main").then(() => {
cmConfigurator = document.querySelector("cm-configurator-main")
// Initialize UI elements
menuContainer = document.getElementById("menu-container")
// Once the configurator has loaded, the menu can be rendered based on the available parameters
cmConfigurator.addEventListener("loadingCompleted", initializeMenu)
// Update the menu when available parameter values changed.
cmConfigurator.addEventListener("configurationLoaded", initializeMenu)
// Update the menu when available parameter values changed.
cmConfigurator.addEventListener("changeCompleted", initializeMenu)
})
async function initializeMenu() {
// clear the menu container
menuContainer.innerHTML = ""
// load all available parameters
parameterList = cmConfigurator.getParameterList()
for (const parameter of parameterList) {
// create a container element for each parameter
const parameterContainer = htmlToNode(`
<div class="menu-section">
<h3>${parameter.name}</h3>
<div class="parameter-flex" id="menu-parameter-values-container"></div>
</div>
`)
for (const parameterValue of parameter.values) {
// create a button for each possible parameter value
const parameterValueButton = htmlToNode(`
<button class="${parameterValue.id === parameter.value ? "active" : ""}">
${parameterValue.name}
</button>
`)
parameterValueButton.onclick = async (event) => {
updateParameterMenuActiveStates(event.currentTarget)
await cmConfigurator.setParameter(parameter.id, parameter.parameterType, parameterValue.id)
}
parameterContainer.querySelector("#menu-parameter-values-container").appendChild(parameterValueButton)
}
menuContainer.appendChild(parameterContainer)
}
}
function updateParameterMenuActiveStates(element) {
// remove active class from all siblings
const siblings = element.parentElement.children
for (const sibling of siblings) {
sibling.classList.remove("active")
}
// set active class for clicked element
element.classList.add("active")
}
function htmlToNode(html) {
const template = document.createElement("template")
template.innerHTML = html.trim()
return template.content.firstChild
}
</script>
</head>
<body>
<div class="container">
<div class="menu">
<div class="menu-controls" id="menu-container">
<!-- Container holds the dynamically rendered menu elements -->
</div>
</div>
<div class="configurator-container">
<cm-configurator-main ui-style="default" template-uuid="fb825772-66cd-4001-ae46-d537f194d6a2" use-external-menu="true"></cm-configurator-main>
</div>
</div>
</body>
</html>