Source: bemap-ol/bemap-map-ol-popup.js

/**
 * Add a popup to the map
 * @public
 * @param {bemap.Popup} popup
 * @param {object} options
 * @return {bemap.OlMap} this
 */
bemap.OlMap.prototype.addPopup = function(popup, options) {
    if (popup !== null && bemap.inheritsof(popup, bemap.Popup)) {

        if (popup.container_ === null) {
            popup.container_ = document.createElement("div");
            popup.closer_ = document.createElement("div");
            popup.content_ = document.createElement("div");
            popup.container_.id = 'popup';
            popup.container_.className = 'ol-popup';
            popup.closer_.className = 'ol-popup-closer';
            popup.container_.appendChild(popup.closer_);
            popup.container_.appendChild(popup.content_);
            popup.closer_.onclick = function() {
                popup.native.setPosition(undefined);
                popup.visible = false;
            };
            document.body.insertBefore(popup.container_, document.getElementById(this.native.target));
        }

        if (popup.information !== null) {
            popup.content_.innerHTML = popup.information;
        }

        popup.native = new ol.Overlay({
            autoPan: true,
            element: popup.container_
        });

        if (popup.map === null) {
            popup.map = this;
        }

        bemap.OlMap.prototype._addOwnToProperties(popup);

        if (popup.coordinate !== undefined && popup.visible === true) {
            popup.native.setPosition(ol.proj.transform(popup.coordinate.getLonLatArray(), bemap.Map.PROJ.EPSG_WGS84, this.native.getView().getProjection()));
        } else if (popup.coordinate === undefined && popup.visible === true) {
            var center = this.native.getView().getCenter();
            popup.coordinate = new bemap.Coordinate(center[0], center[1]);
            popup.native.setPosition(this.native.getView().getCenter());
        } else {
            popup.native.setPosition(undefined);
        }

        this.native.addOverlay(popup.native);

    }
    return this;
};

/**
 * Remove a popup from the map.
 * @public
 * @param {bemap.Popup} popup the popup to remove from the map.
 * @return {bemap.OlMap} this;
 */
bemap.OlMap.prototype.removePopup = function(popup) {
    if (popup !== null && bemap.inheritsof(popup, bemap.Popup) && popup.container_ !== null) {
        this.native.removeOverlay(popup.native);
        popup.container_.removeChild(popup.closer_);
        popup.container_.removeChild(popup.content_);
        popup.container_.remove();
        popup.container_ = null;
        popup.content_ = null;
        popup.closer_ = null;
        popup.map = null;
        popup.native = null;
    }
    return this;
};

/**
 * Set the visiblility of the popup.
 * @param {bemap.Popup} popup the popup.
 * @param {Boolean} visible true for visible and false for hidden.
 * @return {bemap.Popup} this.
 */
bemap.OlMap.prototype.setVisiblePopup = function(popup, visible) {
    if (popup !== null && bemap.inheritsof(popup, bemap.Popup) && popup.native !== null) {
        popup.visible = visible;
        this.native.once('postrender', function(evt) {
            if (this.visible === true) {
                this.native.setPosition(ol.proj.transform(this.coordinate.getLonLatArray(), bemap.Map.PROJ.EPSG_WGS84, evt.map.getView().getProjection()));
            } else {
                this.native.setPosition(undefined);
            }
        }, popup);
    }
    return this;
};

/**
 * Remove all the popups from the map.
 * @return {bemap.OlMap} this;
 */
bemap.OlMap.prototype.clearPopup = function() {
    var overlays = this.native.getOverlays().getArray();
    while (overlays[0]) {
        var popup = this._getOwnFromProperties(overlays[0]);
        this.removePopup(popup);
    }
    return this;
};

/**
 * Set the coordinate of the popup.
 * @param {bemap.Popup} popup the popup of wich to set the coordinate.
 * @param {bemap.Coordinate} coordinate the new coordinate.
 * @param {object} options Options.
 * @param {bemap.Layer} options.panningMap enable the map panning animation. move map from the current position to the popup anchor at the center of map.
 * @return {bemap.OlMap} this.
 */
bemap.OlMap.prototype.setCoordinatePopup = function(popup, coordinate, options) {
    if (popup !== null && bemap.inheritsof(popup, bemap.Popup)) {
        popup.coordinate = coordinate;
        if (popup.native !== null) {
            var pos = ol.proj.transform(popup.coordinate.getLonLatArray(), bemap.Map.PROJ.EPSG_WGS84, this.native.getView().getProjection());
            popup.native.setPosition(pos);
            if(ol.animation) {
                var pan = ol.animation.pan({
                    source: this.native.getView().getCenter()
                });
                this.native.beforeRender(pan);
            }
            if (options && options.panningMap) {
                this.native.getView().setCenter(pos);
            }
            popup.visible = true;
        }
    }
    return this;
};