text: /* eslint-disable */
  
  // This file is only use for development purpose.
  // The source is wrapped in order to avoid loading GMaps globally.
  // The source code is available on GitHub:
  // https://github.com/googlemaps/v3-utility-library/tree/master/infobox
  
  const createInfoBox = googleReference => {
    /**
     * @name InfoBox
     * @version 1.1.13 [March 19, 2014]
     * @author Gary Little (inspired by proof-of-concept code from Pamela Fox of Google)
     * @copyright Copyright 2010 Gary Little [gary at luxcentral.com]
     * @fileoverview InfoBox extends the Google Maps JavaScript API V3 <tt>OverlayView</tt> class.
     *  <p>
     *  An InfoBox behaves like a <tt>google.maps.InfoWindow</tt>, but it supports several
     *  additional properties for advanced styling. An InfoBox can also be used as a map label.
     *  <p>
     *  An InfoBox also fires the same events as a <tt>google.maps.InfoWindow</tt>.
     */
  
    /* !
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
  
    /* jslint browser:true */
    /* global google */
  
    /**
     * @name InfoBoxOptions
     * @class This class represents the optional parameter passed to the {@link InfoBox} constructor.
     * @property {string|Node} content The content of the InfoBox (plain text or an HTML DOM node).
     * @property {boolean} [disableAutoPan=false] Disable auto-pan on <tt>open</tt>.
     * @property {number} maxWidth The maximum width (in pixels) of the InfoBox. Set to 0 if no maximum.
     * @property {Size} pixelOffset The offset (in pixels) from the top left corner of the InfoBox
     *  (or the bottom left corner if the <code>alignBottom</code> property is <code>true</code>)
     *  to the map pixel corresponding to <tt>position</tt>.
     * @property {LatLng} position The geographic location at which to display the InfoBox.
     * @property {number} zIndex The CSS z-index style value for the InfoBox.
     *  Note: This value overrides a zIndex setting specified in the <tt>boxStyle</tt> property.
     * @property {string} [boxClass="infoBox"] The name of the CSS class defining the styles for the InfoBox container.
     * @property {Object} [boxStyle] An object literal whose properties define specific CSS
     *  style values to be applied to the InfoBox. Style values defined here override those that may
     *  be defined in the <code>boxClass</code> style sheet. If this property is changed after the
     *  InfoBox has been created, all previously set styles (except those defined in the style sheet)
     *  are removed from the InfoBox before the new style values are applied.
     * @property {string} closeBoxMargin The CSS margin style value for the close box.
     *  The default is "2px" (a 2-pixel margin on all sides).
     * @property {string} closeBoxURL The URL of the image representing the close box.
     *  Note: The default is the URL for Google's standard close box.
     *  Set this property to "" if no close box is required.
     * @property {Size} infoBoxClearance Minimum offset (in pixels) from the InfoBox to the
     *  map edge after an auto-pan.
     * @property {boolean} [isHidden=false] Hide the InfoBox on <tt>open</tt>.
     *  [Deprecated in favor of the <tt>visible</tt> property.]
     * @property {boolean} [visible=true] Show the InfoBox on <tt>open</tt>.
     * @property {boolean} alignBottom Align the bottom left corner of the InfoBox to the <code>position</code>
     *  location (default is <tt>false</tt> which means that the top left corner of the InfoBox is aligned).
     * @property {string} pane The pane where the InfoBox is to appear (default is "floatPane").
     *  Set the pane to "mapPane" if the InfoBox is being used as a map label.
     *  Valid pane names are the property names for the <tt>google.maps.MapPanes</tt> object.
     * @property {boolean} enableEventPropagation Propagate mousedown, mousemove, mouseover, mouseout,
     *  mouseup, click, dblclick, touchstart, touchend, touchmove, and contextmenu events in the InfoBox
     *  (default is <tt>false</tt> to mimic the behavior of a <tt>google.maps.InfoWindow</tt>). Set
     *  this property to <tt>true</tt> if the InfoBox is being used as a map label.
     */
  
    /**
     * Creates an InfoBox with the options specified in {@link InfoBoxOptions}.
     *  Call <tt>InfoBox.open</tt> to add the box to the map.
     * @constructor
     * @param {InfoBoxOptions} [opt_opts]
     */
    function InfoBox(opt_opts) {
      opt_opts = opt_opts || {};
  
      googleReference.maps.OverlayView.apply(this, arguments);
  
      // Standard options (in common with google.maps.InfoWindow):
      //
      this.content_ = opt_opts.content || '';
      this.disableAutoPan_ = opt_opts.disableAutoPan || false;
      this.maxWidth_ = opt_opts.maxWidth || 0;
      this.pixelOffset_ =
        opt_opts.pixelOffset || new googleReference.maps.Size(0, 0);
      this.position_ = opt_opts.position || new googleReference.maps.LatLng(0, 0);
      this.zIndex_ = opt_opts.zIndex || null;
  
      // Additional options (unique to InfoBox):
      //
      this.boxClass_ = opt_opts.boxClass || 'infoBox';
      this.boxStyle_ = opt_opts.boxStyle || {};
      this.closeBoxMargin_ = opt_opts.closeBoxMargin || '2px';
      this.closeBoxURL_ =
        opt_opts.closeBoxURL ||
        'http://www.google.com/intl/en_us/mapfiles/close.gif';
      if (opt_opts.closeBoxURL === '') {
        this.closeBoxURL_ = '';
      }
      this.infoBoxClearance_ =
        opt_opts.infoBoxClearance || new googleReference.maps.Size(1, 1);
  
      if (typeof opt_opts.visible === 'undefined') {
        if (typeof opt_opts.isHidden === 'undefined') {
          opt_opts.visible = true;
        } else {
          opt_opts.visible = !opt_opts.isHidden;
        }
      }
      this.isHidden_ = !opt_opts.visible;
  
      this.alignBottom_ = opt_opts.alignBottom || false;
      this.pane_ = opt_opts.pane || 'floatPane';
      this.enableEventPropagation_ = opt_opts.enableEventPropagation || false;
  
      this.div_ = null;
      this.closeListener_ = null;
      this.moveListener_ = null;
      this.mapListener_ = null;
      this.contextListener_ = null;
      this.eventListeners_ = null;
      this.fixedWidthSet_ = null;
    }
  
    /* InfoBox extends OverlayView in the Google Maps API v3.
     */
    InfoBox.prototype = new googleReference.maps.OverlayView();
  
    /**
     * Creates the DIV representing the InfoBox.
     * @private
     */
    InfoBox.prototype.createInfoBoxDiv_ = function() {
      let i;
      let events;
      let bw;
      const me = this;
  
      // This handler prevents an event in the InfoBox from being passed on to the map.
      //
      const cancelHandler = function(e) {
        e.cancelBubble = true;
        if (e.stopPropagation) {
          e.stopPropagation();
        }
      };
  
      // This handler ignores the current event in the InfoBox and conditionally prevents
      // the event from being passed on to the map. It is used for the contextmenu event.
      //
      const ignoreHandler = function(e) {
        e.returnValue = false;
  
        if (e.preventDefault) {
          e.preventDefault();
        }
  
        if (!me.enableEventPropagation_) {
          cancelHandler(e);
        }
      };
  
      if (!this.div_) {
        this.div_ = document.createElement('div');
  
        this.setBoxStyle_();
  
        if (typeof this.content_.nodeType === 'undefined') {
          this.div_.innerHTML = this.getCloseBoxImg_() + this.content_;
        } else {
          this.div_.innerHTML = this.getCloseBoxImg_();
          this.div_.appendChild(this.content_);
        }
  
        // Add the InfoBox DIV to the DOM
        this.getPanes()[this.pane_].appendChild(this.div_);
  
        this.addClickHandler_();
  
        if (this.div_.style.width) {
          this.fixedWidthSet_ = true;
        } else if (
          this.maxWidth_ !== 0 &&
          this.div_.offsetWidth > this.maxWidth_
        ) {
          this.div_.style.width = this.maxWidth_;
          this.div_.style.overflow = 'auto';
          this.fixedWidthSet_ = true;
        } else {
          // The following code is needed to overcome problems with MSIE
  
          bw = this.getBoxWidths_();
  
          this.div_.style.width = `${this.div_.offsetWidth -
            bw.left -
            bw.right}px`;
          this.fixedWidthSet_ = false;
        }
  
        this.panBox_(this.disableAutoPan_);
  
        if (!this.enableEventPropagation_) {
          this.eventListeners_ = [];
  
          // Cancel event propagation.
          //
          // Note: mousemove not included (to resolve Issue 152)
          events = [
            'mousedown',
            'mouseover',
            'mouseout',
            'mouseup',
            'click',
            'dblclick',
            'touchstart',
            'touchend',
            'touchmove',
          ];
  
          for (i = 0; i < events.length; i++) {
            this.eventListeners_.push(
              googleReference.maps.event.addDomListener(
                this.div_,
                events[i],
                cancelHandler
              )
            );
          }
  
          // Workaround for Google bug that causes the cursor to change to a pointer
          // when the mouse moves over a marker underneath InfoBox.
          this.eventListeners_.push(
            googleReference.maps.event.addDomListener(
              this.div_,
              'mouseover',
              function(e) {
                this.style.cursor = 'default';
              }
            )
          );
        }
  
        this.contextListener_ = googleReference.maps.event.addDomListener(
          this.div_,
          'contextmenu',
          ignoreHandler
        );
  
        /**
         * This event is fired when the DIV containing the InfoBox's content is attached to the DOM.
         * @name InfoBox#domready
         * @event
         */
        googleReference.maps.event.trigger(this, 'domready');
      }
    };
  
    /**
     * Returns the HTML <IMG> tag for the close box.
     * @private
     */
    InfoBox.prototype.getCloseBoxImg_ = function() {
      let img = '';
  
      if (this.closeBoxURL_ !== '') {
        img = '<img';
        img += ` src='${this.closeBoxURL_}'`;
        img += ' align=right'; // Do this because Opera chokes on style='float: right;'
        img += " style='";
        img += ' position: relative;'; // Required by MSIE
        img += ' cursor: pointer;';
        img += ` margin: ${this.closeBoxMargin_};`;
        img += "'>";
      }
  
      return img;
    };
  
    /**
     * Adds the click handler to the InfoBox close box.
     * @private
     */
    InfoBox.prototype.addClickHandler_ = function() {
      let closeBox;
  
      if (this.closeBoxURL_ !== '') {
        closeBox = this.div_.firstChild;
        this.closeListener_ = googleReference.maps.event.addDomListener(
          closeBox,
          'click',
          this.getCloseClickHandler_()
        );
      } else {
        this.closeListener_ = null;
      }
    };
  
    /**
     * Returns the function to call when the user clicks the close box of an InfoBox.
     * @private
     */
    InfoBox.prototype.getCloseClickHandler_ = function() {
      const me = this;
  
      return function(e) {
        // 1.0.3 fix: Always prevent propagation of a close box click to the map:
        e.cancelBubble = true;
  
        if (e.stopPropagation) {
          e.stopPropagation();
        }
  
        /**
         * This event is fired when the InfoBox's close box is clicked.
         * @name InfoBox#closeclick
         * @event
         */
        googleReference.maps.event.trigger(me, 'closeclick');
  
        me.close();
      };
    };
  
    /**
     * Pans the map so that the InfoBox appears entirely within the map's visible area.
     * @private
     */
    InfoBox.prototype.panBox_ = function(disablePan) {
      let map;
      let bounds;
      let xOffset = 0,
        yOffset = 0;
  
      if (!disablePan) {
        map = this.getMap();
  
        if (map instanceof googleReference.maps.Map) {
          // Only pan if attached to map, not panorama
  
          if (!map.getBounds().contains(this.position_)) {
            // Marker not in visible area of map, so set center
            // of map to the marker position first.
            map.setCenter(this.position_);
          }
  
          bounds = map.getBounds();
  
          const mapDiv = map.getDiv();
          const mapWidth = mapDiv.offsetWidth;
          const mapHeight = mapDiv.offsetHeight;
          const iwOffsetX = this.pixelOffset_.width;
          const iwOffsetY = this.pixelOffset_.height;
          const iwWidth = this.div_.offsetWidth;
          const iwHeight = this.div_.offsetHeight;
          const padX = this.infoBoxClearance_.width;
          const padY = this.infoBoxClearance_.height;
          const pixPosition = this.getProjection().fromLatLngToContainerPixel(
            this.position_
          );
  
          if (pixPosition.x < -iwOffsetX + padX) {
            xOffset = pixPosition.x + iwOffsetX - padX;
          } else if (pixPosition.x + iwWidth + iwOffsetX + padX > mapWidth) {
            xOffset = pixPosition.x + iwWidth + iwOffsetX + padX - mapWidth;
          }
          if (this.alignBottom_) {
            if (pixPosition.y < -iwOffsetY + padY + iwHeight) {
              yOffset = pixPosition.y + iwOffsetY - padY - iwHeight;
            } else if (pixPosition.y + iwOffsetY + padY > mapHeight) {
              yOffset = pixPosition.y + iwOffsetY + padY - mapHeight;
            }
          } else if (pixPosition.y < -iwOffsetY + padY) {
            yOffset = pixPosition.y + iwOffsetY - padY;
          } else if (pixPosition.y + iwHeight + iwOffsetY + padY > mapHeight) {
            yOffset = pixPosition.y + iwHeight + iwOffsetY + padY - mapHeight;
          }
  
          if (!(xOffset === 0 && yOffset === 0)) {
            // Move the map to the shifted center.
            //
            const c = map.getCenter();
            map.panBy(xOffset, yOffset);
          }
        }
      }
    };
  
    /**
     * Sets the style of the InfoBox by setting the style sheet and applying
     * other specific styles requested.
     * @private
     */
    InfoBox.prototype.setBoxStyle_ = function() {
      let i, boxStyle;
  
      if (this.div_) {
        // Apply style values from the style sheet defined in the boxClass parameter:
        this.div_.className = this.boxClass_;
  
        // Clear existing inline style values:
        this.div_.style.cssText = '';
  
        // Apply style values defined in the boxStyle parameter:
        boxStyle = this.boxStyle_;
        for (i in boxStyle) {
          if (boxStyle.hasOwnProperty(i)) {
            this.div_.style[i] = boxStyle[i];
          }
        }
  
        // Fix for iOS disappearing InfoBox problem.
        // See http://stackoverflow.com/questions/9229535/google-maps-markers-disappear-at-certain-zoom-level-only-on-iphone-ipad
        this.div_.style.WebkitTransform = 'translateZ(0)';
  
        // Fix up opacity style for benefit of MSIE:
        //
        if (
          typeof this.div_.style.opacity !== 'undefined' &&
          this.div_.style.opacity !== ''
        ) {
          // See http://www.quirksmode.org/css/opacity.html
          this.div_.style.MsFilter = `"progid:DXImageTransform.Microsoft.Alpha(Opacity=${this
            .div_.style.opacity * 100})"`;
          this.div_.style.filter = `alpha(opacity=${this.div_.style.opacity *
            100})`;
        }
  
        // Apply required styles:
        //
        this.div_.style.position = 'absolute';
        this.div_.style.visibility = 'hidden';
        if (this.zIndex_ !== null) {
          this.div_.style.zIndex = this.zIndex_;
        }
      }
    };
  
    /**
     * Get the widths of the borders of the InfoBox.
     * @private
     * @return {Object} widths object (top, bottom left, right)
     */
    InfoBox.prototype.getBoxWidths_ = function() {
      let computedStyle;
      const bw = { top: 0, bottom: 0, left: 0, right: 0 };
      const box = this.div_;
  
      if (document.defaultView && document.defaultView.getComputedStyle) {
        computedStyle = box.ownerDocument.defaultView.getComputedStyle(box, '');
  
        if (computedStyle) {
          // The computed styles are always in pixel units (good!)
          bw.top = parseInt(computedStyle.borderTopWidth, 10) || 0;
          bw.bottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
          bw.left = parseInt(computedStyle.borderLeftWidth, 10) || 0;
          bw.right = parseInt(computedStyle.borderRightWidth, 10) || 0;
        }
      } else if (document.documentElement.currentStyle) {
        // MSIE
  
        if (box.currentStyle) {
          // The current styles may not be in pixel units, but assume they are (bad!)
          bw.top = parseInt(box.currentStyle.borderTopWidth, 10) || 0;
          bw.bottom = parseInt(box.currentStyle.borderBottomWidth, 10) || 0;
          bw.left = parseInt(box.currentStyle.borderLeftWidth, 10) || 0;
          bw.right = parseInt(box.currentStyle.borderRightWidth, 10) || 0;
        }
      }
  
      return bw;
    };
  
    /**
     * Invoked when <tt>close</tt> is called. Do not call it directly.
     */
    InfoBox.prototype.onRemove = function() {
      if (this.div_) {
        this.div_.parentNode.removeChild(this.div_);
        this.div_ = null;
      }
    };
  
    /**
     * Draws the InfoBox based on the current map projection and zoom level.
     */
    InfoBox.prototype.draw = function() {
      this.createInfoBoxDiv_();
  
      const pixPosition = this.getProjection().fromLatLngToDivPixel(
        this.position_
      );
  
      this.div_.style.left = `${pixPosition.x + this.pixelOffset_.width}px`;
  
      if (this.alignBottom_) {
        this.div_.style.bottom = `${-(
          pixPosition.y + this.pixelOffset_.height
        )}px`;
      } else {
        this.div_.style.top = `${pixPosition.y + this.pixelOffset_.height}px`;
      }
  
      if (this.isHidden_) {
        this.div_.style.visibility = 'hidden';
      } else {
        this.div_.style.visibility = 'visible';
      }
    };
  
    /**
     * Sets the options for the InfoBox. Note that changes to the <tt>maxWidth</tt>,
     *  <tt>closeBoxMargin</tt>, <tt>closeBoxURL</tt>, and <tt>enableEventPropagation</tt>
     *  properties have no affect until the current InfoBox is <tt>close</tt>d and a new one
     *  is <tt>open</tt>ed.
     * @param {InfoBoxOptions} opt_opts
     */
    InfoBox.prototype.setOptions = function(opt_opts) {
      if (typeof opt_opts.boxClass !== 'undefined') {
        // Must be first
  
        this.boxClass_ = opt_opts.boxClass;
        this.setBoxStyle_();
      }
      if (typeof opt_opts.boxStyle !== 'undefined') {
        // Must be second
  
        this.boxStyle_ = opt_opts.boxStyle;
        this.setBoxStyle_();
      }
      if (typeof opt_opts.content !== 'undefined') {
        this.setContent(opt_opts.content);
      }
      if (typeof opt_opts.disableAutoPan !== 'undefined') {
        this.disableAutoPan_ = opt_opts.disableAutoPan;
      }
      if (typeof opt_opts.maxWidth !== 'undefined') {
        this.maxWidth_ = opt_opts.maxWidth;
      }
      if (typeof opt_opts.pixelOffset !== 'undefined') {
        this.pixelOffset_ = opt_opts.pixelOffset;
      }
      if (typeof opt_opts.alignBottom !== 'undefined') {
        this.alignBottom_ = opt_opts.alignBottom;
      }
      if (typeof opt_opts.position !== 'undefined') {
        this.setPosition(opt_opts.position);
      }
      if (typeof opt_opts.zIndex !== 'undefined') {
        this.setZIndex(opt_opts.zIndex);
      }
      if (typeof opt_opts.closeBoxMargin !== 'undefined') {
        this.closeBoxMargin_ = opt_opts.closeBoxMargin;
      }
      if (typeof opt_opts.closeBoxURL !== 'undefined') {
        this.closeBoxURL_ = opt_opts.closeBoxURL;
      }
      if (typeof opt_opts.infoBoxClearance !== 'undefined') {
        this.infoBoxClearance_ = opt_opts.infoBoxClearance;
      }
      if (typeof opt_opts.isHidden !== 'undefined') {
        this.isHidden_ = opt_opts.isHidden;
      }
      if (typeof opt_opts.visible !== 'undefined') {
        this.isHidden_ = !opt_opts.visible;
      }
      if (typeof opt_opts.enableEventPropagation !== 'undefined') {
        this.enableEventPropagation_ = opt_opts.enableEventPropagation;
      }
  
      if (this.div_) {
        this.draw();
      }
    };
  
    /**
     * Sets the content of the InfoBox.
     *  The content can be plain text or an HTML DOM node.
     * @param {string|Node} content
     */
    InfoBox.prototype.setContent = function(content) {
      this.content_ = content;
  
      if (this.div_) {
        if (this.closeListener_) {
          googleReference.maps.event.removeListener(this.closeListener_);
          this.closeListener_ = null;
        }
  
        // Odd code required to make things work with MSIE.
        //
        if (!this.fixedWidthSet_) {
          this.div_.style.width = '';
        }
  
        if (typeof content.nodeType === 'undefined') {
          this.div_.innerHTML = this.getCloseBoxImg_() + content;
        } else {
          this.div_.innerHTML = this.getCloseBoxImg_();
          this.div_.appendChild(content);
        }
  
        // Perverse code required to make things work with MSIE.
        // (Ensures the close box does, in fact, float to the right.)
        //
        if (!this.fixedWidthSet_) {
          this.div_.style.width = `${this.div_.offsetWidth}px`;
          if (typeof content.nodeType === 'undefined') {
            this.div_.innerHTML = this.getCloseBoxImg_() + content;
          } else {
            this.div_.innerHTML = this.getCloseBoxImg_();
            this.div_.appendChild(content);
          }
        }
  
        this.addClickHandler_();
      }
  
      /**
       * This event is fired when the content of the InfoBox changes.
       * @name InfoBox#content_changed
       * @event
       */
      googleReference.maps.event.trigger(this, 'content_changed');
    };
  
    /**
     * Sets the geographic location of the InfoBox.
     * @param {LatLng} latlng
     */
    InfoBox.prototype.setPosition = function(latlng) {
      this.position_ = latlng;
  
      if (this.div_) {
        this.draw();
      }
  
      /**
       * This event is fired when the position of the InfoBox changes.
       * @name InfoBox#position_changed
       * @event
       */
      googleReference.maps.event.trigger(this, 'position_changed');
    };
  
    /**
     * Sets the zIndex style for the InfoBox.
     * @param {number} index
     */
    InfoBox.prototype.setZIndex = function(index) {
      this.zIndex_ = index;
  
      if (this.div_) {
        this.div_.style.zIndex = index;
      }
  
      /**
       * This event is fired when the zIndex of the InfoBox changes.
       * @name InfoBox#zindex_changed
       * @event
       */
      googleReference.maps.event.trigger(this, 'zindex_changed');
    };
  
    /**
     * Sets the visibility of the InfoBox.
     * @param {boolean} isVisible
     */
    InfoBox.prototype.setVisible = function(isVisible) {
      this.isHidden_ = !isVisible;
      if (this.div_) {
        this.div_.style.visibility = this.isHidden_ ? 'hidden' : 'visible';
      }
    };
  
    /**
     * Returns the content of the InfoBox.
     * @returns {string}
     */
    InfoBox.prototype.getContent = function() {
      return this.content_;
    };
  
    /**
     * Returns the geographic location of the InfoBox.
     * @returns {LatLng}
     */
    InfoBox.prototype.getPosition = function() {
      return this.position_;
    };
  
    /**
     * Returns the zIndex for the InfoBox.
     * @returns {number}
     */
    InfoBox.prototype.getZIndex = function() {
      return this.zIndex_;
    };
  
    /**
     * Returns a flag indicating whether the InfoBox is visible.
     * @returns {boolean}
     */
    InfoBox.prototype.getVisible = function() {
      let isVisible;
  
      if (typeof this.getMap() === 'undefined' || this.getMap() === null) {
        isVisible = false;
      } else {
        isVisible = !this.isHidden_;
      }
      return isVisible;
    };
  
    /**
     * Shows the InfoBox. [Deprecated; use <tt>setVisible</tt> instead.]
     */
    InfoBox.prototype.show = function() {
      this.isHidden_ = false;
      if (this.div_) {
        this.div_.style.visibility = 'visible';
      }
    };
  
    /**
     * Hides the InfoBox. [Deprecated; use <tt>setVisible</tt> instead.]
     */
    InfoBox.prototype.hide = function() {
      this.isHidden_ = true;
      if (this.div_) {
        this.div_.style.visibility = 'hidden';
      }
    };
  
    /**
     * Adds the InfoBox to the specified map or Street View panorama. If <tt>anchor</tt>
     *  (usually a <tt>google.maps.Marker</tt>) is specified, the position
     *  of the InfoBox is set to the position of the <tt>anchor</tt>. If the
     *  anchor is dragged to a new location, the InfoBox moves as well.
     * @param {Map|StreetViewPanorama} map
     * @param {MVCObject} [anchor]
     */
    InfoBox.prototype.open = function(map, anchor) {
      const me = this;
  
      if (anchor) {
        this.position_ = anchor.getPosition();
        this.moveListener_ = googleReference.maps.event.addListener(
          anchor,
          'position_changed',
          function() {
            me.setPosition(this.getPosition());
          }
        );
  
        this.mapListener_ = googleReference.maps.event.addListener(
          anchor,
          'map_changed',
          function() {
            me.setMap(this.map);
          }
        );
      }
  
      this.setMap(map);
  
      if (this.div_) {
        this.panBox_();
      }
    };
  
    /**
     * Removes the InfoBox from the map.
     */
    InfoBox.prototype.close = function() {
      let i;
  
      if (this.closeListener_) {
        googleReference.maps.event.removeListener(this.closeListener_);
        this.closeListener_ = null;
      }
  
      if (this.eventListeners_) {
        for (i = 0; i < this.eventListeners_.length; i++) {
          googleReference.maps.event.removeListener(this.eventListeners_[i]);
        }
        this.eventListeners_ = null;
      }
  
      if (this.moveListener_) {
        googleReference.maps.event.removeListener(this.moveListener_);
        this.moveListener_ = null;
      }
  
      if (this.mapListener_) {
        googleReference.maps.event.removeListener(this.mapListener_);
        this.mapListener_ = null;
      }
  
      if (this.contextListener_) {
        googleReference.maps.event.removeListener(this.contextListener_);
        this.contextListener_ = null;
      }
  
      this.setMap(null);
    };
  
    return InfoBox;
  };
  
  export default createInfoBox;
  