Introduction
The Landing Pages for Spotfire are a set of templates to enhance the look and feel of existing dashboards. A landing page is useful to organize different Spotfire Pages.
The purpose of this article is to provide easy to use scripts and templates to create landing pages in no time. Some Templates does not require any JavaScript. However, when HTML Sanitation is enabled you need to use JavaScript to add those 'unsupported' tags. In any case, it is always a good practice to use script keeping in mind that the dashboard should not be affected or crippled if the script fails to run.
For simplicity and efficiency, I will try to get straight to the point without further explanation. If questions arise, feel free to comment.
Template 1
This simple template requires minimal scripting. The script is responsible to add the font-awesome library for the icons to show and to add additional layout options. To add more items, just duplicate any of the <div class="grid"> . The colors, fonts and layout is defined in the embedded style within the script.
html
<div id="css"></div> <div style="font-size:20px;margin: 0% 20%;"> <div class="container"> <div class="grid"> <div class="icon"><i class="fa fa-3x fa-solid fa-chart-line"></i></div> <div class="desc"> <h2>Stock screener and company analysis</h2> <p> Tool that helps investors filter stocks based on specific criteria and provides insights into the financial health of a company </p> </div> </div> <div class="grid"> <div class="icon"><i class="fa fa-3x fa-solid fa-location-dot"></i></div> <div class="desc"> <h2>Revenue by country</h2> <p> The revenue dashboard by country provides a <b>comprehensive</b> view of sales data for Africa, Europe, Asia, North America, and the rest of the world. It allows users to choose a specific region or see the entire world, making it easy to monitor revenue performance and identify potential growth opportunities. </p> </div> </div> <div class="grid"> <div class="icon"> <i class="fa fa-3x fa-solid fa-sitemap"></i> </div> <div class="desc"> <h2>Sector and industry breakdown</h2> <p> A treemap visualization that enables drill-down analysis of stock prices by sector and industry. Users can select a sector and industry to drill down into specific stocks, allowing for deeper analysis and identification of investment opportunities. </p> </div> </div> <div class="grid"> <div class="icon"><i class="fa fa-3x fa-solid fa-circle-nodes"></i></div> <div class="desc"> <h2>K-means clustering</h2> <p> Analyze stock data by market capitalization and price-to-earnings (P/E) ratios. Filter stocks by market cap size and high or low P/E ratios.<br/><br/>Group the stocks into clusters based on their market cap and P/E ratio to identify patterns and similarities in the data. </p> </div> </div> </div>
JavaScript
css = ` <link rel="stylesheet" href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==' crossorigin="anonymous" referrerpolicy="no-referrer" /> <style> @import 'https://fonts.googleapis.com/css?family=Lato:400,700' #landingPage { background-color: #dfe9ff; font-family: "Lato", sans-serif; } .grid { display: flex; align-items: center; padding: 8px; margin: 10px; } .container .icon { display: flex; align-items: center; justify-content: center; height: 125px; width: 20vw; color: darkblue; } @media (max-width: 550px) { .container .icon { display: none; } } .container .desc { display: flex; flex-direction: column; width: 65vw; } @media (max-width: 550px) { .container .desc { width: 100%; text-align: center; padding: 0; height: 150px; } } @media (max-width: 650px) { .container { margin-top: 0; } } </style>` document.getElementById("css").innerHTML = css
Template 2
This other template is simpler to maintain as the html is straight forward. The JavaScript is responsible to convert the entire card clickable and parse the html markup to create all the elements layout and some formatting.
Adding more cards
To add more cards, just duplicate the card markup and it's contents <div class="landing-page-card">.
Changing the colors, background and font-size
The colors, fonts and other styles can be done directly on the <div class="landing-page-card" style="background:beige"> or the main <div id="landing-page" style="background:#dfe9ff;color:green;font-size:24px"> container. For additional tweaking, edit the <style> tag contentes on the script.
Icons
The icons for each card are set by the comma separated set of icons for each card on the <img class="landing-page-card-icons fa-solid fa-chart-line,fa-solid fa-location-dot,fa-solid fa-sitemap,fa-solid fa-circle-nodes"/>
HTML
<div id="landing-page" style="background:#dfe9ff;color:green;font-size:24px"> <div id="landing-page-banner-text"> <h1>Analyzing Stock Performance</h1> <p>Interactive Application with <b>different visual tools</b> to enable investors to make <b>data-driven investment decisions</b> by analyzing stock. Data screening and company analysis to check revenue by country and options to analyze further via sector and industry breakdown and other analysis </p> <div class="banner-button"><a>Get Started</a></div> </div> <img id="landing-page-banner-image" />; <div class="landing-page-card" > <a href="#">Stock screener and company analysis</a> Tool that helps investors filter stocks based on specific criteria and provides insights into the financial health of a company </div> <div class="landing-page-card"> <a href="#">Revenue By Country</a> The revenue dashboard by country provides a <b>comprehensive</b> view of sales data for Africa, Europe, Asia, North America, and the rest of the world. It allows users to choose a specific region or see the entire world, making it easy to monitor revenue performance and identify potential growth opportunities. </div> <div class="landing-page-card"> <a href="#">Sector and industry breakdown</a> <p>A treemap visualization that enables drill-down analysis of stock prices by sector and industry. Users can select a sector and industry to drill down into specific stocks, allowing for deeper analysis and identification of investment opportunities. </p> </div> <div class="landing-page-card"> <a href="#">K-means clustering</a> <p>Analyze stock data by market capitalization and price-to-earnings (P/E) ratios. Filter stocks by market cap size and high or low P/E ratios.<br/><br/>Group the stocks into clusters based on their market cap and P/E ratio to identify patterns and similarities in the data <a>another link</a> </p> </div> <span class="landing-page-card-icons fa-solid fa-chart-line,fa-solid fa-location-dot,fa-solid fa-sitemap,fa-solid fa-circle-nodes"></span> </div>
JavaScript
(() => { //return //script Params landingPageId = "landing-page"; landingPageImage = 'https://preview.ibb.co/bMi5Y6/banner_img.png'; //main element landingPageDiv = document.getElementById(landingPageId); //banner elements landingPageBannerId= "#"+landingPageId+"-banner-" landingPageTextDiv = document.querySelector(landingPageBannerId+"text"); //banner image landingPageIamgeDiv = document.querySelector(landingPageBannerId+"image"); //landingPageIamgeDiv.src = landingPageImage //card elements landingPageCardLinks = [...document.querySelectorAll(".landing-page-card > a")]; landingPageCardLinks.forEach(a=>a.remove) landingPageCardContents = [...document.querySelectorAll(".landing-page-card")] //icons landingPageCardIcons = document.querySelector(".landing-page-card-icons").classList.value.split(",") landingPageCardIcons[0] = landingPageCardIcons[0].replace("landing-page-card-icons ",""); template=` <link rel="stylesheet" href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <div class="banner"> <div class="banner-text"></div> <img class="banner-image" /> </div> <div class="cards"></div> ` //by now we "cut" all elements from main container, so we replace with template landingPageDiv.innerHTML = template //start 'pasting' elements //banner text templateBannerText = document.querySelector("#"+landingPageId+" .banner .banner-text") templateBannerText.append(...landingPageTextDiv.childNodes); //banner image templateBannerImage = document.querySelector("#"+landingPageId+" .banner .banner-image") templateBannerImage.src = landingPageImage //cards landingPageCardLinks.forEach((a,j)=>{ div = document.createElement("div"); //Object.assign(a.style,landingPageCardContents[j].style) a.className = "card"; a.style.textDecoration = "none"; i = document.createElement("i"); i.className = landingPageCardIcons[j] + " fa-xl"; i.style.color = "#9b3323"; h3 = document.createElement("h3"); h3.className = "card-title"; h3.innerText = a.innerText; const p = document.createElement("p"); let descriptionText = landingPageCardContents[j].innerText; const titleIndex = descriptionText.indexOf(a.innerText); if (titleIndex) { descriptionText = descriptionText.slice(0, titleIndex) + descriptionText.slice(titleIndex + a.innerText.length); } p.innerText = descriptionText.trim(); //footer a2 = document.createElement("a"); a2.className = "card-link" a2.innerText = "Go to page"; div.append(i); div.append(h3); div.append(p); div.append(a2); a.innerHTML="" a.append(div) document.querySelector(".cards").append(a); //apply inline style (if any) sourceStyle = landingPageCardContents[j].getAttribute('style'); a.setAttribute('style', sourceStyle); p.setAttribute('style', sourceStyle); }) cardCount = landingPageCardLinks.length + 1; //Default Style that can be override by other themes / layouts style = `<style> #landing-page { background: #dfe9ff; font-family: Lato, sans-serif; height:100vh; } .banner{ display:flex; padding:3%; } .banner .banner-image { opacity: 0.5; position: absolute; right: 0px; top: 0px; filter: drop-shadow(0 3rem 0.05rem rgba(191, 216, 255, 1)); } @media (min-width: 300px) { .banner .banner-image { display: none; height: 400px; top: 0px; opacity: 0.5; } } @media (min-width: 900px) { .banner .banner-image { display: inherit; height: 400px; top: 0px; opacity: 0.5; } } @media (min-width: 1400px) { .banner .banner-image { display: inherit; height: 500px; top: 0px; opacity: 0.8; } } @media (min-width: 1800px) { .banner .banner-image { height: 600px; top: -50px; opacity: 1; } } .banner .banner-text { max-width: 850px; float: left; } .banner .banner-text h1 { color: #00106a; font-size: 3rem; font-weight: 700; letter-spacing: 3px; margin-bottom: 1rem; } .banner .banner-text p { color: #00106a; xfont-size: 1.05rem; line-height: 1.75; margin-bottom:35px; } .banner-button a{ border: 0; border-radius: 50px; padding: 0.75rem 2.75rem; background: #4b71ff; color: #fff !important; box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, .25); cursor: pointer; position: relative; font-size: 1rem; font-weight: 400; letter-spacing: 1px; transition: all 0.3s ease-in-out; color:white; text-decoration:none !important; } .banner-button a:hover { transform: translateY(-5px); box-shadow: 0 1rem 1.5rem rgba(0, 0, 0, .25); } .cards { display: flex; flex-wrap: wrap; justify-content:center; } .card { flex-basis: calc(100% / ${cardCount}); background-color: #ddd; margin: 10px; } /* Media queries for smaller screens */ @media (max-width: 768px) { .card { flex-basis: calc(100% / ${cardCount/2}); } } @media (max-width: 480px) { .card { flex-basis: 100%; } } .card { padding: 16px 24px; background: #fff; position: relative; border: none; box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, .15); border: 2px solid transparent; transition: all 0.3s ease-in-out; } .cards a:hover{ text-decoration:none; } .card h3.card-title { font-weight: 700; font-size: 1.3rem; color: #00106a; } .card p { color: #989dc5; font-size: 70%; line-height: 1.5; margin-bottom: 72px; } .card .card-link { position: absolute; bottom: 18px; } .card:hover { filter: brightness(95%); box-shadow: 0 1rem 1.5rem rgba(0, 0, 0, .15); cursor: pointer; } .card .card-icon { width: 60px; margin-bottom: 8px; position: relative; top: 0; left: -12px; } </style>` landingPageDiv.insertAdjacentHTML("afterend",style) })()
More Templates
A quick and dirty tip is to find templates on the web or even design your own template on a web based editor such as google docs, google slides or even Excel and then select then copy and paste directly while editing a text area other than html mode.
Center Content
To center the content, just edit the html and wrap everything with a div tag that flex it all centered
<div style="display:flex;justify-content: center;align-items: center;"> : <generated html content from pasting from Google Sheets goes here...> : </div>
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.
Recommended Comments
There are no comments to display.