Widget Stacker

To use widget in Stacker (or any other non LiveView app that doesn’t import BetterDocComponents) add the following code on the page widget needs to appear:



Javascript:


const widgetID = "my-widget-in-stacker"
const iframeID = "my-widget-in-stacker-iframe"
const baseURL = "https://parc-staging.betterdoc.org"
const widgetPath = "admission/legacy/search"
const widgetPosition = "open-from-bottom-right"

const embedWidget = function(widgetID, iframeID, baseUrl, path) {
  const div = document.createElement("div")

  const iframeEl = `
    <iframe
      id="${iframeID}"
      src="${baseUrl}/${path}"
      style="position: relative; z-index: 50;"
      width="0" height="0"
      frameborder="0"
    ></iframe>
  `;

  div.innerHTML = iframeEl
  const bdWidget = document.getElementById(widgetID)
  bdWidget.appendChild(div)

  window.addEventListener("message", (event) => {
    if (event.origin !== baseUrl) return

    const data = JSON.parse(event.data)

    if (widgetID !== data.frameSenderId) return

    const widgetFrame = document.getElementById(iframeID)
    widgetFrame.height = data.height
    widgetFrame.width = data.width
  }, false);
}

const widgetHTML = `
  <div class="widget-anchor ${widgetPosition}-anchor"
    style="
      z-index: 100;
      position: fixed;
      bottom: 25px;
      right: 25px;
      cursor: pointer;"
  >
    <input type="checkbox" id="${widgetID}-trigger" name="${widgetID}-trigger" class="widget-trigger" style="display: none;">

    <div id="${widgetID}" class="widget-app expand-to-frame-height open-from-bottom-right-app"></div>

    <label for="${widgetID}-trigger" class="widget-trigger unselectable" style="cursor: pointer;">
      <span>Trigger This</span>
    </label>
  </div>
`;

const widgetDiv = document.createElement('div')
widgetDiv.innerHTML = widgetHTML
document.body.appendChild(widgetDiv)

embedWidget(widgetID, iframeID, baseURL, widgetPath)


CSS:


  .widget-anchor .widget-trigger:checked ~ .widget-app {
    display: block;
  }

  .widget-anchor .widget-trigger:not(:checked) ~ .widget-app {
    display: none;
  }

  .expand-to-frame-height iframe {
    animation-name: expand-height;
    animation-duration: .4s;
  }

  .expand-to-frame-height-again iframe {
    animation-name: expand-height;
    animation-duration: .4s;
  }

  @keyframes expand-height {
    from {height: 0px;}
  }

  .open-from-bottom-fixed-right-anchor {
    position: fixed;
    bottom: 2rem;
    right: 2rem;
  }

  .open-from-bottom-fixed-right-anchor > label {
    float: right;
  }

  .open-from-bottom-fixed-right-app {
    position: relative;
    bottom: 1.5rem;
  }

  .open-from-top-centered-anchor {
    position: relative;
  }

  .open-from-top-centered-app {
    position: absolute;
    top: 2.5rem;
    left: 50%;
    transform: translate(-50%, 0);
  }

  .open-from-bottom-centered-anchor {
    position: relative;
  }

  .open-from-bottom-centered-app {
    position: absolute;
    bottom: 2.5rem;
    left: 50%;
    transform: translate(-50%, 0);
  }

  .open-from-top-left-anchor {
    position: relative;
  }

  .open-from-top-left-app {
    position: absolute;
    top: 2.5rem;
    left: 0;
  }

  .open-from-top-right-anchor {
    position: relative;
  }

  .open-from-top-right-app {
    position: absolute;
    top: 2.5rem;
    right: 0;
  }

  .open-from-bottom-left-anchor {
    position: relative;
  }

  .open-from-bottom-left-app {
    position: absolute;
    bottom: 2.5rem;
    left: 0;
  }

  .open-from-bottom-right-anchor {
    position: relative;
  }

  .open-from-bottom-right-app {
    position: absolute;
    bottom: 2.5rem;
    right: 0;
  }

  .open-from-bottom-fixed-left-anchor {
    position: fixed;
    bottom: 2rem;
    left: 2rem;
  }

  .open-from-bottom-fixed-left-anchor > label{
    float: left;
  }

  .open-from-bottom-fixed-left-app {
    position: relative;
    bottom: 1.5rem;
  }

  .unselectable {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }