function mapCObj (element) {
   function isValid_geo(lat,lng){ return lat && lng && lat > -180.0 && lat < 180.0 && lng > -180.0 && lat > -180.0 && (lng != 0.0 || lat != 0.0) ; }
   var t = this;
// result list
   this.list = []; // result list array
   this.listCreate = function(e) {
      var j = jQuery(e).children();
      this.markers.init(j.length,true,false);
      for(var i = 0; i < j.length; i++) {
         j.eq(i).attr('index',this.list.length);
         this.list.push(j.eq(i));
         this.list[this.list.length-1].bind('mouseover',markerMouseOverHelper);
         this.list[this.list.length-1].bind('mouseout',markerMouseOutHelper);
      }
      this.listUpdate();
   }
   this.listSelect = function(i) { this.list[i].addClass('mSelected'); }
   this.listUnselect = function(i) { this.list[i].removeClass('mSelected'); }
   this.listUpdate = function() {
      var tmp,lat,lng,icon;
      for(var i = 0; i < this.list.length; i++) {
         lat = this.list[i].attr('lat');
         lng = this.list[i].attr('lng');
         icon = this.list[i].attr('icon');
         if (isValid_geo(lat,lng)) {
            tmp = new google.maps.LatLng(lat,lng);
            this.markers.set(i,tmp,icon,true);
            this.markers.show(i);
         }
      }
      this.zoom2Fit();
   }
//
   this.mapCreate = function (e) {
      if (mapCObj.prototype.lat && mapCObj.prototype.lng) var latlng = new google.maps.LatLng(mapCObj.prototype.lat,mapCObj.prototype.lng);
      else var latlng = new google.maps.LatLng(43.6419646, -79.3746487);
      var myOptions = {
         zoom: (mapCObj.prototype.zoom ? mapCObj.prototype.zoom : 10),
         center: latlng,
         mapTypeControl: false,
         mapTypeId: google.maps.MapTypeId.ROADMAP
      };
      var c = new google.maps.Map(e, myOptions);
//      var mapTypes = c.getMapTypes();
  // Overwrite the getMinimumResolution() and getMaximumResolution() methods
//      for (var i=0; i<mapTypes.length; i++) {
//         mapTypes[i].getMinimumResolution = function() {return this.minZoom;}
//         mapTypes[i].getMaximumResolution = function() {return this.maxZoom;}
//      }
      return c;
   }
   this.jq = jQuery(element);
   this.mDiv = this.jq.find('#MMap');
   this.spriteUrl = "img/icon_sprites.png";
   this.iconUrl = "img/marker_outline_map.png";
   this.minZoom = parseFloat(this.jq.attr('minLevel')); 
   this.maxZoom = parseFloat(this.jq.attr('maxLevel'));
   if (!this.minZoom) this.minZoom = 0.0;
   if (!this.maxZoom) this.maxZoom = 181.0;
   this.map = this.mapCreate(element);
//   this.closeInfoWindow = function () { map.closeInfoWindow(); }
   if (typeof SmartInfoWindow != 'undefined')
      this.infoWindow = null; 
   else
      this.infoWindow = new google.maps.InfoWindow();
   this.panToMarker = function(i) { map.panTo(this.markers.buf[i].getLatLng()); }
   this.markers = {}; 
   this.markers.buf = [];
   this.markers.tabBuf = [];
   //   GMarker.prototype.open = function() {
   //      this.openInfoWindowHtml(searchPage.tSearch.result.infoWindowHtml(this.index));
   //      searchPage.tSearch.result.select(this.index);
   //   }
   //   GMarker.prototype.openDetails = function () {
   //      t.closeInfoWindow();
   //      searchPage.tDetails.openByIndex(this.index);
   //   }
   this.markers.create = function(opts) {
      var icon;
      icon = new google.maps.MarkerImage(this.spriteUrl,new google.maps.Size(40,40),new google.maps.Point(0,0));
//      opts.icon = icon;
      return new google.maps.Marker(opts);
   }
   this.markers.clearBound = function () {
      if (this.bounds) delete this.bounds;
      this.bounds = new google.maps.LatLngBounds();
//      this.min = {lat:180,lng:180};
//      this.max = {lat:-180,lng:-180};
   }
   function markerDragHelper() {
        var pt,lat,lng ;
   	pt = this.getLatLng();
        lat = pt.lat();
        lng = pt.lng();
//	lat = Math.round((pt.lat() * 10000000))/10000000;
//	lng = Math.round((pt.lng() * 10000000))/10000000;
	tab.cPanel.find(".lat").val(lat);
	tab.cPanel.find(".lng").val(lng);
        if (tab.cObj.setChange) tab.cObj.setChange(); //t.fDetails.changed = true ;
        if (tab.cObj.markerMove) tab.cObj.markerMove(pt);
   }
   function markerMouseOverHelper() {
      var i ; 
      if (typeof this.index == "undefined") i = jQuery(this).attr('index');
      else i = this.index;
      clearTimeout(t.scheduleId);
      if (t.scheduleOut != i) {
         t.listSelect(i); 
         t.markers.select(i,true);
      }
   }
   function markerMouseOutHelper() {
      var i ; 
      if (typeof this.index == "undefined") i = jQuery(this).attr('index');
      else i = this.index;
      t.scheduleOut = i;
// timeout is to smooth the flickering
      t.scheduleId = setTimeout(function() {t.listUnselect(i); t.markers.unselect(i); t.scheduleOut = -1;},50);
   }
   function markerClickHelper() {
      var i ; 
      if (typeof this.index == "undefined") i = jQuery(this).attr('index');
      else i = this.index;
      if (t.list[i].attr('href'))
         if (t.list[i].hasClass('register')) {
            $("<a href='"+t.list[i].attr('href')+"'></a>").nyroModalManual({width:900,height:700});
         } else {
            window.location = t.list[i].attr('href');
         }
//      this.openDetails();
//      searchPage.tDetails.openByIndex(this.index);
//      do nothing now
   }
   this.markers.init = function (num,bInfo,bDraggable) {
// multiple calls of this function is possible, it will just increase the list size
      var bptr = this.buf.length ;
      var eptr = this.buf.length + num;
      for (var i = bptr; i < eptr; i++) {
         this.buf[i] = this.create({position:google.maps.LatLng(0,0),draggable:bDraggable,map:t.map});
	 this.buf[i].setVisible(false);
         this.buf[i].index = i;  // for reference
         this.buf[i].visible = false ;  // to remember if it is shown
         this.buf[i].isset = false ; // to remember if this is valid
//         t.map.addOverlay(this.buf[i]);
         if (bInfo) {
	    google.maps.event.addListener(this.buf[i],'mouseover',markerMouseOverHelper); //function() { this.open(); });
	    google.maps.event.addListener(this.buf[i],'mouseout',markerMouseOutHelper); //function() { this.closeInfoWindow(); });
   	    google.maps.event.addListener(this.buf[i],'click',markerClickHelper); //function() { this.openDetails(); });
         }
         if (bDraggable) google.maps.event.addListener(this.buf[i],'dragend',markerDragHelper);
      }
      this.refPtr.j = this.buf[this.buf.length - 1];
//      var s = getGMarkerIconTag(this.buf[0]); // this is to retrieve the field name in GMarker
//      for (var i = bptr; i < eptr; i++) { 
//         this.buf[i].jqIcon = jQuery(this.buf[i][s][0].firstChild); // this is a hack
//         this.buf[i].jqIcon.before('<img src="'+this.iconUrl+'"></img>');
//      }
   }
   this.markers.set = function(i,latlng,img,bBound) {
        this.buf[i].setPosition(latlng);
// hacking GMap Internals
        if(img) this.setIcon(i,img);
        this.buf[i].isset = true ;
        if(bBound) {
           this.setBound(latlng);
        }
   }
//   this.markers.min = {lat:90,lng:180};
//   this.markers.max = {lat:-90,lng:-180};
   this.markers.clearBound();
   this.markers.setBound = function(latlng) {
//      if(lng < this.min.lng) this.min.lng = lng;
//      if(lng > this.max.lng) this.max.lng = lng;
//      if(lat < this.min.lat) this.min.lat = lat;
//      if(lat > this.max.lat) this.max.lat = lat;
     this.bounds.extend(latlng);
   }
   this.markers.isset = function(i) { return this.buf[i].isset; }
   this.markers.isHidden = function(i) { return ! this.buf[i].visible; }
   this.markers.openInfo = function(i) { 
      var j = jQuery("<div>"+t.list[i].html()+"</div>");
      j.find(".mX").remove();
      if (typeof SmartInfoWindow != 'undefined') {
         if (t.infoWindow) {
            t.infoWindow.close();
            delete t.infoWindow;
         }
         t.infoWindow = new SmartInfoWindow({position:t.markers.buf[i].getPosition(),map:t.map,content:"<div class='infoWinDiv'>"+j.html()+"</div>"});
      } else {
         t.infoWindow.setContent("<div class='infoWinDiv'>"+j.html()+"</div>");
         t.infoWindow.open(t.map,this.buf[i]);
      }
   }
   this.markers.openDetails = function(i) { this.buf[i].openDetails(); }
   this.markers.isInBound = function(i) {
      var x = map.getBounds();
      return x.containsLatLng(this.buf[i].getLatLng());
   }
   this.markers.setIcon = function(i,img) { 
// hacking GMap Internals
      try { this.buf[i].setIcon(img); }  //setIcon(this.buf[i].jqIcon,img); } 
      catch (e) {}
   }
   this.markers.show = function (i) {
      if(this.buf[i].isset) { this.buf[i].setVisible(true); this.buf[i].visible = true; }
   }
   this.markers.hide = function (i, bRestore) {
      var b = (isset(bRestore) ? bRestore : false);
      this.buf[i].setVisible(false);
      this.buf[i].visible = b; //false ;
//      this.buf[i].jqIcon.parent().stop(true,true); // stoping bounce animation
//      if(map) map.closeInfoWindow();
      t.infoWindow.close();
   }
   this.markers.showAll = function () {
      var i;
      for (var i = 0; i < this.buf.length; i++) {
         if(this.buf[i].isset) { 
            this.buf[i].setVisible(true); 
            this.buf[i].visible = true; 
         }
      }
   }
   this.markers.hideAll = function (bRestore) {
      var b = (isset(bRestore) ? bRestore : false );  // if it needs to be remember, set bRestore = true
//      for (i = 0; i < this.buf.length; i++) { this.buf[i].hide(); this.buf[i].visible = (b && this.buf[i].visible); this.buf[i].jqIcon.parent().stop(true,true); }
      for (var i = 0; i < this.buf.length; i++) { this.hide(i,b); }
//      if (map) map.closeInfoWindow();
   }
   this.markers.unset = function(i) {
      this.buf[i].hide();
      this.buf[i].isset = false ;
      this.buf[i].visible = false ;
   }
   this.markers.clearAll = function () {
      for (var i = 0; i < this.buf.length; i++) { this.unset(i); }
//      if (map) map.closeInfoWindow();
      t.InfoWindow.close();
      this.clearBound();
   }
   this.markers.setAlpha = function(i,p) {
      this.buf[i].jqIcon.parent().fadeTo('fast',p);
   }
   this.markers.setZ = function(i,x) {
      if(this.buf[i]) this.buf[i].jqIcon.parent().css('z-index',x);
   }
   this.markers.bounce = function(i) {
      this.buf[i].jqIcon.parent().animate({top: "-=10px"},'fast',function() {
        jQuery(this).animate({top: "+=10px"},'fast');
      });
   }
   this.markers.select = function(x,bNoBounce) {
      if (!this.isHidden(x)) {
//         mapC.markers.openInfo(x);
         this.openInfo(x);
//         for (var i = 0; i < this.buf.length; i++) {
//            if (i == x) {
//               mapC.markers.setAlpha(i,1);
//               mapC.markers.setZ(i,10);
//               if(!bNoBounce) mapC.markers.bounce(i);
//               if(!mapC.markers.isInBound) mapC.panToMarker(i);
//            } else {
//               mapC.markers.setAlpha(i,0.25);
//               mapC.markers.setZ(i,'');
//            }
//         }
         this.lastSelect = x ;
      } else {
         this.lastSelect = -1 ;
//         map.closeInfoWindow();
         t.infoWindow.close();
      }
   }
   this.markers.unselect = function() {
//      for (var i = 0; i < this.buf.length; i++) {
//         mapC.markers.setAlpha(i,1);
//         mapC.markers.setZ(i,'');
//      }
//      mapC.markers.setZ(this.lastSelect,'');
//      map.closeInfoWindow();
      if(t.infoWindow) t.infoWindow.close();
   }
   this.markers.refPtr = {};
   this.markers.refPtr.set = function (latlng) { t.markers.set(t.markers.buf.length - 1, latlng,"start",true); t.markers.setZ(t.markers.buf.length - 1, 10);}
   this.markers.refPtr.unset = function () { t.markers.unset(t.markers.buf.length - 1); }
   this.markers.refPtr.show = function () { t.markers.show(t.markers.buf.length - 1); } 
   this.markers.refPtr.hide = function () { t.markers.hide(t.markers.buf.length - 1); }
   this.zoom2Fit = function() {
//      var min = this.markers.min;
//      var max = this.markers.max;
//      if(isValid_geo(min.lat,min.lng) && isValid_geo(max.lat,max.lng)) {
//         var bound = new google.maps.LatLngBounds(new google.maps.LatLng(this.markers.min.lat,this.markers.min.lng), new google.maps.LatLng(this.markers.max.lat,this.markers.max.lng));
//         var zlevel = map.getBoundsZoomLevel(bound);
//         zlevel = (zlevel >= 15 ? 15 : zlevel);
////         map.setCenter(bound.getCenter(), zlevel);
//         map.setZoom(zlevel);
//         map.panTo(bound.getCenter());
//      }
      var b = this.markers.bounds.isEmpty();
      if(this.lat && this.lng) this.markers.bounds.extend(new google.maps.LatLng(this.lat,this.lng));
//
// setting min bounds
//
      var span = this.markers.bounds.toSpan();
      var c = this.markers.bounds.getCenter();
      var nb = this.markers.bounds;
      if (span.lat() <= this.minZoom || span.lng() <= this.minZoom) {
         nb = new google.maps.LatLngBounds(new google.maps.LatLng(c.lat()-this.minZoom,c.lng()-this.minZoom), new google.maps.LatLng(c.lat()+this.minZoom, c.lng()+this.minZoom));
      }
      if (span.lat() >= this.maxZoom || span.lat() >= this.maxZoom) {
         nb = new google.maps.LatLngBounds(new google.maps.LatLng(c.lat()-this.maxZoom,c.lng()-this.maxZoom), new google.maps.LatLng(c.lat()+this.maxZoom, c.lng()+this.maxZoom));
      }
      if(!b) this.map.fitBounds(nb);
   }
   this.postprocess = function() {
      if(this.mButtonStates[1]) this.zoom2Fit();
   }
// zoom control
//   this.onZoomChanged = function() {
//      if (t.onZoomChanged.p) return;
//
//      if (t.map.getZoom() > t.maxZoom) {
//         t.onZoomChanged.p = true;
//         t.map.setZoom(t.maxZoom);
//         t.onZoomChanged.p = false;
//      }
//      else if (t.map.getZoom() < t.minZoom) {
//         t.onZoomChanged.p = true;
//         t.map.setZoom(t.minZoom);
//         t.onZoomChanged.p = false;
//      }
//   }
//   this.onZoomChanged.p = false;
//   google.maps.event.addListener(this.map, 'zoom_changed', t.onZoomChanged);
//
//   google.maps.event.addListener(this.map,"dragend", function () {
//      if (t.isDisplayAll() && !searchPage.tSearch.isHidden())  searchPage.tSearch.displayAll(); 
//   });
//    this.jq.find('#GMap').droppable({
// 	accept: '.dragMarker',
// 	drop: function(ev, ui) { 
// // assuming dropping marker[0]
// 		var gmap_offset = t.jq.find('#GMap').offset();
// 		var point = new google.maps.Point(ui.absolutePosition.left - gmap_offset.left, ui.absolutePosition.top - gmap_offset.top);
// 		var latlng = t.map.fromContainerPixelToLatLng(point); 
// 		var icon,iconname;
//                 tab.cPanel.find('.lat').val(latlng.lat());
//                 tab.cPanel.find('.lng').val(latlng.lng());
//                 if (mapC.markers.isHidden(0)) {
//                    tab.cPanel.find('.latgeo').val('-180.0');
//                    tab.cPanel.find('.lnggeo').val('-180.0');
// 		   tab.cPanel.find('[name="geoacc"]').val(8); // assuming drag & drop has the highest accuracy
//                 }
// 		icon = t.markers.buf[0].getIcon();
//                 if (tab.cObj.setChange) tab.cObj.setChange();
// 		point = new GPoint(point.x + icon.iconAnchor.x, point.y + icon.iconAnchor.y);
// 		latlng = t.map.fromContainerPixelToLatLng(point);
//                 iconname = tab.cPanel.find('[name="icon"]').val();
// 		t.markers.set(0,latlng,iconname,false);
//                 t.markers.show(0);
// 	}
//    });
//    this.spbuf = [];
//    this.savePosition = function() {
//       var x = {c : map.getCenter(), z : map.getZoom() };
//       this.spbuf.push(x);
//    }
//    this.returnToSavedPosition = function() {
//       var x = this.spbuf.pop();
//       map.setZoom(x.z);
//       map.panTo(x.c);
//    }
}

function addrGeo(element,url) {
   var t = this;
   this.url = ( url ? url : window.location.href );
   this.j = jQuery(element);
   this.googleUrl = "http://maps.google.com/maps/api/geocode/json";
   this.j.keypress(function(e) {
      if (e.keyCode == '13') { // enter key
         t.addr = t.j.val();
         var geocoder = new google.maps.Geocoder();
         geocoder.geocode({'address':t.addr},t.geoResponse);
      }
   });
   this.geoResponse = function(d,s) {
      if (s == "OK") {
         t.j.removeClass('mFailed');
         var q = t.url;
         q=q.replace(/addr.*&*/,'');
         q=q.replace(/lat.*&*/,'');
         q=q.replace(/lng.*&*/,'');
         if (q.search(/\?/) == -1) q+='?addr='+escape(t.addr);
         else q+="&addr="+escape(t.addr);
         q+="&lat="+d[0].geometry.location.lat();
         q+="&lng="+d[0].geometry.location.lng();
         window.location = q;
      } else {
         t.j.addClass('mFailed');
      }
   }
}

