Introduction
A popup is a small window that it is display on top of other windows. The JavaScript Popup for Spotfire can hold Spotfire controls such as Action Controls, Filters, Property Controls and Dynamic Items. Examples of these can be buttons, dropdowns, input boxes, filters, calculated values, Sparklines, etc. It can also hold or any other HTML element supported by the Text Area.
Popups are great way to save on valuable dashboard space and help make a better experience for the analyst.
How it works
The popup consists in html code and some JavaScript code. The html must follow a specific structure that defines the popup elements so the script can render the popup. To have multiple triggers and multiple popups, you need multiple html and javascript sets for each popup.
Popup elements
These parts are the popup container, popup trigger, the popup title and the popup contents. The popup container is an html tag element that enclose these element in sequence.
Popup container
The main container has 3 children, one for each popup component (trigger, title and contents). It should have a unique id attribute to identify the popup. This id is passed as a parameter for the popup script.
Popup trigger
The first popup container child is the trigger. The trigger is responsible to show or hide the popup. This can be an image, text or icon. It can hold Spotfire controls but it is not recommended, unless you use a label or calculated value without any click event handlers.
Popup title
This is the title of the popup, and can only take text. The second child of the popup container is defined as the popup title. If the popup title ends with *** the default popup visibility will be opened by default.
Popup contents
The third child of the popup container holds the contents of the popup and can include any Spotfire control or html tag.
Example with one popup
html
<div id="myPopup" class="JSPopup"> <div>Open popup A</div> <div>This is popup A</div> <div> Popup contents goes <b>here</b> </div> </div>
script
The script takes the id as the input parameter. To test without this parameter, uncomment the second that reads id="popup2";
/* usage: <div class="JSPopup" id="myPopup"> <div>click to open popup (trigger)</div> <div>Popup title (pullable)</div> <div>Popup contents</div> </div> then run script */ //script params id="myPopup" function createPopout(popup, i) { let id = "JSPopup_" + i; let popupElements = popup.children; let popupTrigger = popupElements[0]; let popupTitle = popupElements[1].innerText; let popupContents = popupElements[2]; let isOpened = false; /*show all popup on start? If not, popup opens if title ends with "***" */ popupTrigger.style.cursor = "default"; //add dragging library let template = ` <div id="${id}" class="pullable ${isOpened ? "" : "hidden"}" > <span class="close"></span> <div class="contents"></div> </div> <style> .hidden{ left:-1000px !important; } #${id}{ border:1px solid darkgray; position:fixed; padding:5px 5px 5px 5px; background:${popup.style.background || "whitesmoke"}; Xcolor:${popup.style.color}; Xfont-size:${popup.style.fontSize}; Xfont-family:${popup.style.fontFamily}; box-shadow: 0 3px 11px 0 rgba(0,0,0,.16),0 3px 6px 0 rgba(0,0,0,.16); border-radius: 6px; cursor:default; min-width:200px; } #${id} .close::after{ content:"✖"; color:darkgray; float:right; margin-top:-15px; cursor:default; } #${id} .close:hover::after{ color:gray; } #${id} .contents{ border:0px solid darkgray; background:${popupContents.style.background || "#FFF"}; margin-top:3px; padding:5px; min-height:100px; } .DropdownListContainer.sf-element-styled-dialog.sfc-style-root.prevent-flyout-close { z-index: 999; } </style> `; popup.innerHTML = template; let popupBody = document.getElementById(id); //add trigger popup.appendChild(popupTrigger); //add title to hidden popup template if (popupTitle.endsWith("***")) { popupTitle = popupTitle.slice(0, popupTitle.length - 3); popupBody.classList.remove("hidden"); } handle = document.createElement("div"); handle.className = "handle"; textNode = document.createTextNode(popupTitle); handle.prepend(textNode); popupBody.prepend(handle); //add contents to hidden popup template let templateContents = document.querySelector(`#${id} .contents`); templateContents.style = popupContents.style.cssText; popupBody.style = popup.style.cssText; popup.removeAttribute("style"); templateContents.append(...popupContents.childNodes); //make target open dialog popupTrigger.onclick = (x) => { pp = document.getElementById(id); pp.classList.toggle("hidden"); [...document.querySelectorAll(".pullable")].forEach((d) => { d.style.zIndex = 0; }); pp.style.zIndex = 10; }; //make dialog close button close document.querySelectorAll("#" + id + " .close").forEach((x) => { x.onclick = () => { x.parentNode.classList.add("hidden"); }; }); //make dialogs draggable document.querySelectorAll(".pullable").forEach((aPopup) => { new Draggabilly(aPopup, { handle: ".handle" }); }); } // Add dragging library draggingLibraryUrl = 'https://unpkg.com/draggabilly@3/dist/draggabilly.pkgd.min.js'; script = document.createElement("script"); script.src = draggingLibraryUrl; ph = document.getElementById(id); ph.appendChild(script); //parse popups after dragging library loads script.onload = () => { //create a popup for every JSPopup class [...document.querySelectorAll(".JSPopup")].forEach((rawPopup, i) => createPopout(rawPopup, i) ); };
Making the Popups draggable when Internet is unreliable
You need to install this library in case there are internet restrictions to go fetch draggabilly, a third party JavaScript library that allows the popups to be draggable. From https://unpkg.com/draggabilly@3/dist/draggabilly.pkgd.min.js, just copy the code from the last link from this sentence into your JavaScript and you are done. Remember, this an optional step if we cannot assure connection to the draggabilly.min.js file.
Changing the look and feel of the popup
The style of the popup is embedded in the script. The best way is to override the styles with a separate script. To change the default look and feel for all the popups, then change the main script. Here is an example of that
popup_blueberry.css
//requires: popup.js //script params //id="myPopup" const popupColors={ c1:"lightgray",//background c2:"#003C84", //border c3:"navy", //title background c4:"#0E0E0E", //text c5:"#FFF" //title } //default style. Override with popup_yourtheme.css css =`<style> #${id} .popup-jsc { width: min-content !important; background-color: #eaeaea !important; border-radius: 0.5em; border: 1px solid whitesmoke; box-shadow: rgb(187 187 187) 5px 4px 9px 1px; } #${id} .flt.drag { border: none; margin: 0; padding: 5px; color:${popupColors.c5}; background: ${popupColors.c3}; } #${id} .popupContents { display: inline-block; padding: 6px 10px; font: 1em arial, helvetica, sans-serif; color: ${popupColors.c4};; background-color: ${popupColors.c1}; border:1px outset ${popupColors.c2}; border-radius:.5em; border-top: none; border-top-left-radius: 0; border-top-right-radius: 0; } </style>` document.getElementById(id).insertAdjacentHTML("beforeend", css);
Popup_greendish.js
//requires: popup.js //script params //id="myPopup" const popupColors={ c1:"green", //contents c2:"darkGreen", //border contents c3:"lightgray", //title background c4:"whitesmoke", //contents color c5:"navy" //title color } //default style. Override with popup_yourtheme.css css =`<style> #${id} .popup-jsc { width: min-content !important; background-color: #eaeaea !important; border-radius: 0.5em; border: 1px solid whitesmoke; box-shadow: rgb(187 187 187) 5px 4px 9px 1px; } #${id} .flt.drag { border: none; margin: 0; padding: 5px; color:${popupColors.c5}; background: ${popupColors.c3}; } #${id} .popupContents { display: inline-block; padding: 6px 10px; font: 1em arial, helvetica, sans-serif; color: ${popupColors.c4};; background-color: ${popupColors.c1}; border:1px outset ${popupColors.c2}; border-radius:.5em; border-top: none; border-top-left-radius: 0; border-top-right-radius: 0;} </style>` document.getElementById(id).insertAdjacentHTML("beforeend", css);
Back to the JavaScript Component Hub for Spotfire
Disclaimer
This method makes assumptions about the inner workings of Spotfire version 12.0.0 LTS Any analyses created using this hack may cause instability and performance issues and are likely to break when Spotfire is upgraded or hotfixed in the future. Any issues resulting from applying this hack are not covered by Spotfire maintenance agreements and Support will not assist in troubleshooting problems with analysis files where this approach is used.
-
1
Recommended Comments
There are no comments to display.