A simple flat sidebar navigation JavaScript to use in TextAreas to enhance page navigation and features
The Flat Sidebar saves real state.
|
How to use
Add a TextArea and edit the HTML. Add the sample html code below and then the provided JavaScript at the end. Just create a new script and copy+paste the code from the sidebar-popup.js into a new JavaScript.
html Example (no navigation grouping)
<DIV id="sidebar" style="FONT-SIZE: 20px; BACKGROUND: #3498db; COLOR: white"></DIV> <span id="sidebar-logo">C. Corp</span> <DIV id="sidebar-nav" > <a>Page 1</a> <a>Page 2</a> <SpotfireControl (repalce with link spotfire control) /> <a>Page 4</a> <a>Page 5</a> <a>Page 6</a> <a>Page 7</a> <a>Page 8</a> </div> <div id="sidebar-nav-icons" >house,user,circle,box,umbrella,music,heart,gear</div> <div id="sidebar-controls"> <div>Control group 1</div> <div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> </div> <div>Control group 2</div> <div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> </div> </div>
html Example (with groups)
<DIV id="sidebar" style="FONT-SIZE: 15px; BACKGROUND: #3498db; COLOR: white"></DIV> <span id="sidebar-logo"> <img src="bffeccd1047746e5bd1a3a11c6048a9d.png"/> </span> <DIV id="sidebar-nav" > <a>Page 1</a> <li> <a>Page 2***</a> <a>Page 3</a> </li> <a>Page 4</a> <li> <a>Page 5</a> <a>Page 6</a> </li> <a>Page 7</a> <li> <a>Page 8</a> </li> </div> <div id="sidebar-nav-icons" >house,user,circle,box,umbrella,music,heart,gear </div> <div id="sidebar-controls" style="border:1px solid black;background:orange"> <div>Control group 1</div> <div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> </div> <div>Control group 2</div> <div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> <div>replace with spotfire control</div> </div> </div>
JavaScript
sidebar-flat.js
sidebar = document.getElementById("sidebar") h=sidebar.parentElement.offsetHeight; bgColor = window.getComputedStyle(document.querySelector(".sfc-text-area")).backgroundColor; hasLogo = document.querySelector("#sidebar-logo"); hasFeathers = typeof feather!="undefined"; template = ` <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" /> <div class="container"> <div class="sidebar-logo"></div> <nav class="side-nav"> <ul class="nav-menu sidebar-nav"></ul> </nav> <div class="sidebar-controls"></div> </div> <style> .sidebar-logo{ text-align:center; padding-top:${hasLogo?0:5}x; } .sidebar-logo img{ text-align:center; margin:0px;padding:0; } /*vertical line under logo*/ .sidebar-logo::after{ display:${hasLogo?"block":"none"}; content:""; padding-top:5px; border-bottom:2px solid ; } /*logo image matches fontSize*/ .sidebar-logo *{ vertical-align:middle; height:${sidebar.style.fontSize} !important; width:unset !important; text-align:center; padding-top:10px; display:initial; width:none; } /*takes entire screen*/ .container { height: ${h}px; } .side-nav .nav-menu { list-style: none; background-color: ${sidebar.style.backgroundColor}; display:contents; } .side-nav .nav-item { position: relative; padding: 10px 20px; } .nav-item.active { background-color: ${bgColor }; /*◄*/ box-shadow: 0px -3px rgba(0, 0, 0, 0.2), 0px 3px rgba(0, 0, 0, 0.2); } .nav-item.active a { color: ${sidebar.style.backgroundColor||"#3498db"} !important; } .nav-item a { text-decoration: none !important; color: ${sidebar.style.color||"white"} !important; } .menu-text { padding: 0 20px; } .side-nav .nav-item.active::before { content: ""; position: absolute; background-color: transparent; bottom: 100%; right: 0; height: 150%; width: 20px; border-bottom-right-radius: 25px; box-shadow: 0 20px 0 0 ${bgColor};/*◄*/ } .side-nav .nav-item.active::after { content: ""; position: absolute; background-color: transparent; top: 100%; right: 0; height: 150%; width: 20px; border-top-right-radius: 25px; box-shadow: 0 -20px 0 0 ${bgColor};/*◄*/ } .icon { margin-right: 15px; } details { padding: 10px; } details > div { padding: 10px 20px 0 10px; display: flex; flex-direction: column; align-items: stretch; } details > div a{ color:${sidebar.style.color} !important; } details .sf-element{ color:${sidebar.style.background} !important; } details .sf-element-dropdown-list-item.sfpc-selected{ color:${sidebar.style.background} !important; background:${sidebar.style.color} !important; } details .sf-element-text-box{ color:${sidebar.style.background} !important; } details .sf-element-dropdown .sf-element-text-box{ color:${sidebar.style.background} !important; } details .sf-element-filter-item .sf-element-text-box, details .sf-element-item-slider, details .sf-element-text-box { color:${sidebar.style.color} !important; } details .sfc-list-box{ background:${sidebar.style.background} !important; } details summary { cursor: pointer; } #sidebar summary { padding-left: 10px; cursor:default; } </style>` sidebar.innerHTML = template //move components (ids) to template placeholders (class names) function moveElement(component,templateComponent){ if(templateComponent!=undefined){ if (component.id == "sidebar-nav") { icons = document.querySelector("#sidebar-nav-icons"); if (hasFeathers && icons) icons = icons.innerText.split(",").map(x=>`<i class="icon" data-feather="${x}"></i>`); if (!hasFeathers && icons) icons = icons.innerText.split(",").map(x=>`<i class="icon fa-solid fa-${x}"></i>`); let i=0; [...document.querySelectorAll("#sidebar-nav a")].forEach(a=>{ li = document.createElement("li"); li.className="nav-item"; if(a.innerText.endsWith("***")) { li.className="nav-item active"; a.innerText = a.innerText.replace("***",""); } if (icons && icons[i]) a.insertAdjacentHTML("afterbegin",icons[i++]); li.append(a); document.querySelector(".sidebar-nav").append(li); }) } if(component.id=="sidebar-controls"){ let controls = [...document.querySelectorAll("#sidebar-controls > *")] for (i=0;i<controls.length;i+=2){ isOpen=false; if(controls[i].innerText.endsWith("***")){ isOpen=true; controls[i].innerText = controls[i].innerText.replace("***",""); } sum = document.createElement("summary"); det = document.createElement("details"); div = document.createElement("div"); det.append(sum); sum.append(...controls[i].childNodes); div.append(...controls[i+1].childNodes); det.append(div); templateComponent.append(det); if(isOpen) sum.click(); } } templateComponent.append(...component.childNodes); } if (!templateComponent) console.log(`⚠️ class ".${component.id}" does not exists on template!`); component.remove(); } //behave like accordion setTimeout(function(){ details = [...document.querySelectorAll("#sidebar details")] details.forEach((detail) => { detail.addEventListener('click', (e) => { const active = details.find(d => d.open) if (!e.currentTarget.open && active) { active.open = false } }) }) },500) //move elements var components = "nav,title,logo,options,controls,nav-icons"; components = components.split(",").map(x=>{return "#sidebar-"+x}).join(", "); [...document.querySelectorAll(components)].forEach(component=>{templateComponent="."+component.id;moveElement(component,document.querySelector(templateComponent)) }); iconSize = parseInt(window.getComputedStyle(sidebar).getPropertyValue("font-size").replace("px",""))+0+"px"; if (hasFeathers) feather.replace({width:iconSize,height:iconSize})
See also
JavaScript Sidebar for Spotfire
JavaScript Masthead for Spotfire
IronPython Masthead for Spotfire
Recommended Comments
There are no comments to display.