text: /**
   * mag
   */
  
  (function (root, factory) {
    'use strict'; // eslint-disable-line semi
  
    var name = 'Mag'
    if (typeof define === 'function' && define.amd) {
      define(['./mag-analytics'], function (MagnificentAnalytics) {
        return (root[name] = factory(MagnificentAnalytics))
      })
    } else if (typeof exports === 'object') {
      module.exports = factory(require('./mag-analytics'))
    } else {
      root[name] = factory(root.MagnificentAnalytics)
    }
  }(this, function (MagnificentAnalytics) {
    'use strict'; // eslint-disable-line semi
  
    /**
     * @typedef {Object} MagModelFocus
     * @property {number} x - X position, from [0,1].
     * @property {number} y - Y position, from [0,1].
     */
  
    /**
     * @typedef {Object} MagModelLens
     * @property {number} w - Width, from (0,∞).
     * @property {number} h - Height, from (0,∞).
     */
  
    /**
     * @typedef {Object} MagModel
     * @property {number} zoom - Zoom level, from (0,∞).
     * @property {MagModelFocus} focus - Focus object.
     * @property {MagModelLens} lens - Lens object.
     */
  
    /**
     * @typedef {Object} MagOptions
     * @property {MagModel} model - A model.
     * @property {number} zoomMin - Minimum zoom level allowed, from (0,∞).
     * @property {number} zoomMax - Maximum zoom level allowed, from (0,∞).
     * @property {boolean} constrainLens - Whether lens position is constrained.
     * @property {boolean} constrainZoomed - Whether zoomed position is constrained.
     */
  
    /**
     * Mag constructor.
     *
     * @alias module:mag
     *
     * @class
     *
     * @param {MagOptions} options - Options.
     */
    var Mag = function (options) {
      options = options || {}
      options.model = options.model || {}
      options.zoomMin = options.zoomMin || 1
      options.zoomMax = options.zoomMax || 10
      options.constrainLens = options.constrainLens !== false
      options.constrainZoomed = options.constrainZoomed !== false
  
      this.id = options.id
  
      this.model = options.model
      this.options = options
  
      this.fillModel()
    }
  
    Mag.prototype.fillXY = function (r) {
      r = r || {}
      r.x = r.x || 0
      r.y = r.y || 0
      return r
    }
  
    Mag.prototype.fillWH = function (r) {
      r = r || {}
      r.w = r.w || 0
      r.h = r.h || 0
      return r
    }
  
    Mag.prototype.fillModel = function () {
      var model = this.model
      model.mode = model.mode || 'lag'
      model.focus = this.fillXY(model.focus)
      model.lens = this.fillXY(this.fillWH(model.lens))
      model.zoomed = this.fillXY(this.fillWH(model.zoomed))
      model.boundedLens = this.fillXY(this.fillWH(model.boundedLens))
      model.zoom = model.zoom || 1
      model.ratio = model.ratio || 1
    }
  
    /**
     * Update computed model state, especially lens and zoomed.
     */
    Mag.prototype.compute = function () {
      var lens, focus, zoomed, zoom, dw, dh
      var options = this.options
      var model = this.model
      lens = model.lens
      focus = model.focus
      zoomed = model.zoomed
      zoom = model.zoom
  
      zoom = this.minMax(zoom, options.zoomMin, options.zoomMax)
  
      focus.x = this.minMax(focus.x, 0, 1)
      focus.y = this.minMax(focus.y, 0, 1)
  
      dw = 1 / zoom
      dh = 1 / zoom
      dh = dh / model.ratio
  
      lens.w = dw
      lens.h = dh
  
      if (options.constrainLens) {
        lens = this.constrainLensWH(lens)
      }
      lens.x = focus.x - (lens.w / 2)
      lens.y = focus.y - (lens.h / 2)
      if (options.constrainLens) {
        lens = this.constrainLensXY(lens)
      }
  
      zoomed.w = 1 / dw
      zoomed.h = 1 / dh
  
      var z = this.constrainZoomed(zoomed, options)
      if (z.w !== zoomed.w) {
        zoom *= z.w / zoomed.w
      }
      zoomed = z
  
      zoomed.x = 0.5 - focus.x * zoomed.w
      zoomed.y = 0.5 - focus.y * zoomed.h
  
      // the following is better equation for constrained zoom
      // zoomed.x = focus.x * (1 - zoom)
      // zoomed.y = focus.y * (1 - zoom)
  
      if (options.constrainZoomed) {
        zoomed.x = this.minMax(zoomed.x, 1 - zoom, 0)
        zoomed.y = this.minMax(zoomed.y, 1 - zoom, 0)
      }
  
      model.lens = lens
      model.focus = focus
      model.zoomed = zoomed
      model.zoom = zoom
    }
  
    Mag.prototype.minMax = function (val, min, max) {
      return val < min ? min : (val > max ? max : val)
    }
  
    Mag.prototype.minMax1 = function (val, min) {
      return this.minMax(val, min, 1)
    }
  
    Mag.prototype.constrainZoomed = function (r, options) {
      var wm
      var hm
      wm = this.minMax(r.w, options.zoomMin, options.zoomMax)
      if (wm !== r.w) {
        hm *= wm / r.w
        hm = this.minMax(hm, options.zoomMin, options.zoomMax)
      } else {
        hm = this.minMax(r.h, options.zoomMin, options.zoomMax)
        if (hm !== r.h) {
          wm *= hm / r.h
          wm = this.minMax(wm, options.zoomMin, options.zoomMax)
        }
      }
      return {
        w: wm,
        h: hm,
        x: r.x,
        y: r.y
      }
    }
  
    Mag.prototype.constrainLensWH = function (r) {
      var wm
      var hm
      wm = this.minMax1(r.w, 0.1)
      if (wm !== r.w) {
        hm *= wm / r.w
        hm = this.minMax1(hm, 0.1)
      } else {
        hm = this.minMax1(r.h, 0.1)
        if (hm !== r.h) {
          wm *= hm / r.h
          wm = this.minMax1(wm, 0.1)
        }
      }
      return {
        w: wm,
        h: hm,
        x: r.x,
        y: r.y
      }
    }
  
    Mag.prototype.constrainLensXY = function (r) {
      return {
        x: this.minMax(r.x, 0, 1 - r.w),
        y: this.minMax(r.y, 0, 1 - r.h),
        w: r.w,
        h: r.h
      }
    }
  
    Mag.prototype.constrainLens = function (r) {
      var c = this.constrainLensXY(this.constrainLensWH(r))
      if (((c.w + c.x) > 1)) {
        c.x = Math.max(0, 1 - c.w)
      }
      if (((c.h + c.y) > 1)) {
        c.y = Math.max(0, 1 - c.h)
      }
      return c
    }
  
    Mag.prototype.project = function (frame) {
      var model = this.model
      var lens = model.lens
      return {
        x: lens.x * frame.w,
        y: lens.y * frame.h,
        w: lens.w * frame.w,
        h: lens.h * frame.h
      }
    }
  
    if (MagnificentAnalytics) {
      MagnificentAnalytics.track('mag.js')
    }
  
    return Mag
  }))
  