function CustomInfo() {

//*     cCustomInfo() - jurk@webit.de

      //Einfaches ersetzen der Google Standartbubble
      //    es werden die Funktionen google.maps.Marker.closeInfoWindow, google.maps.Map.closeInfoWindow, google.maps.Marker.openInfoWindow, google.maps.Map.openInfoWindow
      //    überschrieben
      
      //    custom_info_window.js sollte geladen werden, wenn google.maps (GMap) vorhaden ist.
      //    oder nach dem laden der Karte CustomInfo() ausführen
      
      //    In Verwendung mit gmhelper.js reicht es die Datei im header zu anzugeben.
      
      //~ Beispiel CSS:
      
      //~ div.cCustomInfo {
        //~ padding: 0px 0px 8px 8px;
        //~ background: url(../images/point_bottom_left.png) no-repeat bottom left;
      //~ }

      //~ div.cCustomInfo_content {
        //~ background-color: #f2efe9; padding:2px;
        //~ width: auto;
        //~ white-space: nowrap;
        //~ padding: 2px;
      //~ }

      //~ div.cCustomInfo_offset {
        //~   top:10px;
        //~   left:20px; //* x , y *//
      //~ }

  function cCustomInfo(point, html) {
    this.point = point;
    this.html = html;
    this.pixelOffset = new google.maps.Size(offset[0],offset[1]);
    this.events = [];
    this.width = 0;
    this.height = 0;
    
    this._stealEvents = function(e) {
      if(navigator.userAgent.toLowerCase().indexOf('msie') != -1 && document.all) {
        window.event.cancelBubble = true;
        window.event.returnValue = false;
      } else { e.stopPropagation(); }
    }
    
    this.centerMap = function() {
      var p = this.map.fromLatLngToDivPixel(this.point)
      var map_center = this.map.fromLatLngToDivPixel(this.map.getCenter());
      var map_ne = this.map.fromLatLngToDivPixel(this.map.getBounds().getNorthEast());
      var map_sw = this.map.fromLatLngToDivPixel(this.map.getBounds().getSouthWest());
      var window_center = new google.maps.Point(p.x+(this.width/2)+this.pixelOffset.width,p.y-(this.height/2)-this.pixelOffset.height);
      if(map_sw.x > p.x || map_ne.x < p.x + this.pixelOffset.width + this.width || map_ne.y > p.y-this.height-this.pixelOffset.height || map_sw.y < p.y) {
        this.map.panTo(this.map.fromDivPixelToLatLng(window_center))
      }
    }
  } 

  cCustomInfo.prototype = new google.maps.Overlay();

  cCustomInfo.prototype.initialize = function(map) {
    google.maps.Event.trigger(map,'__remove_info_windows');
    var div = document.createElement("div");
    div.style.position = "absolute";
    
    var div_ci = document.createElement("div");
    div_ci.className = 'cCustomInfo';
    var div_content = document.createElement("div");
    div_content.className = 'cCustomInfo_content';
    
    if(typeof this.html == 'string') {
      div_content.innerHTML = this.html;
    } else {
      div_content.appendChild(this.html);
    }
    
    div_ci.appendChild(div_content);
    div.appendChild(div_ci);
    
    // default kartenevents ausschalten
    var stealEvents = ['mousedown', 'dblclick', 'DOMMouseScroll'];
    for( var e in stealEvents){ if(isNaN(e)){ continue; } this.events.push(google.maps.Event.bindDom(div_content, stealEvents[e], this, this._stealEvents)); }
    
    
    this.map = map;
    this.div = div;
    
    var self = this;
    this.events.push(google.maps.Event.addListener(this.map, '__remove_info_windows', function(e) {if(!e) {self.remove();}} ));
    this.events.push(google.maps.Event.addListener(this.map, 'click', function(e) {if(!e) {self.remove();}} ));
    this.map.getPane(G_MAP_FLOAT_PANE).appendChild(div);
    this.width = parseInt(getStyle(div,'width'));
    this.height = parseInt(getStyle(div,'height'));
    this.centerMap();
  }

  cCustomInfo.prototype.remove = function() {
    if(this.div.parentNode){ this.div.parentNode.removeChild(this.div); }
    for(var e in this.events){ if(isNaN(e)){ continue; } google.maps.Event.removeListener(this.events[e]); }
  }

  cCustomInfo.prototype.copy = function() { return new cCustomInfo(this.point, this.html); }


  cCustomInfo.prototype.redraw = function(force) {
    var p = this.map.fromLatLngToDivPixel(this.point);
    var left = (p.x + this.pixelOffset.width);
    var top = (p.y - this.pixelOffset.height - this.height);
    this.div.style.left = left + "px";
    this.div.style.top = top + "px";
  }

  // überschreiben der standartfunktionen

  google.maps.Map.prototype.openInfoWindowHtml = function(point,html) {
    this.__oCustomInfo = new cCustomInfo(point,html)
    this.addOverlay(this.__oCustomInfo);
  }

  google.maps.Map.prototype.closeInfoWindow = function() {
    if(this.__oCustomInfo){ this.__oCustomInfo.remove(); }
  }

  google.maps.Marker.prototype.openInfoWindowHtml = function(html) {
    var self = this
    self.__oCustomInfo = new cCustomInfo(self.getPoint(),html)
    self.__oCustomInfo.events.push( google.maps.Event.addListener(self, 'remove', function() { self.__oCustomInfo.remove();}));
    self[getMap(self)].addOverlay(self.__oCustomInfo);
  }

  google.maps.Marker.prototype.closeInfoWindow = function() {
    if(this.__oCustomInfo){ this.__oCustomInfo.remove(); }
  }
  
  var map = {};
  var offset =  getOffset();
  
  //* holt die map instanz aus einen objekt der maps api
  function getMap(object){
    if(!map[object]) {
      for(var prop in object) { if(object[prop] instanceof google.maps.Map || object[prop] instanceof GMap){ map[object] = prop; break; } }
    }
    return map[object];
  }
  
  function getOffset() {
    var temp = document.createElement("div");
    temp.className = 'cCustomInfo_offset';
    document.getElementsByTagName('body')[0].appendChild(temp);
    y = parseInt(getStyle(temp,'bottom'))
    x = parseInt(getStyle(temp,'left'))
    temp.parentNode.removeChild(temp)
    return [x,y]
  }
  //* Interne Funktion um übergebene Styleeigenschaften eines DOM Elements zu ermitteln.
  function getStyle(x,styleProp) {
    var y = x.style[styleProp];
    if(!y) {
      if (x.currentStyle) {
        var y = x.currentStyle[styleProp];
      } else if (window.getComputedStyle) {
        var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
      }
    }
    y = (styleProp == 'width' && y == 'auto') ?  x.offsetWidth : y
    y = (styleProp == 'height' && y == 'auto') ?  x.offsetHeight : y
    return y;
  }
}

if(typeof google == 'function' && typeof google.maps == 'function') { CustomInfo() }

