How to achieve adaptive height embedding with ThoughtSpot Everywhere

Embedding an iframe is a great option to embed content because of its security and performance features, but it can be tricky to get the right fit. Especially when we interact with them, or the user changes the browser viewport. 

Some of the most common issues include an additional or missing scroll bar or the modal windows opening inside the iframe without showing the center of the current viewport.

 

How ThoughtSpot Everywhere works.How ThoughtSpot Everywhere works.

ThoughtSpot Everywhere is the only embedded analytics solution that solves the dreaded double scrollbar problem and makes for a seamless experience for your app.

How ThoughtSpot Everywhere works.

Solving for adaptive height

To embed the iframe you need to set height as per content. Here while interacting with iframe, height can change, or simply the browser height can change. You need to handle the dynamic height iframe. We can do this by sending an event from an embedded app to the parent app to change the height of the iframe for each iframe reflow.

Since content can have large heights, showing the modal in the middle of the iframe won’t be that user-friendly. The ideal solution can be showing the modal in the center of the current viewport. To implement this you need to get the current viewport position before opening modals. This can be achieved by calculating current viewport height from parent app and making the iframe wait on getting the height from the parent before opening the modal.

Calculating current viewport height

To calculate current viewport height, you need 3 params from iframe to locate the center of the visible IFrame viewport.

Viewport height compared to Iframe height.
  1. offsetTopClient: The number of pixels between the top edge of the HostApp and the top edge of your app's iframe.

  2. viewPortHeight(Host app): window.innerHeight from SDK

  3. scrollTopClient: the number of pixels Host-app is scrolled vertically.

 

var offsetTopClient = this.iFrame.offsetTop;
var scrollTopClient = window.scrollY;
var viewPortHeight = window.innerHeight;
var iframeHeight = this.iFrame.innerHeight;

var iframeScrolled = scrollTopClient - offsetTopClient;
var iframeVisibleViewPort, iframeOffset, iframeCenter;

if(iframeScrolled < 0) {
   iframeVisibleViewPort = viewPortHeight - (offsetTopClient - scrollTopClient) ;
   iframeVisibleViewPort = Math.min(iframeHeight,iframeVisibleViewPort);
   iframeOffset = 0;
} else {
   iframeVisibleViewPort = Math.min(iframeHeight - iframeScrolled,viewPortHeight);
   iframeOffset = iframeScrolled;
}

iframeCenter = iframeOffset + iframeVisibleViewPort/2;

var modalHeight = 400;
var modalTop;
modalTop = Math.max(0,iframeCenter - modalHeight/2);
modalTop = Math.min(iframeHeight - modalHeight/2,modalTop);

When a user clicks an action that opens a modal in an iframe, you should make the iframe wait for getting the height from the parent before opening the modal. For that, you first send an event to get the height from the parent and wait for a message from the parent. You achieve this by creating a separate message channel for each request and wrapping the whole thing inside a promise.

From the embedded app end:

const getCenterOfViewport = () => new Promise((res, rej) => {
  const channel = new MessageChannel(); 

  channel.port1.onmessage = ({data}) => {
    channel.port1.close();
    if (data.error) {
      rej(data.error);
    }else {
      res(data.result);
    }
  };

  worker.postMessage({}, '*', [channel.port2]);
});

console.log(await getCenterOfViewport());

From the parent app end:

addEventListener("message", (event) => {
  try{
    Let center = getViewPortCenter();
    event.ports[0].postMessage({result: center});
  }catch(e) {
    event.ports[0].postMessage({error: e});
  }
}, false)

ThoughtSpot Everywhere to the rescue

With ThoughtSpot Everywhere, developers can embed analytics quickly, without the hassle of figuring out how to render an iframe correctly whenever a viewport changes. ThoughtSpot Everywhere is the only embedded analytics platform that solves the dreaded double scrollbar problem and makes for a seamless experience for your app.<br>

  1. Click the FullHeight knob while using the TSE playground

  2. Click RUN to execute the code.

Clicking the knob adds fullHeight:true for Liveboard, which is internally used to handle the iframe.

const embed = new LiveboardEmbed("#embed", {
   frameParams: {},
   fullHeight: true,
   liveboardId: "12asdqwd-e284-4fc4-b80c-111cb606449a",
});

Start using fullHeight now in your ThoughtSpot Everywhere solutions or sign up for a free trial today.