function mapCObj (element) {
   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[i].bind('mouseover',markerMouseOverHelper);
         this.list[i].bind('mouseout',markerMouseOutHelper);
      }
      this._listUpdate();
   }
   this.listDelete = function() { delete this.list; this.list = []; this.markers.clearAll(); }
   this.listSelect = function(i) { this.list[i].addClass('mSelected'); }
   this.listUnselect = function(i) { this.list[i].removeClass('mSelected'); }
   this._listUpdate = function() {
      var tmp;
      for(var i = 0; i < this.list.length; i++) {
         tmp = new google.maps.LatLng(this.list[i].attr('lat'),this.list[i].attr('lng'));
         this.markers.set(i,tmp,false,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
      };
      return new google.maps.Map(e, myOptions);
   }
   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 = 30;
   this.maxZoom = 50;
   this.map = this.mapCreate(element);
   this.setCenter = function(lat,lng) {
      var c = new google.maps.LatLng(lat,lng); 
      this.map.setCenter(c);
      this.lat = lat;
      this.lng = lng;
   }
//   this.closeInfoWindow = function () { map.closeInfoWindow(); }
   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;
      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.listUnselect(i);
      t.markers.unselect(i);
   }
   function markerClickHelper() {
//      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) { 
      t.infoWindow.setContent("<div class='infoWinDiv'>"+t.list[i].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 { 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].setVisible(false);
      this.buf[i].isset = false ;
      this.buf[i].visible = false ;
   }
   this.markers.clearAll = function () {
      t.infoWindow.close();
      for (var i = 0; i < this.buf.length; i++) { this.unset(i); }
//      if (map) map.closeInfoWindow();
      this.clearBound();
   }
   this.markers.deleteAll = function () {
      t.infoWindow.close();
      for (var i = this.buf.length - 1; i >= 0; i--) { delete this.buf[i]; }
      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();
      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));
      if(!b) this.map.fitBounds(this.markers.bounds);
   }
   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,callback) {
   var t = this;
   this.url = ( url ? url : window.location.href );
   this.j = jQuery(element);
   this.callback = callback;
   this.googleUrl = "http://maps.google.com/maps/api/geocode/json";
   this.j.keypress(function(e) {
      if (e.keyCode == '13') { // enter key
         t.geoSubmit();
//         t.addr = t.j.val();
//         var geocoder = new google.maps.Geocoder();
//         geocoder.geocode({'address':t.addr,'region':'ca'},t.geoResponse);
      }
   });
   this.geoSubmit = function() {
      t.addr = t.j.val();
      var geocoder = new google.maps.Geocoder();
      geocoder.geocode({'address':t.addr,'region':'ca'},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;
         mapC.setCenter(d[0].geometry.location.lat(),d[0].geometry.location.lng());
         if (t.j.attr('target')) {
            jQuery('#'+t.j.attr('target')).text(t.j.val());
         }
         if (typeof callback == "function") callback();
      } else {
         t.j.addClass('mFailed');
      }
   }
}

