Source: BKGWebMap/Popup.js

/*
 * Copyright (c) 2013 Bundesamt by Kartographie und Geodäsie.
 * See license.txt in the BKG WebMap distribution or repository for the
 * full text of the license.
 *
 * Author: Dirk Thalheim
 */

/**
 * @requires OpenLayers/Popup.js
 * @requires OpenLayers/Popup/Anchored.js
 */

/**
 * @classdesc Klasse für Popups, die auf einer Karte angezeigt werden können.
 *
 * @constructor BKGWebMap.Popup
 * @param {string} id
 * @param {OpenLayers.LonLat} lonlat
 * @param {OpenLayers.Size} contentSize
 * @param {string} contentHTML
 * @param {Object} anchor - Objekt mit Eigenschaften 'size' (OpenLayers.Size) und 'offset' (OpenLayers.Pixel)
 *                         (z.B. OpenLayers.Icon).
 * @param {boolean} closeBox
 * @param {Function} closeBoxCallback - Function to be called on closeBox click.
 */
BKGWebMap.Popup = OpenLayers.Class(OpenLayers.Popup.Anchored, {

    /**
     * Die CSS Klasse für das Popup
     * @memberOf BKGWebMap.Popup
     * @type string
     */
    displayClass: "bkgWebMapPopup",

    /**
     * @memberOf BKGWebMap.Popup
     * @type boolean
     */
    panMapIfOutOfView: true,

    /**
     * Abstand zum Marker-Icon
     * @memberOf BKGWebMap.Popup
     * @type int
     */
    margin: 5,

    autoSize: true,

    initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox,
                        closeBoxCallback)
    {
        OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments);
    },

    /** @private */
    setBackgroundColor:function(color) {
        //does nothing since the popup's style is declared via css
    },

    /** @private */
    setBorder:function() {
        //does nothing since the popup's style is declared via css
    },

    /** @private */
    setOpacity:function(opacity) {
        //does nothing since the popup's style is declared via css
    },

    /**

     * @memberOf BKGWebMap.Popup
     * @param {OpenLayers.Pixel} px
     * @return {OpenLayers.Pixel} The the new px position of the popup on the screen relative to the passed-in px.
     */
    calculateNewPx:function(px) {
        var newPx = px.offset(this.anchor.offset);

        //use contentSize if size is not already set
        var size = this.size || this.contentSize;

        var top = (this.relativePosition.charAt(0) == 't');
        // TODO: Versatz von 6 Pixeln hat mit Padding zu tun. Wie kann dies dynamisch ermittelt werden?
        newPx.y += (top) ? -(size.h + this.margin + 6) : this.anchor.size.h + this.margin;
        newPx.x += (-size.w / 2) + (this.anchor.size.w / 2);

        return newPx;
    },

    /**
     * Method: updateRelativePosition
     * The popup has been moved to a new relative location, so we may want to
     *     make some cosmetic adjustments to it.
     *
     *     Note that in the classic Anchored popup, there is nothing to do
     *     here, since the popup looks exactly the same in all four positions.
     *     Subclasses such as Framed, however, will want to do something
     *     special here.
     * @memberOf BKGWebMap.Popup
     */
    updateRelativePosition: function () {
        OpenLayers.Popup.Anchored.prototype.updateRelativePosition.apply(this);

        var top = (this.relativePosition.charAt(0) == 't');

        OpenLayers.Element.removeClass(this.div, top ? 'bottom' : 'top');
        OpenLayers.Element.addClass(this.div, top ? 'top' : 'bottom');

        //to be overridden by subclasses
    },


    CLASS_NAME: "BKGWebMap.Popup"
});