# Source: components/infoWindow.js

    import React from 'react';
    import ReactDom from 'react-dom';

    /** The component designed to implement the google.maps.InfoWindow class. This component can be the child of either the `<Map />` or `<Marker />` components, but if you decide to put it within the `<Map />` component you must set its coordinate property so that it has an anchor point.
    * @memberof Map
    *
    * @property {object} props
    * @property {google.maps} props.maps Required.
    * @property {google.maps.Map} props.map Required.
    * @property {google.maps.MVCObject} props.anchor Required if coordinates aren't provided.
    * @property {object} props.coords Required if anchor isn't provided.
    * @property {number} props.coords.lng
    * @property {number} props.coords.lat
    * @property {bool} props.disableAutopan
    * @property {number} props.maxWidth
    * @property {object} props.pixelOffset
    * @property {object} props.pixelOffset.width
    * @property {object} props.pixelOffset.height
    * @property {google.maps.InfoWindowOptions} props.options These will overwrite any of the convenience props above. See [google.maps.InfoWindowOptions]{@link https://developers.google.com/maps/documentation/javascript/3.exp/reference#InfoWindowOptions} documentation for all the options.
    * @property {bool} props.open Allows you to open and close a window without fully unmounting it.
    * @property {object} state
    * @property {google.maps.InfoWindow} state.infoWindow The internal instance of the infoWindow.
    * @property {function} props.onCloseClick Use this to listen for the close click event. When someone tries to close the infowindow. Implement closing.
    */

    class InfoWindow extends React.Component {
        constructor(props) {
            super(props);
            this.displayName = 'InfoWindow';
            this.state = {
            	infoWindow : null,
            	anchor : null
            }

            this.loadInfoWindowContent = this.loadInfoWindowContent.bind(this);
            this.node = null;
        }
        componentWillMount() {
        	  var {maps, map, anchor, coords} = this.props;
              if(maps && map) {
              	var options = {
              		position : anchor? undefined : coords
              	}
              	var infoWindow = new maps.InfoWindow(options)
              	if(this.props.open)
    	          	infoWindow.open(map, anchor);
    	        else
    	        	infoWindow.close()
              	//Don't let the infowindow do it's default thing when a user tries to close it.
        		maps.event.addListener(infoWindow, 'closeclick', e => {
    	    		if(typeof this.props.onCloseClick === 'function')
    	    			this.props.onCloseClick(e);
        		});

              	this.setState({infoWindow, anchor})
              }
              else {
              	console.error("InfoWindow must live inside of a <Map /> component context.")
              }
        }
    	/** Load rendered children into infoWindow.
    	* @return {undefined}
    	*/
        loadInfoWindowContent() {
        	if(this.state.infoWindow) {

    	    	this.node = ReactDom.findDOMNode(this.refs.infoWindowChildren);
        		this.state.infoWindow.setContent(this.node); //Set infowindow content

        	}

        }
        /** Place rendered children back into their normal location to await their destruction.
        * @return {undefined}
        */
        cleanInfoWindowContentForUnmount() {
        	//Undo our previous dom manipulation.
          	var parent = ReactDom.findDOMNode(this);
          	var child = this.node;
          	parent.appendChild(child);
        }
        componentDidMount() {

        	this.loadInfoWindowContent()
        }
        componentWillUnmount() {
        	if(this.state.infoWindow)
    	    	this.state.infoWindow.open(null);
            this.setState({infoWindow : null});
            this.cleanInfoWindowContentForUnmount();

        }
        componentDidUpdate(prevProps, prevState) {
        	if(this.state.infoWindow) {
        		if(this.props.open && !prevProps.open)
    		      	this.state.infoWindow.open(this.props.map, this.state.anchor);
    	    	else if(!this.props.open && prevProps.open)
    	    		this.state.infoWindow.close();
        	}

        	if(!this.node)
    	    	this.loadInfoWindowContent();

        	var {coords} = this.props;

    		if(!prevProps.coords || (coords.lat != prevProps.coords.lat && coords.lng != prevProps.coords.lng))
    			this.state.infoWindow.setPosition(this.props.coords);

        }
        render() {

            return <div><div ref="infoWindowChildren">{this.props.children}</div></div>;
        }
    }

    InfoWindow.propTypes = {
    	maps : React.PropTypes.object,
    	map : React.PropTypes.object,
    	coords : React.PropTypes.shape({
    		lat : React.PropTypes.number.isRequired,
    		lng : React.PropTypes.number.isRequired
    	}),
    	onCloseClick : React.PropTypes.func
    }

    export default InfoWindow;

#### Search results