Jump to content
  • JavaScript Masthead-popups Template for Spotfire


    A Masthead template that uses all the masthead components: filters, options, logo, title, etc.

    pop-nav.thumb.png.c9830e7c9913456c78335431eb29af30.png

    Introduction

    This template is the most complete template. Supports the following components:

    • masthead-logo - text or image for the logo
    • masthead-ittle  - text for the analysis title
    • masthead-nav  - links for navigation or any other page action
    • masthead-nav-icons - comma separated font-awesome icon name for masthead-nav
    • masthead-options - any Spotfire control or html element for the options button content popup
    • masthead-options-trigger - text for the options trigger and popup title
    • masthead-options-trigger-icon - icon for the options popup and trigger
    • masthead-filters - Spotfire control or any other element can go here

    html

    <DIV id="masthead" style="FONT-SIZE: 15px; BACKGROUND: #3498db; COLOR: white"></DIV> 
    
    <div id="masthead-logo" style="color:#3498db; background:black;position:relative">
       LOGO
    </div>
    
    <h1 id="masthead-title" >JavaScript Masthead-popup for Spotfire</h1>
    
    <h3 id="masthead-nav" style="text-align:center;font-size:20px">
       <a>page 1</a>
       <a>page 2</a>
       <a>page 3</a>
    </h3>
    <div id="masthead-nav-icons" hidden>circle,globe,bell</div>
    
    <span id="masthead-options-trigger">options</span>
    <div  id="masthead-options-trigger-icon">bell</div>
    
    <div id="masthead-options" style="background:rgba(0,255,0,0.1);border:2px solid lime;margin:10px;padding:10px;font-size:20px">
          replace with spotifre control<br>or any other element
    </div>
    
    
    <div id="masthead-filters" style="border:1px solid black;background:orange">
       <div>Filters 1</div> 
       <div>Filters 1 contents</div> 
    
       <div>Filters 2</div> 
       <div>Filters 2 contents</div> 
    
       <div>Filters 3</div> 
       <div>Filters 4 contents</div> 
    </div>
     


    masthead-popups.js

    masthead = document.getElementById("masthead");
    hasFeathers = typeof feather!="undefined";
    
    triggerTitle = document.getElementById('masthead-options-trigger')?.innerText || "options"
    triggerIcon = document.getElementById('masthead-options-trigger-icon')?.innerText || "chevron-down"
    if (triggerIcon && hasFeathers) triggerIcon = `<i class="icon" data-feather="${triggerIcon}"></i>`;
    if (triggerIcon && !hasFeathers) triggerIcon = `<i class="icon fa-solid fa-${triggerIcon}"></i>`;
    if(triggerIcon=="chevron-down") triggerIcon=="▼";
    
    
    template = `
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" />
    
    <div class="masthead">
    
      <div>
        <table border=0 width=333>
            <tr align="center"><td  width=1 class="masthead-logo"></td><td width=100 rowspan=2><b id="mastheadNav">STOCK</b><br><i>Analysis</i></td></tr>
            <tr align="center"><td  class="masthead-title"></td></tr>
        </table>
      </div>
    
      <div class="masthead-filters"></div>
    
      <div class="masthead-nav">
         <li id="mastheadPopupTrigger"><a>${triggerTitle} &nbsp; ${triggerIcon}</a></li> 
      </div>
    
    
    </div>
    
    
    
    <div id="mastheadPopup" class="draggable dialog" hidden >
      ${triggerTitle}
      <span class="close"></span>
      <div class="contents masthead-options"></div>
    </div>
    
    
    
    <style>
    
    
    /*masthead*/
    .masthead {
      display: grid;
      width: 100%;
      grid-template-columns: 5fr 60fr 25fr;
      grid-gap: 0px;
      background:rgba(0,0,0,0.1);
    }
    
    .masthead-filters {
        display: flex;
        align-items: center;
        justify-content: center;
        color:${masthead.style.background};
    }
    
    .masthead > div {
      background-color: ${window.getComputedStyle(masthead).getPropertyValue("background-color")};
    }
    
    .masthead-title{
     font-size:${parseInt(window.getComputedStyle(masthead).getPropertyValue("font-size").replace("px",""))-5+"px"};
    }
     
    .masthead-nav {
        display: grid;
        grid-auto-flow: column;
        align-content: center;
        list-style: none;
        grid-gap: 6px; 
        text-align:center;
        cursor:default;
    }
    
    .masthead-nav a{
       color:${masthead.style.color} !important;
       text-decoration:none !important;
    }
    
    .icon {
        margin-right: 15px;
    }
    
    .masthead-nav li:hover {
        background: rgba(255,255,255,.1);
    }
    
    /*popup*/
    .dialog{
      border:1px solid rgba(0,0,0,.2);
      position:fixed;
      padding:5px 5px 5px 5px;
      background:${masthead.style.background};
      z-index:10;
      border-radius:5px;
      cursor:default;
      right:23px;
    }
    .dialog .close::after{
      content:"✖";
      color:${masthead.style.color};
      float:right;
      margin-top:-2px;
    }
    .dialog .close:hover::after{
      color:gray;
    }
    
    .dialog .contents{
      border:1px solid darkgray;
      background:${masthead.style.color};
      margin-top:3px;
      padding:5px;
      min-height:100px;
      display:grid;
      color:${masthead.style.background};
    }
    
    /*logo*/
    .svg_logo, .logo {
      fill:${masthead.style.color} !important;
      width:50px;
      padding-right:15px;
      display:inline-block;
      vertical-align: middle;
    }
    
    /*accordion*/
    .accordion__trigger[aria-expanded="true"]::after {
        transform: unset;
        content:"?";
    }
        
        
    .accordion__trigger:hover, .accordion__trigger:focus {
       background: ${masthead.style.background};
    }
    
    .accordion__trigger::after{
      content:"?";
      border:none;
      right: 10px;
      font-size: 12px;
      border-right: 10px solid transparent; /*triangle color*/
      transition:none;
    }
    
    /*border colors*/
    
    .accordion__trigger{
      padding: 0.3rem;
      font-size: 13px;
      background: ${masthead.style.background};
      color: ${masthead.style.color};
      border-bottom: 1px solid ${masthead.style.background};
    }
    
    
    .accordion__panel--open {
        border-bottom: 1px solid  ${masthead.style.background};
    }
    
    .accordion__panel{
        border-right: 1px solid ${masthead.style.background};
        border-left: 1px solid ${masthead.style.background};
    }
    
    /*popup filters*/
    .dropdown-el {
         text-align: center;
         background: #ebf4fb;
         min-height: 95vh;
         margin: 0;
         max-width: 18em;
         padding: 0;
         font-family: "Myriad Pro", "Arial", sans;
         font-size: 12px;
         position: relative;
         display: inline-block;
         margin-right: 1em;
         min-height: 2em;
         max-height: 2em;
         overflow: hidden;
         top: 0.5em;
         cursor: default;
         text-align: left;
         white-space: nowrap;
         color: #444;
         outline: none;
         border: 1px oustet transparent;
         border-radius: 1em;
         transition: 0.3s all ease-in-out;
    }
     .dropdown-el input:focus + label {
         background: #def;
    }
     .dropdown-el input {
         width: 1px;
         height: 1px;
         display: inline-block;
         position: absolute;
         opacity: 0.01;
    }
     .dropdown-el label {
         border-top: 0.06em solid #d9d9d9;
         display: block;
         height: 2em;
         line-height: 2em;
         padding-left: 1em;
         padding-right: 3em;
         cursor: default;
         position: relative;
         transition: 0.3s color ease-in-out;
    }
     .dropdown-el label:nth-child(2) {
         margin-top: 2em;
         border-top: 0.06em solid #d9d9d9;
    }
     .dropdown-el input:checked + label {
         display: block;
         border-top: none;
         position: absolute;
         top: 0;
         width: 100%;
    }
     .dropdown-el input:checked + label:nth-child(2) {
         margin-top: 0;
         position: relative;
    }
     .icon::after {
         content: "";
         position: absolute;
         right: 0.8em;
         top: 0.9em;
         border: 0.3em solid #3694d7;
         border-color: #3694d7 transparent transparent transparent;
         transition: 0.4s all ease-in-out;
    }
     .pop{
         border: 0.06em solid #3694d7;
         background: #fff;
         border-radius: 0.25em;
         padding: 0;
         box-shadow: rgba(0, 0, 0, 0.1) 3px 3px 5px 0px;
         min-height: 50px;
         overflow-y:auto;
         position:fixed;
         padding:2px;
         transition: 0.4s all ease-in-out;
        z-index:1;
       display: flex;
        align-items: center;
        justify-content: center;
    
    } 
    
    </style>`
    
    masthead.innerHTML = template;
    
    
    
    
    //move elements function
    function moveElement(from,to){
        if(to!=undefined){
            if (from.id == "masthead-nav"){
                icons = document.querySelector("#masthead-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("#masthead-nav a")].reverse().forEach(x=>{
                    if(x.innerText.endsWith("***")) {
                        x.innerText = x.innerText.replace("***","")
                        document.getElementById("mastheadNav").innerText = x.innerText.toUpperCase()
                    }
                    li = document.createElement("li");
                    li.append(x);
                    if (icons[i]) x.insertAdjacentHTML("afterbegin",icons[i++]);
                    document.querySelector(".masthead-nav").prepend(li)
                })
            }
    
    
            if(from.id=="masthead-filters"){
                let filters = [...document.querySelectorAll("#masthead-filters > *")]
                for (i=0;i<filters.length;i+=2){
                
                    div = document.createElement("div")
                    div.className="nowrap"
                    spn = document.createElement("span")
                    spn.className="dropdown-el icon"
                    lbl = document.createElement("label")
                    spn.append(lbl)
                    lbl.append(...filters[i].childNodes)
                    br = document.createElement("br")
                    pop = document.createElement("span")
                    pop.className="pop"
                    pop.append(...filters[i+1].childNodes)
                    div.append(spn)
                    div.append(br)
                    div.append(pop)
    
                    to.append(div)
                    console.log(to)
                }
            } 
    
                 
            to.append(...from.childNodes);    
        }
        from.remove()
        if (!to) console.log(`⚠️ class ".${from.id}" does not exists on template!`)
    }
    
     
    //move elements
    var imports = "nav,title,logo,options,nav-icons,filters,options-trigger,options-trigger-icon";
    imports = imports.split(",").map(x=>{return "#masthead-"+x}).join(", ");
    [...document.querySelectorAll(imports)].forEach(e=>{t="."+e.id;moveElement(e,document.querySelector(t)) });
    
    iconSize = parseInt(window.getComputedStyle(masthead).getPropertyValue("font-size").replace("px",""))+13+"px";
    
    if (typeof feather!="undefined") try{feather.replace({width:iconSize,height:iconSize})}catch(err){alert("one or more feather icon was not found. Check feathericons.com and masthead-hav-icons masthead component")}
    
    
    
    /*popup*/
    //script parameters
    var popupId = "mastheadPopup"
    
    //globals
    var draggables = document.querySelectorAll('.draggable');
    var draggableRuntime = {}
     
    var startDrag = (e) => {
      draggableRuntime.x =e.offsetX;
      draggableRuntime.y= e.offsetY;
      draggableRuntime.canMove = true;
      draggableRuntime.srcElement = e.srcElement 
    };
    
    var doDrag = (e) => {
      //allow selection on the resulting top right window
      if(e.srcElement.id=="overlayStatus") {e.stopPropagation(); return}
    
      //compute positions
      if(draggableRuntime.canMove ) {
        draggableRuntime.srcElement.style.left = (e.clientX - draggableRuntime.x )/window.innerWidth*100 + "%";
        draggableRuntime.srcElement.style.top = (e.clientY - draggableRuntime.y)/window.innerHeight*100  + "%";
      }
      
    };
    
    var endDrag =(e) => {
      draggableRuntime.canMove = false; 
    }
    
      
    //make target open dialog
    document.getElementById(popupId+"Trigger").onclick=x=>{
        document.getElementById(popupId).hidden=!document.getElementById(popupId).hidden;
    }  
      
      
    //make dialgo close button close
    document.querySelectorAll(".dialog .close").forEach(x => {
      x.onclick = function(){x.parentNode.hidden=true}
    });
    
       
      //make dialog dragable
      document.addEventListener('mousemove', doDrag);
    //    draggables[0].parentNode.addEventListener('mousemove', doDrag);
        draggables.forEach(d => { 
           d.addEventListener('mousedown', startDrag);
           d.addEventListener('mouseup', endDrag);
         });
    
    
    
    
    /**popup filters*/
    //bind events
    var x=[...document.querySelectorAll(".dropdown-el.icon")]
    x.forEach(el=>{
        el.addEventListener('click',(ev)=>{
            let pop = el.parentNode.lastElementChild
            hideAll(pop)
            pop.style.zIndex=pop.style.zIndex=="-1"?"auto":"-1"
        })
    })
    
    //hides all except el
    function hideAll(el){
       [...document.getElementsByClassName("pop")]
       .map((e,i)=>{
           if(el!=e){
                e.style.zIndex = "-1"
           }
        })
    }
    
    
    
    hideAll()
     

    This template supports both, font-awesome and feather icons. If you cannot see the font-awesome icons or your organization prevents from fetching resources from external sites, you can either add the font-awesone-all.min.js as a new script from cdnjs.com/font-awesome or feather icons by copying the JavaScript code from either of those  as a new script. For example, To install the latest version of feather icons, copy the code from https://unpkg.com/feather-icons and add a new script called feather-icons@x.xx.x.js. The version shows up at the url after the file loads. 

    Place the URL as the description of your scripts. It's a good practice!

    To make this script fixed at the top of the screen, try the JavaScript Fixed Masthead for Spotfire

    Back to JavaScript Masthead for Spotfire


    User Feedback

    Recommended Comments

    There are no comments to display.


×
×
  • Create New...