var HCH = {
	socio_demographical:{
	},
	facet:{	
	},
	home: {
		util: {
			// HOME SPECIFIC
			//==============
			//default values of transaction and super category:
			transactionType:"rent",
			superCategory:"residential",
			urlContext:"",

			//initializes all tabs for rent / buy / commercial / residential
			initAllTabs: function(transactionType,superCategory,urlContext) {
				HCH.home.util.transactionType=transactionType;
				HCH.home.util.superCategory=superCategory;
				HCH.home.util.urlContext=urlContext;
				jQuery(".ui-main-tab, .ui-under-tab").find("a").each( function(index, value) {
					jQuery( this ).click( function() {
						return HCH.home.util.selectTab( jQuery( this ).attr("id") );					   
					});
				});
				HCH.home.util.selectTab();
			},

			//clears all tabs for rent / buy / commercial / residential
			resetAllTabs: function() {
				jQuery(".tab-container").addClass("hide");
				jQuery(".ui-main-tab #first").removeClass("active");
				jQuery(".ui-main-tab, .ui-under-tab").find("a").each( function(index, value) {
					jQuery( this ).parent().removeClass("active");	
				});
			},

			// Activates the appropriate tab and tab container depending on the selected rent / buy and commercial / residential tabs
			selectTab: function (id) {
				if (id) {
					if (id.indexOf("myhome")>=0) {
						HCH.home.util.resetAllTabs();						
						jQuery("#tab-myhome-myhome").removeClass("hide");
						jQuery(".panel-search-distance-new").addClass("hide");
						HCH.home.util.switchTransactionTab();
						HCH.home.util.switchMyHomeTab();
						//netMetrics();

						// reload NetMetrix tracking
						HCH.util.trackingNetMetrix(HCH.home.util.urlContext);

						return false;
					} else {
						if (id.indexOf("residential")>=0) 
							HCH.home.util.superCategory="residential";
						if (id.indexOf("commercial")>=0) 
							HCH.home.util.superCategory="commercial";
						if (id.indexOf("rent")>=0) 
							HCH.home.util.transactionType="rent";
						if (id.indexOf("buy")>=0) 
							HCH.home.util.transactionType="buy";

						HCH.util.trackingNetMetrix(HCH.home.util.urlContext);
						//netMetrics();
					}
				}
				var tabId = "#tab-"+HCH.home.util.superCategory+"-"+HCH.home.util.transactionType;
				HCH.home.util.resetAllTabs();
				jQuery( tabId ).removeClass("hide");
				jQuery(".panel-search-distance-new").removeClass("hide");
				HCH.home.util.switchTransactionTab();
				HCH.home.util.switchSuperCategoryTab();

				return false;
			},

			//Switches the appropriate tab depending on the currently selected transaction:
			switchTransactionTab: function() 
			{
				jQuery( '.ui-under-tab [id="tab-'+HCH.home.util.transactionType+'"]' ).parent().addClass("active");	
			},
			//Switches the appropriate tab depending on the currently selected super category:
			switchSuperCategoryTab: function() 
			{
				jQuery('.ui-main-tab [id="tab-'+HCH.home.util.superCategory+'"]' ).parent().addClass("active");
				if(HCH.home.util.superCategory == "residential")
				{ 
					jQuery(".ui-main-tab #first").addClass("active"); 
				}
			},
			//Switches the MyHome tab:
			switchMyHomeTab: function() 
			{
				jQuery('.ui-main-tab [id="tab-myhome"]').parent().addClass("active");
			}
		}
	},
	result: {
		rerender: {},
		util: {
			// RESULT LIST SPECIFIC
			//=====================
			// change sortorder
			changesorting: function(v) {
				window.location.href = v;
			},

			// pattern for coordinate replacements
			gmap: {
				// GLatLng helper array
				a: [],

				// GMarker helper array
				m: [],

				// poi z-index helper array
				z: [],

				// any pois to show at all
				blnPois: false,

				// onclick tooltip visible
				blnPoiMCv: false,
				// corresponding index
				idxPoiMCv: null,

				// hover tooltip visible
				blnPoiMOv: false,
				// corresponding index
				idxPoiMOv: null,
				
				// true if the distance form is set
				blnIsDistance: false,
				
				// poi ico helper array
				p: ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T"],

				// custom GMarker helper
				cM: function() {},

				// prepare poi/marker data
				setup: function() {
					// reset helper arrays and blnPois
					HCH.result.util.gmap.a,HCH.result.util.gmap.m = [];
					HCH.result.util.gmap.blnPois = false;

					var _v = HCH.result.rerender.v;
					for (var i = 0; i < _v.length; i++) {
						// if accuracy is sufficient, proceed with markers
						if (parseInt(_v[i][3],10) > 5) {
							HCH.result.util.gmap.a[i] = new GLatLng(_v[i][1],_v[i][2]);// store gmap compatible obj (GLatLang) in helper array
							HCH.result.util.gmap.m[i] = HCH.result.util.gmap.cM(HCH.result.util.gmap.a[i],i,HCH.result.rerender.r[i].levelOne);// push new marker in marker array, pass counter and lvl
							HCH.result.util.gmap.blnPois = true;// switch map enabler
						} else {
							HCH.result.util.gmap.a[i] = null;
							HCH.result.util.gmap.m[i] = null;
						}
					}
					var _a = jQuery("#result_list .img_cnt");// need array idx of clicked result item (matching v[idx])
					for (var y = 0; y < _a.length; y++) {
						jQuery.data(_a[y], 'idx', y);// inject idx as jquery data
					}
				},

				// fit feeded pois on map with appropriate zoom
				fit: function(arrayOfMarkers,objMap) {
					var _bounds = new GLatLngBounds();
					var _i = 0;
					while (_i < arrayOfMarkers.length) {
						if (arrayOfMarkers[_i]) {
							_bounds.extend(arrayOfMarkers[_i].getPoint());
						}
						_i++;
					}
					var _latCenter = (_bounds.getNorthEast().lat() + _bounds.getSouthWest().lat()) / 2;
					var _lngCenter = (_bounds.getNorthEast().lng() + _bounds.getSouthWest().lng()) / 2;
					var _center = new GLatLng(_latCenter,_lngCenter);
					var _zoom = objMap.getBoundsZoomLevel(_bounds);
					// set a min zoom
					var _minZoom = 13;
					if(_zoom > _minZoom){
						_zoom = _minZoom;
					}
					objMap.setCenter(_center, _zoom);
				},

				// prepare poi coordinates for container pixel transformation
				calcXY: function(mIdx) {
					var latToTransform = HCH.result.rerender.v[mIdx][1];
					var lngToTransform = HCH.result.rerender.v[mIdx][2];
					_xy = _gmap.fromLatLngToContainerPixel(new GLatLng(latToTransform,lngToTransform));
					return _xy;
				},

				// toggle hover tooltip
				togglePoiMO: function(nr) {
					if (HCH.result.util.gmap.blnPoiMOv) {
						jQuery("#mo_side_map").hide();
						HCH.result.util.gmap.blnPoiMOv = false;
						HCH.result.util.gmap.idxPoiMOv = null;
					} else {
						jQuery("#mo_side_map").show();
						HCH.result.util.gmap.blnPoiMOv = true;
						HCH.result.util.gmap.idxPoiMOv = nr;
					}
				},

				// hide hover tooltip
				hidePoiMO: function() {
					jQuery("#mo_side_map").hide();
					HCH.result.util.gmap.blnPoiMOv = false;
					HCH.result.util.gmap.idxPoiMOv = null;
				},

				// show onlick tooltip
				showPoiMC: function(nr) {
					//HCH.result.util.gmap.m[nr].Tq[0].style.zIndex = HCH.result.util.gmap.z[nr][1] + 200000;// increase z-index before showing
					jQuery("#mc_side_map").show();
					HCH.result.util.gmap.blnPoiMCv = true;
					HCH.result.util.gmap.idxPoiMCv = nr;
				},

				// hide onclick tooltip
				hidePoiMC: function(nr) {
					/*if (nr) {
						HCH.result.util.gmap.m[nr].Tq[0].style.zIndex = HCH.result.util.gmap.z[nr][1];// restore initial zindex
					}*/
					jQuery("#mc_side_map").hide();
					HCH.result.util.gmap.blnPoiMCv = false;
					HCH.result.util.gmap.idxPoiMCv = null;
				},

				// handle poi mouseclick in result list and side map
				poiMC: function(poi_index,blnReCenter) {
					// first, hide any mouseover tooltip
					if (HCH.result.util.gmap.blnPoiMOv) {
						HCH.result.util.gmap.hidePoiMO();
					}

					// reset zoom if result item triggered
					if (blnReCenter) {
						HCH.result.util.gmap.fit(HCH.result.util.gmap.m,_gmap);
					}

					// conditional toggle for onclick tooltip
					if (HCH.result.util.gmap.blnPoiMCv) {
						if (poi_index == HCH.result.util.gmap.idxPoiMCv) {
							HCH.result.util.gmap.hidePoiMC(poi_index);
							return;
						} else {
							HCH.result.util.gmap.hidePoiMC(HCH.result.util.gmap.idxPoiMCv);
						}
					}

					// prepare click-tooltip position to match current layout/flyout
					var _mc_xy = HCH.result.util.gmap.calcXY(poi_index);
					var _left = _mc_xy.x - 525;
					var _top = _mc_xy.y - 69;
					jQuery("#mc_side_map").css({'left': _left + 'px','top': _top + 'px'});

					// empty any existing tooltip content
					var _ct = jQuery("#ct_mc");
					_ct.empty();

					// clone, refine and append result item html
					jQuery("#result_list .r_i:not(.adv1)").eq(poi_index).clone().appendTo(_ct);
					jQuery(".img_cnt, .r_i_fav, a.more",_ct).remove();
					// remove thumbnail for lvl2 ads
					if (!HCH.result.rerender.r[poi_index].levelOne) {
						jQuery(".r_i_img",_ct).remove();
						jQuery(".r_i_c",_ct).css("marginLeft",0);
					}

					// show tooltip, scroll map into view
					HCH.result.util.gmap.showPoiMC(poi_index);
					HCH.util.scrollIntoView("ct_hom_tabholder",100);
				},

				// handle poi mouseover in side map
				poiMOv: function() {},

				// prepare overlays and events
				init: function() {
					// if paged, hide any open tooltips/overlays
					_gmap.clearOverlays();
					HCH.result.util.gmap.hidePoiMO();
					HCH.result.util.gmap.hidePoiMC(HCH.result.util.gmap.idxPoiMCv);

					HCH.result.util.gmap.setup();
					if (HCH.result.util.gmap.blnPois) {
						jQuery("#gmap").show();
						for (var j = 0; j < HCH.result.util.gmap.m.length; j++) {
							if (HCH.result.util.gmap.m[j]) {
								_gmap.addOverlay(HCH.result.util.gmap.m[j]);// add GMarker overlays
								//HCH.result.util.gmap.z.push([HCH.result.util.gmap.m[j].Tq[0].id,parseInt(HCH.result.util.gmap.m[j].Tq[0].style.zIndex,10)]);// fill zindex helper
							} else {
								HCH.result.util.gmap.z.push([null,null]);
							}
						};

						// add small zoom control
						_gmap.addControl(new GSmallZoomControl());

						// add GMap events here
						GEvent.addListener(_gmap, "movestart", function() {
							HCH.result.util.gmap.hidePoiMO();
							HCH.result.util.gmap.hidePoiMC(HCH.result.util.gmap.idxPoiMCv);
						});
						GEvent.addListener(_gmap, "dragstart", function() {
							HCH.result.util.gmap.hidePoiMO();
							HCH.result.util.gmap.hidePoiMC(HCH.result.util.gmap.idxPoiMCv);
						});
						GEvent.addListener(_gmap, "zoomend", function() {
							HCH.result.util.gmap.hidePoiMO();
							HCH.result.util.gmap.hidePoiMC(HCH.result.util.gmap.idxPoiMCv);
						});

						// poi fitting, finalize map
						HCH.result.util.gmap.fit(HCH.result.util.gmap.m,_gmap);
					} else {
						jQuery("#gmap").hide();
					}
				},

				// update map tab to reflect small map focus
				updateFullMapTab: function(link, lat1, lat2, lng1, lng2, zoom) {
					jQuery(link).attr("href", function() {
						return HCH.result.util.gmap.replaceTabLatLng(link.href,lat1,lat2,lng1,lng2,zoom);
					});
				},


				// FULL MAP SPECIFIC
				//==================
				// map focus coordinates
				lat1: "",
				lat2: "",
				lng1: "",
				lng2: "",
				// tile handling helper
				upperLeftTileCoordinate: [],
				// info message helper
				visiblePoiCount: 0,
				maxResultCount: 0,

				// calculate and set upper left tile coordinates
				setUpperLeftTileCoordinates: function(){
					var northWestLat = _gmap.getBounds().getNorthEast().lat();
					var northWestLng = _gmap.getBounds().getSouthWest().lng();
					var northWestLatLng = new GLatLng(northWestLat, northWestLng);
					var northWestPoint = _gmap.getCurrentMapType().getProjection().fromLatLngToPixel(northWestLatLng,_gmap.getZoom());
					var upperLeftTileX = Math.floor(northWestPoint.x/256);
					var upperLeftTileY = Math.floor(northWestPoint.y/256);
					HCH.result.util.gmap.upperLeftTileCoordinate = [upperLeftTileX, upperLeftTileY];
				},

				// calculate and get upper left tile coordinates
				getUpperLeftTileCoordinates: function(){
					var northWestLat = _gmap.getBounds().getNorthEast().lat();
					var northWestLng = _gmap.getBounds().getSouthWest().lng();
					var northWestLatLng = new GLatLng(northWestLat, northWestLng);
					var northWestPoint = _gmap.getCurrentMapType().getProjection().fromLatLngToPixel(northWestLatLng,_gmap.getZoom());
					HCH.result.util.gmap.upperLeftTileX = Math.floor(northWestPoint.x/256);
					HCH.result.util.gmap.upperLeftTileY = Math.floor(northWestPoint.y/256);
					var tileCoordinate = new Array(HCH.result.util.gmap.upperLeftTileX, HCH.result.util.gmap.upperLeftTileY);

					return tileCoordinate;
				},

				// ad detail thumbnail html to be shown in infowindow
				itemLevelHtml: function(blnT, blnH, blnL2) {
					var _s = '<div class=\"r_i ';
					if (blnL2) {
						_s += 'l2';
					} else {
						if (blnT) {
							_s += 't';
						} else {
							if (blnH) {
								_s += 'h';
							} else {
								_s += 'l1';
							}
						}
					}
					_s += ' clear\">';

					return _s;
				},

				// ad detail thumbnail html to be shown in infowindow
				itemThumbHtml: function() {},

				// ad detail price html to be shown in infowindow
				itemPriceHtml: function() {},

				// ad detail properties html to be shown in infowindow
				itemPropsHtml: function() {},

				// ad detail extras html to be shown in infowindow
				itemExtrasHtml: function() {},

				// ad detail logo html to be shown in infowindow
				itemLogoHtml: function() {},

				// build poi HTML (infowindow)
				itemHtml: function() {},

				// async post: fetching detail data, success: overwrite data, complete: process detail html and pop gmap infowindow
				getDataByAdId: function() {},

				// shows info message according to numbers of result found in current map section (not triggered on initial search)
				showInfoMessage: function(blnFirstSearch) {
					if (!blnFirstSearch) {
						// for each poi in current map bounds the var visiblePoiCount is increased (see HCH.result.util.gmap.showResultMarker).
						// on each map search, rerender.maxResultCount (total results available) and rerender.v.length (max. 200 first results) are recalculated,
						// so to have an indicator about how many results are not shown, the following math returns the result
						var containsResultCount = HCH.result.rerender.maxResultCount - (HCH.result.rerender.v.length - HCH.result.util.gmap.visiblePoiCount);
						if (containsResultCount >= 200) {// more potentially visible results -> show info
							jQuery("#fullmap_info_nores").hide();
							jQuery("#fullmap_info").show(1000);
						} else if (containsResultCount == 0) {// no results in current bounds
							jQuery("#fullmap_info").hide();
							jQuery("#fullmap_info_nores").show(1000);
						} else {// 1-199 visible results -> no special info
							jQuery("#fullmap_info_nores,#fullmap_info").hide(1000);
						}
					}
				},

				// enrich poi click (GEvent) with adId and trigger infowindow preparation
				closrPC: function(idx) {
					return function(evt) {
						HCH.result.util.gmap.bubbleActive = true;
						if (jQuery.browser.msie && jQuery.browser.version == 7) {// IE7 ajax json bugged
							return;
						}
						HCH.result.util.gmap.getDataByAdId(this,HCH.result.rerender.v[idx][0]);
					};
				},

				// process search results, marker setup, remove busy layer
				showResultMarker: function() {},

				// marker icon placeholder
				basic_icon: "",

				// infowindow status
				bubbleActive: false,

				// toggle busy layer (overlaying map)
				indicateBusy: function(elId, bln) {
					jQuery(elId).toggle(bln);
				},

				// clear gmap overlays
				resetMapState: function() {
					_gmap.clearOverlays();
					HCH.result.util.gmap.bubbleActive = false;
					HCH.result.util.gmap.visiblePoiCount = 0;
				},

				// update filter links to reflect map focus
				updateFilterLink: function(link, lat1, lat2, lng1, lng2, zoom) {
					jQuery(link).attr("href", function() {
						return HCH.result.util.gmap.replaceLatLng(link.href,lat1,lat2,lng1,lng2, zoom);
					});
				},

				// update facet links to reflect map focus
				updateFacetLink: function(link, lat1, lat2, lng1, lng2, zoom) {
					jQuery(link).attr("href", function() {
						return HCH.result.util.gmap.replaceLatLng(link.href,lat1,lat2,lng1,lng2, zoom);
					});
				},

				// update search to reflect map focus
				updateSearch: function(elId, lat1, lat2, lng1, lng2, zoom) {
					// dedicated hidden field is changed accordingly
					jQuery(elId).attr("value", function() {
						var sw = new GLatLng(lat1,lng1);
						var ne = new GLatLng(lat2,lng2);
						var latlng = "/m/" + sw.toUrlValue() + "/" + ne.toUrlValue() + "/" + zoom;
						return latlng;
					});
				},

				// update language links to reflect small map focus
				updateLanguageSwitch: function(link, lat1, lat2, lng1, lng2, zoom) {
					jQuery(link).attr("title", function() {
						return HCH.result.util.gmap.replaceTabLatLng(link.title,lat1,lat2,lng1,lng2,zoom);
					});
				},

				// update map tab to reflect small map focus
				updateTab: function(link, lat1, lat2, lng1, lng2, zoom) {
					jQuery(link).attr("href", function() {
						return HCH.result.util.gmap.replaceTabLatLng(link.href,lat1,lat2,lng1,lng2,zoom);
					});
				},

				// context replace helper
				replaceTabLatLng: function(link, lat1, lat2, lng1, lng2, zoom) {
					var sw = new GLatLng(lat1,lng1);
					var ne = new GLatLng(lat2,lng2);
					var latlng = "/" + sw.toUrlValue() + "/" + ne.toUrlValue();
					if (zoom != null) {
						latlng = latlng + "/" + zoom;
					}
					if (link.search(/\?/)!=-1) {
						var _split_link = link.split("?");
						return _split_link[0]+ latlng+"?"+_split_link[1];
					} else {
						return link + latlng;
					}
				},

				// generic replace helper
				replaceLatLng: function(link, lat1, lat2, lng1, lng2, zoom) {
					var sw = new GLatLng(lat1,lng1);
					var ne = new GLatLng(lat2,lng2);
					var latlng = "/" + sw.toUrlValue() + "/" + ne.toUrlValue() + "/" + zoom;
					if (link.search(/\?/)!=-1) {
						var _split_link = link.split("?");
						return _split_link[0]+"/m"+ latlng+"?"+_split_link[1];
					} else {
						return link +"/m"+ latlng;
					}
				},

				// ad detail data, basic, serverside
				itemData: {},

				// drag zoom styles (remember: never use label based texts in this plugin!)
				dragZoomOpts: {},
				
				// google map setup
				initGMap: function() {
					// customize map appearance (controls)
					var mUI = _gmap.getDefaultUI();
					mUI.maptypes.hybrid = false;
					mUI.controls.overviewmapcontrol = true;
					mUI.zoom.scrollwheel = false;
					_gmap.setUI(mUI);

					// custom control: dragzoom v1.2/3 (http://gmaps-utility-library-dev.googlecode.com/svn/tags/dragzoom/1.3/)
					_gmap.addControl(
						new DragZoomControl({}, HCH.result.util.gmap.dragZoomOpts, {}),
						new GControlPosition(G_ANCHOR_TOP_LEFT,new GSize(74,5))
					);

					// initial centering and zoom lvl
					var sw = new GLatLng(HCH.result.util.gmap.lat1,HCH.result.util.gmap.lng1);
					var ne = new GLatLng(HCH.result.util.gmap.lat2,HCH.result.util.gmap.lng2);
					var bounds = new GLatLngBounds(sw,ne);
					var zoom = _gmap.getBoundsZoomLevel(bounds);
					var center = bounds.getCenter();
					_gmap.setCenter(center);
					_gmap.setZoom(zoom);

					// GEvent: when zoom is being changed - reset overlays
					GEvent.addListener(_gmap, "zoomend", function() {
						HCH.result.util.gmap.resetMapState();
					});

					// GEvent: when map interaction stops, update results (moveend is also triggered after other interactions)
					GEvent.addListener(_gmap, "moveend", function() {
						if (HCH.result.util.gmap.bubbleActive) 
						{
							return;
						} 
						else 
						{
							// check if tiles shown on the map changed since last move
							var currentTileCoordinate = HCH.result.util.gmap.getUpperLeftTileCoordinates();
							if (currentTileCoordinate[0] != HCH.result.util.gmap.upperLeftTileCoordinate[0] || currentTileCoordinate[1] != HCH.result.util.gmap.upperLeftTileCoordinate[1])
							{
								
								HCH.result.util.gmap.indicateBusy("#ct_res_full_map_busy");
								HCH.result.util.gmap.resetMapState();
								
								performMapSearch(_gmap.getBounds().getSouthWest().lat(), _gmap.getBounds().getNorthEast().lat(), _gmap.getBounds().getSouthWest().lng(), _gmap.getBounds().getNorthEast().lng(), _gmap.getZoom());
								
								// set current upper left tile coordinate for next check
								HCH.result.util.gmap.setUpperLeftTileCoordinates();

								if (HCH.result.util.gmap.blnIsDistance)
								{
									HCH.result.util.gmap.addDistanceAreaOverlay();
								}
							}
						}
					});

					// opening infowindow: update vars
					GEvent.addListener(_gmap, "infowindowopen", function() {
						HCH.result.util.gmap.bubbleActive = true;
						// remove thumbnail for lvl2 ads
						if (jQuery("#r_m_flyout .r_i.l2").length > 0) {
							var _ct = jQuery("#r_m_flyout");
							jQuery(".r_i_img",_ct).remove();
							jQuery(".r_i_c",_ct).css("marginLeft",0);
						}
					});

					// closing infowindow: update vars
					GEvent.addListener(_gmap, "infowindowclose", function() {
						HCH.result.util.gmap.bubbleActive = false;
					});

					// set upper left tile coordinates
					HCH.result.util.gmap.setUpperLeftTileCoordinates();

					// do initial search
					performMapSearch(_gmap.getBounds().getSouthWest().lat(), _gmap.getBounds().getNorthEast().lat(), _gmap.getBounds().getSouthWest().lng(), _gmap.getBounds().getNorthEast().lng(), _gmap.getZoom());

					// process initial results
					HCH.result.util.gmap.showResultMarker(true);					
				},

				distanceOverlay: null,
			
				//getDistanceKMLUrl: function() {
				//},
				
				// google map setup for distance area
				initDistanceArea: function() {
				}
			},
			
			// toggle more link in facets (expand/collapse)
			toggleMoreFacet: function(el) {
				var _e = jQuery(el);
				var _t = _e.siblings(".sm");
				_t.each(function(i,e) {
					jQuery(e).toggleClass("opn");
				});
				_e.toggleClass("dn");
				_e.siblings(".coll,.exp").toggleClass("dn");
			},

			// emphasize range filter button
			emphButton: function(relatedInput) {
				var _range = jQuery(relatedInput).parents(".range");
				var _btnRange = jQuery(_range).find(".btnRange");
				if (!_btnRange.hasClass("emphasized")) {
					_btnRange.addClass("emphasized");
				}
			}
		}
	},
	detail: {
		// DETAIL SPECIFIC
		//================
		util: {
			// jump to tab: environment
			showDetailMap: function(){
				jQuery("#ct_det_tabholder").tabs("select", HCH.util._env_map.tabEnvIndex);
			},

			// distance toggles
			toggleDistancePoi: function(catname) {
				HCH.gmap.searchPoiMarkers(catname);
				var _cbs = jQuery("#ct_det_poi input:radio");
				for (var _i = 0; _i < _cbs.length; _i++) {
					if (jQuery(_cbs[_i]).val() == catname) {
						_cbs[_i].checked = true;
						break;
					}
				}
				HCH.detail.util.showDetailMap();
			},

			// route search
			initRouteSearch: function(btn,inp) {
				var _b = jQuery(btn);// target button to trigger GDirections load
				var _i = jQuery(inp);// target input field with value string to pass on
				var _c = HCH.util.getCookie('routesearch') != null ? HCH.util.getCookie('routesearch') : '';// get cookie: last entered routesearch

				if ((_b.length > 0) && (_i.length > 0)) {
					// prefill with cookie value
					if (_c.length > 0) {
						_i.val(_c);
					}
					// clickhandler
					_b.click(function() {
						var _tAddr = _i.val();
						var _url = 'http://maps.google.ch/maps?f=d&source=s_d&daddr=' + _tAddr + '&saddr=' + HCH.util._env_map.rAddr + '&dirflg=d';
						var _d = new Date('Jan 01 2020');// expiry date
						// save last entered string in cookie
						HCH.util.setCookie('routesearch',_tAddr,_d,'/');// path set to root

						// prepare the windows options: 
						var sOptions;
						sOptions = 'location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,toolbar=no';
						sOptions = sOptions + ',width=800';// + (screen.availWidth - 10).toString();
						sOptions = sOptions + ',height=600';// + (screen.availHeight - 122).toString();
						sOptions = sOptions + ',screenX=0,screenY=0,left=0,top=0';

						// show url with params in new window
						window.open(_url,'route',sOptions);
						return false;
					});
				}
			}
		}
	},
	myhome: {
		// MYHOME SPECIFIC
		//================
		// stored base values for comparison
		base: {},

		// alert messages
		alert: {},

		// generate graphical bar: iterate over
		/* arrG[0: lefttoright (boolean),
				1: replacemode (boolean),
				2: container width (int),
				3: bar width (int),
				4: bar color (string),
				5: jquery selector to append to (string)]
		*/
		graph: function(arrG) {
			// defaults
			var _ct_h = 10;// container height
			var _ct_bgc = '#d2d6d8';// container bgcolor
			var _h = 10;// bar height

			// html concatenation for each el
			for (var i = 0; i < arrG.length; i++) {
//console.debug("drawing "+arrG[i][5]+" width:"+arrG[i][3]);
				var _s = "";
				if (isFinite(arrG[i][3])) {
					if (arrG[i][0]) {// visible bar from left to right or inverse
						_s += '<div style=\"width:' + arrG[i][2] + 'px; height:' + _ct_h + 'px; background-color:' + _ct_bgc + ';\">';
						_s += 	'<div style=\"width:' + arrG[i][3] + '%; height:' + _h + 'px; background-color:' + arrG[i][4] + ';\"></div>';
						_s += '</div>';
					} else {
						_s += '<div style=\"width:' + arrG[i][2] + 'px; height:' + _ct_h + 'px; background-color:' + arrG[i][4] + ';\">';
						_s += 	'<div style=\"width:' + (100 - arrG[i][3]) + '%; height:' + _h + 'px; background-color:' + _ct_bgc + ';\"></div>';
						_s += '</div>';
					}
					if (arrG[i][1]) {// replace mode (used when comparison is triggered)
						jQuery(arrG[i][5]).empty().append(_s);
					} else {// append mode (page load)
						jQuery(arrG[i][5]).append(_s);
					}
				} else {
//console.log("empty data for "+arrG[i]);
				}
			}
		},

		// When a numerical value is 0, the method returns '-', 
		// otherwise it returns the value with 1 decimal.
		zeroOrFixed: function(n) {
			if (n == 0) {
				return '-';
			}
			return n.toFixed(1);
		},
		
		// Same as above, but formats nicely for currency values
		zeroOrFixedMoney: function (amount, currencySymbol, delimiter, decimalPlaces)
		{
			if (amount == 0)
			{
				return '-';
			}
			// setup some default values
			if (decimalPlaces == null || decimalPlaces == undefined) 
			{ 
				decimalPlaces = 0; 
			}

			//check that the value can be recognised as an Floating point number
			try 
			{
				amount = parseFloat(amount);
				amount = amount.toFixed(decimalPlaces);
			}
			catch (e) 
			{
				throw ('localeNumberFormat caused INVALID FLOAT with value ' + amount);
			}

			if (delimiter == null || delimiter == undefined) 
			{ 
				delimiter = ','; 
			}
			
			// convert to string
			if (amount.match != 'function') 
			{
				amount = amount.toString(); 
			}

			// validate as numeric
			var regIsNumeric = /[^\d,\.-]+/igm;
			var results = amount.match(regIsNumeric);

			if (results != null) 
			{
				outputText('INVALID NUMBER', eOutput);
				return null;
			}

			// setup some variables for delimiting the strings with commas
			var minus = amount.indexOf('-') >= 0 ? '-' : '';
			amount = amount.replace('-', '');
			//alert(amount);

			var amtLen = amount.length;
			var decPoint = amount.indexOf('.');
			var wholeNumberEnd = decPoint > 0 ? amtLen - (amtLen - decPoint) : amtLen;

			var wholeNumber = amount.substr(0, wholeNumberEnd);
			var fraction = amount.substr(wholeNumberEnd, amtLen - wholeNumberEnd);

			//var segments = (wholeNumberEnd - (wholeNumberEnd % 3)) / 3;
			var rvsNumber = wholeNumber.split('').reverse().join('');
			var output = '';

			for (var i = 0; i < wholeNumberEnd; i++) 
			{
				if (i % 3 == 0 && i != 0 && i != wholeNumberEnd) 
				{ 
					output += delimiter; 
				}
				output += rvsNumber.charAt(i);
			}
			output = minus + output.split('').reverse().join('') + fraction +" "+currencySymbol;
			return output;
		},

		// output numerical values for compare target: iterate over arrV
		/* arrV[0: value (string),
				1: jquery selector to append to (string)]
		*/
		num: function(arrV) {
			for (var i = 0; i < arrV.length; i++) {
				jQuery(arrV[i][1]).empty().append(arrV[i][0]);
			}
		},

		// autocomplete helper for city comparison (sociodemo data)
		autocompleteSilent: {
			timeout: 10000,
			delay: 100,
			scrollHeight: 230,
			build: function(form, input, button, url, parameters) {
				var field = jQuery(input);
				field.autocomplete(url, {
					cacheLength: 20,
					delay: HCH.myhome.autocompleteSilent.delay,
					extraParams: parameters,
					highlight: false,
					matchSubset: false,
					scrollHeight: HCH.myhome.autocompleteSilent.scrollHeight,
					timeout: HCH.myhome.autocompleteSilent.timeout,
					selectFirst: false,
					formatItem: function(row) {
						return row[0].split("\t")[1];
					},
					formatResult: function(row) {
						return row[0].split("\t")[0];
					}
				}).result(function(event, data, formatted) {
//console.debug(data);
					// use btn action instead of submit
					HCH.myhome.compareCity();
				});
			}
		},

		// process city comparison form
		compareCity: function() {
			var _t = jQuery("#inp_compare").val();// target city to compare
			// poll data: call a4j jsfunction, see parts/searchbox_citycompare.xhtml
			loadCityData(_t);
		},

		// callback from comparison form submit
		loadCompareData: function(data) {
//console.log(data);
			if (data) {
				// show same city alert for identical submit
				// currently only works in german because the myhome core is not based on a translated location string
				if (data.city.toLowerCase() == HCH.myhome.base.city.toLowerCase()) {
					jQuery("#inp_compare").val('');// empty input
					alert(HCH.myhome.alert.sameCity);
				} else {
					//var _percPrec = 1;
					//var _notDef = "#{i18n['ambition.sociodemo.notDefined']}";

					// graphs: family comp
					HCH.myhome.graph([[true,true,200,data.household1Pers.toFixed(1),'#c1022c','.g_t_household1Pers'],[true,true,200,data.household2Pers.toFixed(1),'#c1022c','.g_t_household2Pers'],[true,true,200,data.household3Pers.toFixed(1),'#c1022c','.g_t_household3Pers'],[true,true,200,data.householdMorePers.toFixed(1),'#c1022c','.g_t_householdMorePers']]);
					// numerical
					HCH.myhome.num([[HCH.myhome.zeroOrFixed(data.household1Pers) + '%','.n_t_household1Pers'],[HCH.myhome.zeroOrFixed(data.household2Pers) + '%','.n_t_household2Pers'],[HCH.myhome.zeroOrFixed(data.household3Pers) + '%','.n_t_household3Pers'],[HCH.myhome.zeroOrFixed(data.householdMorePers) + '%','.n_t_householdMorePers']]);

					// graphs: nationality
					HCH.myhome.graph([[true,true,200,data.swiss.toFixed(1),'#c1022c','.g_t_swiss'],[true,true,200,data.europeans.toFixed(1),'#c1022c','.g_t_europeans'],[true,true,200,data.eastEuropeans.toFixed(1),'#c1022c','.g_t_eastEuropeans'],[true,true,200,data.international.toFixed(1),'#c1022c','.g_t_international']]);
					// numerical
					HCH.myhome.num([[HCH.myhome.zeroOrFixed(data.swiss) + '%','.n_t_swiss'],[HCH.myhome.zeroOrFixed(data.europeans) + '%','.n_t_europeans'],[HCH.myhome.zeroOrFixed(data.eastEuropeans) + '%','.n_t_eastEuropeans'],[HCH.myhome.zeroOrFixed(data.international) + '%','.n_t_international']]);

					// graphs: communalTaxRate
					// first determine bigger value of both, set bigger one to 100% bar and calculate other respectively
					var _absCommunalTaxRate = parseFloat(data.communalTaxRate.toFixed(1));
					if (HCH.myhome.base.communalTaxRate > _absCommunalTaxRate) {
						var _relBaseCommunalTaxRate = (100/HCH.myhome.base.communalTaxRate) * _absCommunalTaxRate;
						HCH.myhome.graph([[true,true,200,100,'#47728f','.g_b_communalTaxRate']]);
						HCH.myhome.graph([[true,true,200,_relBaseCommunalTaxRate,'#c1022c','.g_t_communalTaxRate']]);
					} else {
						var _relTargetCommunalTaxRate = (100/_absCommunalTaxRate) * HCH.myhome.base.communalTaxRate;
						HCH.myhome.graph([[true,true,200,_relTargetCommunalTaxRate,'#47728f','.g_b_communalTaxRate']]);
						HCH.myhome.graph([[true,true,200,100,'#c1022c','.g_t_communalTaxRate']]);
					}
					// numerical: tax
					HCH.myhome.num([[data.communalTaxRate.toFixed(1) + '%','.n_t_communalTaxRate']]);
					// show warning if communaltaxrates from different cantons
					if (HCH.myhome.base.canton != data.canton) {
						jQuery("#warnSocioTaxComparison").show();
					} else {
						jQuery("#warnSocioTaxComparison").hide();
					}

					// graphs: income
					// first determine bigger value of both, set bigger one to 100% bar and calculate other respectively
					var _absReferenceIncome = parseFloat(data.referenceIncome.toFixed(1));
					if (HCH.myhome.base.referenceIncome > _absReferenceIncome) {
						var _relBaseReferenceIncome = (100/HCH.myhome.base.referenceIncome) * _absReferenceIncome;
						HCH.myhome.graph([[true,true,200,100,'#47728f','.g_b_referenceIncome']]);
						HCH.myhome.graph([[true,true,200,_relBaseReferenceIncome,'#c1022c','.g_t_referenceIncome']]);
					} else {
						var _relTargetReferenceIncome = (100/_absReferenceIncome) * HCH.myhome.base.referenceIncome;
						HCH.myhome.graph([[true,true,200,_relTargetReferenceIncome,'#47728f','.g_b_referenceIncome']]);
						HCH.myhome.graph([[true,true,200,100,'#c1022c','.g_t_referenceIncome']]);
					}
					// numerical: income
					HCH.myhome.num([[HCH.myhome.zeroOrFixedMoney(data.referenceIncome, 'CHF', '\'', 0),'.n_t_referenceIncome']]);

					// graphs: age
						// male
						HCH.myhome.graph([[true,true,225,data.age6500m.toFixed(1),'#c1022c','.g_t_age6500m'],[true,true,225,data.age4064m.toFixed(1),'#c1022c','.g_t_age4064m'],[true,true,225,data.age1539m.toFixed(1),'#c1022c','.g_t_age1539m'],[true,true,225,data.age0014m.toFixed(1),'#c1022c','.g_t_age0014m']]);
						// female
						HCH.myhome.graph([[false,true,225,data.age6500f.toFixed(1),'#c1022c','.g_t_age6500f'],[false,true,225,data.age4064f.toFixed(1),'#c1022c','.g_t_age4064f'],[false,true,225,data.age1539f.toFixed(1),'#c1022c','.g_t_age1539f'],[false,true,225,data.age0014f.toFixed(1),'#c1022c','.g_t_age0014f']]);
					// numerical
						// male
						HCH.myhome.num([[HCH.myhome.zeroOrFixed(data.age6500m) + '%','.n_t_age6500m'],[HCH.myhome.zeroOrFixed(data.age4064m) + '%','.n_t_age4064m'],[HCH.myhome.zeroOrFixed(data.age1539m) + '%','.n_t_age1539m'],[HCH.myhome.zeroOrFixed(data.age0014m) + '%','.n_t_age0014m']]);
						// female
						HCH.myhome.num([[HCH.myhome.zeroOrFixed(data.age6500f) + '%','.n_t_age6500f'],[HCH.myhome.zeroOrFixed(data.age4064f) + '%','.n_t_age4064f'],[HCH.myhome.zeroOrFixed(data.age1539f) + '%','.n_t_age1539f'],[HCH.myhome.zeroOrFixed(data.age0014f) + '%','.n_t_age0014f']]);
				}
			} else {// display invalid city message
				jQuery("#inp_compare").val('');// empty input
				alert(HCH.myhome.alert.invalidCity);
			}
		}
	},
	content: function() {},
	offer: function() {},
	util: {
		// language switch on all pages
		langswitch: function(container, evt) {
			var _c = jQuery(container); //'parent' link
			var _t = jQuery(evt.target); //event target
			var _a = _c.find(".act"); //active element (link/trigger)
			var _p = _c.find(".pas"); //passive element (flyout)
			var _al = _a.text(); //active language string
			var _cl = _t.text(); //clicked element's content (language string to change to)
			var _blnvis = _p.css("display") == "inline" ? true : false; //toggle state (flyout visible?)
			if (_t.hasClass("act") || _t.hasClass("switch_lang")) {
				//toggle flyout
				HCH.util.toggleswitch(_c, _a, _p, _blnvis);
			} else {
				//change language (switch act val with clicked val)
				_t.text(_al);
				_a.text(_cl);
				//change title
				var _at = _a.attr("title"); //active element's title (represents redirection url)
				var _ct = _t.attr("title"); //clicked element's title (represents redirection url)
				_a.attr("title", _ct);
				_t.attr("title", _at);
				//close flyout
				HCH.util.toggleswitch(_c, _a, _p, true);
				//do redirect
				location.href = _a.attr("title");
			}
		},

		// language switch helper: manage language elements on langswitch
		toggleswitch: function(elementContainer, elementWithIco, elementToToggle, blnIsVisible) {
			var _ec = jQuery(elementContainer);
			var _ep = jQuery(elementWithIco);
			var _et = jQuery(elementToToggle);
			var _on = blnIsVisible;
			if (_on) {
				_et.hide();
				_ep.css("background-position", "right -162px");
				_ec.removeClass("act");
			} else {
				_et.show();
				_ep.css("background-position", "right -267px");
				_ec.addClass("act");
			}
		},

		// manage helper text in home search boxes
		initDefaultSearchBoxLabel: function(cls, label) {
			jQuery(cls).focus(function() {
				if (jQuery.trim(this.value) == label) {
					this.value = '';
					this.style.color = '#5D6970';
				}
			}).blur(function() {
				if (jQuery.trim(this.value) == '') {
					this.value = label;
					this.style.color = '#CAD5DB';
				}
			}).val(label).css('color', '#CAD5DB');
		},

		// scroll page content (element id) into view
		scrollIntoView: function(elmId,intVeloc) {
			jQuery('html,body').animate({scrollTop: jQuery('#'+elmId).offset().top}, intVeloc);
		},

		// email masking helper
		flipText: function(text) {
			var out = "";
			for (var i = text.length-1; i >= 0; i--) {
				out += text.charAt(i);
			}
			return out;
		},

		// set cookie
		//	name - name of the cookie
		//	value - value of the cookie
		//	[expires] - expiration date of the cookie (defaults to end of current session)
		//	[path] - path for which the cookie is valid (defaults to path of calling document)
		//	[domain] - domain for which the cookie is valid (defaults to domain of calling document)
		//	[secure] - Boolean value indicating if the cookie transmission requires a secure transmission
		//	* an argument defaults when it is assigned null as a placeholder
		//	* a null placeholder is not required for trailing omitted arguments
		setCookie: function(name, value, expires, path, domain, secure) {
			var curCookie = name + "=" + escape(value) + ((expires) ? "; expires=" + expires.toGMTString() : "") + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : "");
			document.cookie = curCookie;
		},

		// get cookie
		//	name - name of the desired cookie
		//	* return string containing value of specified cookie or null if cookie does not exist
		getCookie: function(name) {
			var dc = document.cookie;
			var prefix = name + "=";
			var begin = dc.indexOf("; " + prefix);
			if (begin == -1) {
				begin = dc.indexOf(prefix);
				if (begin != 0) {
					return null;
				}
			} else {
				begin += 2;
			}
			var end = document.cookie.indexOf(";", begin);
			if (end == -1) {
				end = dc.length;
			}
			return unescape(dc.substring(begin + prefix.length, end));
		},

		// delete cookie
		//	name - name of the cookie
		//	[path] - path of the cookie (must be same as path used to create cookie)
		//	[domain] - domain of the cookie (must be same as domain used to create cookie)
		//	* path and domain default if assigned null or omitted if no explicit argument proceeds
		deleteCookie: function(name, path, domain) {
			if (getCookie(name)) {
				document.cookie = name + "=" + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
			}
		},
		
		trackingNetMetrix: function(urlContext) {
			// reload NetMetrix tracking
			jQuery("#trackingNetMetrix").attr('src', urlContext +'/tracking_netmetrix?'+(Math.random()*100000));
		}
	},

	gmap: {
		// MAP SPECIFIC
		//================
		// error handling XHR
		procXHRError: function(XMLHttpRequest, textStatus, errorThrown) {
//console.log("textStatus:"+textStatus);
//console.log("errorThrown:"+errorThrown);
		},

		// overlay category variables
		buildingPermits: "buildingPermits",
		activeCategory: null,

		// init and clickhandler for overlay categories
		setupPoiRadios: function() {
			var cbs = jQuery("#" + HCH.util._env_map.divNamePois + " input:radio");
			jQuery(cbs).click(function() {
				hidePoi();
				var _v = jQuery(this).attr("value");
				if (this.checked) {
					HCH.gmap.searchPoiMarkers(_v);
				} else {
					HCH.gmap.hidePoiMarkers(_v);
				}
			});
			// show building permits by default
			HCH.gmap.searchPoiMarkers(HCH.gmap.buildingPermits);
			cbs[0].checked = true;
		},

		// overlay toggle
		searchPoiMarkers: function(category) {
			if (HCH.gmap.activeCategory && HCH.gmap.activeCategory != category) {
				HCH.gmap.hidePoiMarkers(HCH.gmap.activeCategory);
			}
			// check if a kml is available then load it, else search for category and generate from there
			var kmlURL = (category == HCH.gmap.buildingPermits ? HCH.util._env_map.buildingPermitsKML : HCH.gmap.createCategoryKMLUrl(category) );
			if (HCH.util._env_map.geoXMLs[category] == undefined) {
				HCH.gmap.generateKMLOverlay(category, kmlURL);
			}
			_gmap.addOverlay(HCH.util._env_map.geoXMLs[category]["geoXML"]);
			HCH.gmap.activeCategory = category;
		},

		// reset overlay
		hidePoiMarkers: function(category) {
			_gmap.removeOverlay(HCH.util._env_map.geoXMLs[category]["geoXML"]);
			HCH.gmap.activeCategory = null;
		},

		// poi layering helper
		increasePoiZindex: function(marker) {
			return GOverlay.getZIndex(marker.getPoint().lat()) + marker.importance*1000000;
		},

		// kml helper
		createBuildingPermitsKMLUrl: function(gPoint) {
		},
		createCategoryKMLUrl: function(category) {
		},
		generateKMLOverlay: function(category, kmlURL) {//poi overlays
			HCH.util._env_map.geoXMLs[category] = new Object();
			HCH.util._env_map.geoXMLs[category]["geoXML"] = new GGeoXml("" + kmlURL);
		},
		centerGMapToAddress: function(center) {
			if (center){
				_gmap.setCenter(center, 13);
				HCH.util._env_map.buildingPermitsKML = HCH.gmap.createBuildingPermitsKMLUrl(center);
				HCH.gmap.setupPoiRadios();
				HCH.util._env_map.lat = center.lat();
				HCH.util._env_map.lng = center.lng();
			} else {
				// center map to the middle of switzerland
				_gmap.setCenter(new GPoint(46.890787, 8.26118), 13);
				HCH.util._env_map.lat = 46.890787;
				HCH.util._env_map.lng = 8.26118;
			}
		},

		// streetview part just for detail.xhtml
		// TODO: documentation!
		checkStreetViewSupported: function() {
			var gstClient = new GStreetviewClient();
			var svLocation = new GLatLng(HCH.util._env_map.lat, HCH.util._env_map.lng);
			gstClient.getNearestPanoramaLatLng(svLocation, HCH.gmap.handleStreetViewNotSupported);
		},
		initializeStreetView: function(svLocation) {
			panoramaOptions = { latlng: svLocation };
			myPano = new GStreetviewPanorama(document.getElementById("pano"), panoramaOptions);
			GEvent.addListener(myPano, "error", HCH.gmap.handleNoFlash);
		},
		handleStreetViewNotSupported: function(latlng) {
			var _info = jQuery("#ct_det_staticmap").find(".gsv");
			var _btn = jQuery("#btnSV");
			if (latlng != null) {
				HCH.gmap.initializeStreetView(latlng);
				_info.show();
				_btn.show();
			} else {
				_info.hide();
				_btn.hide();
			}
		},
		handleNoFlash: function(errorCode) {
			if (errorCode == 603) {//http://code.google.com/apis/maps/documentation/reference.html#GStreetviewPanorama.ErrorValues
				// no flash supported => hide trigger element
				var _btn = jQuery("#btnSV");
				_btn.hide();
				return;
			}
		},
		toggleStreetViewMap: function() {
			var _gsv = jQuery("#pano");
			var _map = jQuery("#gmap");
			var _btn = jQuery("#btnSV");
			var _blnSvAct = (_gsv.css("display") == 'block' ? true : false);
			if (_blnSvAct) {
				_gsv.hide();
				_map.show();
				_btn.val(HCH.util._env_map.toStreetView);
				_btn.removeClass("smap");
				//point and map 'repush'
				var _point = new GLatLng(HCH.util._env_map.lat, HCH.util._env_map.lng);
				_gmap.checkResize();
				_gmap.setCenter(_point, 15);
			} else {
				_map.hide();
				_gsv.show();
				_btn.val(HCH.util._env_map.toMap);
				_btn.addClass("smap");
			}
		},

		// add fav overlay
		overlayFavs: function(favs) {
			_f = favs;
			if (_f.length > 0) {
				for (var i = 0; i < _f.length; i++) {
					// custom GMarker helper
					_p = new GLatLng(_f[i][0],_f[i][1]);
					_ico = new GIcon;
					_ico.image = _f[i][2];
					_ico.iconSize = new GSize(32, 32);
					_ico.iconAnchor = new GPoint(16, 29);
					_poi = new GMarker(_p, {icon:_ico, zIndexProcess:HCH.gmap.increasePoiZindex});
					_poi.importance = 2;
					_gmap.addOverlay(_poi);
				}
			}
		},

		// parse favorites
		procFavs: function(url) {
			jQuery.ajax({
				type: "GET",
				url: url,
				dataType: "xml",
				error: HCH.gmap.procXHRError,
				success: function(data,textStatus,XMLHttpRequest) {
					// parse kml: extract coords
					var _coords = jQuery(data).find("coordinates");
					var _tmp = [];
					jQuery(_coords).each(function() {
						var _x = jQuery(this).text();
						var _x2 = _x.split(",");
						_tmp.push([_x2[1],_x2[0]]);
					});

					// parse kml: extract icon href
					var _favIcons = jQuery(data).find("href");
					var _tmp2 = [];
					jQuery(_favIcons).each(function() {
						_tmp2.push(jQuery(this).text());
					});

					// finalize favMarkers array [lat,lng,icohref]
					jQuery(_tmp).each(function(i,e) {
						HCH.util._env_map.favMarkers.push([_tmp[i][0],_tmp[i][1],_tmp2[i]]);
					});
				},
				complete: function() {
					HCH.gmap.overlayFavs(HCH.util._env_map.favMarkers);
				}
			});
		},

		// map setup
		initGMapMyHome: function(lat, lng) {
			_gmap.addControl(new GSmallMapControl());
			_gmap.addControl(new GMapTypeControl());
			HCH.gmap.centerGMapToAddress(new GLatLng(lat,lng)); // set center calculated from microGIS data
			HCH.gmap.procFavs(HCH.util._env_map.favoritsKML);// retrieve favorites
		}
	},

	// autocomplete configuration for header searchboxes
	autocomplete: {/* TODO: investigate bug width ignored and always read from associated input field */
		timeout: 10000,
		delay: 100,
		scrollHeight: 230,
		minChars:1,
		build: function(form, input, button, url, parameters) {
			var field = jQuery(input);
			field.autocomplete(url, {
				cacheLength: 20,
				minChars:HCH.autocomplete.minChars,
				delay: HCH.autocomplete.delay,
				extraParams: parameters,
				highlight: false,
				matchSubset: false,
				scrollHeight: HCH.autocomplete.scrollHeight,
				timeout: HCH.autocomplete.timeout,
				selectFirst: false,
				formatItem: function(row) {
					return row[0].split("\t")[1];
				},
				formatResult: function(row) {
					return row[0].split("\t")[0];
				}
			}).result(function(event, data, formatted) {
				jQuery(form).submit();
			});
		}
	}
};

