Home Reference Source

src/formats/responsive.js

import { cpexLog, addIframe } from '../utils.js'

/**
 * Simply wraps an HTML banner and scales it down if it's larger than the viewport.
 * It requires responsive settings (with a target elementId and size) to be present.
 */
export default class Responsive {
  constructor (elementId, adUnit, main, width, height) {
    this.main = main
    this.type = 'responsive'
    this.loaded = false
    this.adUnit = adUnit
    this.elementId = elementId
    this.settings = main.settings.formats.responsive
    this.publisher = main.settings.publisher.code
    this.width = width
    this.height = height
    this.iframeCSS = 'margin:auto; border:none; display:block; overflow:hidden; background-color:#FFF;' // Needed for HB reRender
    cpexLog('Responsive: Caught Responsive custom format, in elementId ' + elementId)
  }

  resize () {
    this.updateContentWidth()
    if (this.width > this.contentWidth) { // window inner width without scrollbar
      this.wrapper.style.transformOrigin = 'left top'
      const scaleFactor = this.contentWidth / this.width
      this.wrapper.style.transform = 'scale(' + scaleFactor + ')' // scale down content
      this.wrapper.style.width = this.width * scaleFactor + 'px'
      this.wrapper.style.height = this.height * scaleFactor + 'px' // resize container height to match
    } else {
      this.wrapper.style.transform = 'scale(1)'
    }
  }

  updateContentWidth () {
    if (['eco', 'nova'].includes(this.publisher)) {
      this.contentWidth = document.documentElement.clientWidth
    } else {
      const padding = this.element.getBoundingClientRect().left
      this.contentWidth = document.documentElement.clientWidth - padding * 2
    }
  }

  /**
   * Places the responsive container into the page
   */
  renderIframe () {
    this.element = document.getElementById(this.elementId)
    this.wrapper = document.createElement('div')
    this.wrapper.style.margin = '0 auto' // center content
    // this.wrapper.style.display = 'inline-block' // to remove gap below // removed so that it can be centered for ads smaller than the viewport
    this.element.appendChild(this.wrapper)
    this.element.style.width = '100%' // make container full width, to account for padding
    this.element.style.display = 'block'
    // Add iframe
    this.iframe = addIframe(this.wrapper, { id: this.elementId + '-iframe', width: 1, height: 1 }, () => { // onload callback
      this.loaded = true
      cpexLog('Responsive: Rendered')
    })
    this.iframe.style.cssText = this.iframeCSS
    this.iframe.style.width = this.width + 'px'
    this.iframe.style.height = this.height + 'px'
    this.iframe.style.maxWidth = this.width + 'px'
    this.iframe.style.maxHeight = this.height + 'px'
    this.resize()
    window.addEventListener('resize', () => this.resize())
    return this.iframe
  }

  /**
   * Returns the page to its original state
   */
  reset () {
    this.element.removeChild(this.wrapper)
    const ads = window.cpexPackage.customAds
    if (ads) { delete ads[this.elementId] }
  }
}