/**
 * @name	CeL map function
 * @fileoverview
 * 本檔案包含了 map 的 functions。
 * @since	
 */
'use strict';
if (typeof CeL === 'function')
CeL.run(
{
name:'interact.integrate.map',
code : function(library_namespace) {
/**
 * null module constructor
 * @class	map 的 functions
 */
var _// JSDT:_module_
= function() {
	//	null module constructor
};
/**
 * for JSDT: 有 prototype 才會將之當作 Class
 */
_// JSDT:_module_
.prototype = {
};
//	init function
var SL=new Debug.log,sl=function(){SL.log.apply(SL,arguments);},error=function(){SL.error.apply(SL,arguments);},warn=function(){SL.warn.apply(SL,arguments);};
var gMap,mapO,mData,lostItem,gLocal,dLoc={tw:[23.7,121]};	//	台灣: 23.7,121
addLoad(function(){
 var b=SL.setBoard('log');
 if(window.location.protocol=='file:'&&b)b.style.display='block';	//	強制顯示 log
 if(init&&init.run)sl('Page loaded. Prepare to initial..');
 if(typeof GLatLng=='undefined'){sl('GMap does not loaded.');return;}
 for(var i in dLoc)
  dLoc[i]=new GLatLng(dLoc[i][0],dLoc[i][1]);
 setTimeout('init(0);',0);
});
init.run=1;
function init(i){
 if(!arguments.callee.run)return;
 var m=0,n;
 switch(i){
  case m++:
   setSize();
   if(typeof preLoadMap=='function')preLoadMap();
   break;
  case m++:
   catchFile.sn='map-files';
   catchFile.f=function(url,success,captureId){
	sl('Capture '+(success?'succeeded':'failed')+': '+url+'');
   };
   catchFile([
	'map.js',
	'map.css'
   ]);
   break;
  case m++:
   initMap();
   initSearch();
   if(window.location.protocol=='file:')setTimeout('mapO.removeTM();',3000);	//	3000: 適当。隨 client 而有不同。
   break;
  case m++:
   readLoc();
   break;
  case m++:
   loadMapData();
   break;
  case m++:
   placeMapItem();
   break;
  case m++:
   if(typeof additionalFunc=='function')additionalFunc();
   break;
 }
 m=['Starting initial process. Catch files..','Catch done. Initial all components..','Map loaded. Loading address records..','address loaded. Loading map data..','map data loaded. placing map items..','placing done. Do additional works..','Initial done.'];
 sl('init: '+m[i]);
 if(arguments.callee.run && ++i')+'
'+r.address);
   //	http://code.google.com/apis/ajaxsearch/documentation/reference.html#_class_GlocalResult
   var h='
'+r.title
	+''+r.address+'
'+r.phone.join('
')+(r.phone.length?'
':'')/*+r.listingType+'
'*/+r.content+'
('+r.lat+','+r.lng+') 
Use Google Maps ';
   if(sA2.c)sA2.c.innerHTML+=h;else sl(h);
  },'Local');
  sl('initSearch: local search initialed.');
 }});
 else sl('initSearch: Cannot initial local search. Please load API.');
}
var _map_tmp_message;
initMap.flag={backgroundColor:'#DDE'};
function initMap(){
 var a,m,i,_f=arguments.callee;
 mapO=new gMap('map_canvas',dLoc.tw,_f.flag);
 //if(!mapO)return 1;
 //mapO.geocoder.setBaseCountryCode('TW');
 sl('initMap: set geocoder country code: '+mapO.geocoder.getBaseCountryCode());
 //	要先 show 才能得到 getOverviewMap()
 if(m=mapO.overviewMap)
  //	IE7 上 .hide() 時 .show() 會出錯
  //	2008/9/6 22:37:33	IE6 也會出錯了
  if(navigator.userAgent.indexOf('MSIE')==-1)
   m.show(),setOverviewMap();
 //	small mark template	http://econym.googlepages.com/custom.htm	http://mapki.com/wiki/Available_Images	http://econym.googlepages.com/geicons.htm	http://code.google.com/apis/maps/documentation/overlays.html#Icons_overview
 //	iconSize 的處理還是有問題。
 mapO.icon(_f.iconOption||{
	shadow:'http://labs.google.com/ridefinder/images/mm_20_shadow.png',
	iconSize:new GSize(12,20),
	shadowSize:new GSize(22,20),
	iconAnchor:new GPoint(6,20),
	infoWindowAnchor:new GPoint(5,1)
 },1);
 mapO.icon(_f.iconArray||[
	{image:'http://labs.google.com/ridefinder/images/mm_20_green.png'},//http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png//{shadow:'http://maps.google.com/mapfiles/kml/pal5/icon14s.png',image:'http://maps.google.com/mapfiles/kml/pal5/icon14.png'},//
	{image:'http://labs.google.com/ridefinder/images/mm_20_yellow.png'},
	{image:'http://labs.google.com/ridefinder/images/mm_20_green.png'},//{icon:G_DEFAULT_ICON},
	{image:'http://labs.google.com/ridefinder/images/mm_20_orange.png'},//'http://maps.google.com/mapfiles/arrow.png',
	''
 ]);
 mapO.runAfterAdd=function(o){getO.add(o.address,o.name);showML.sel(o);showML();};
 mapO.runOnClick=function(o){showML.sel(o);showML();};
 mapO.runAfterRemove=function(o){if(showML.sel()==o)showML.sel(null,1);showML();};
 mapO.notFound=function(a,d){sl('沒找到 ['+a+'] '+d.name+'');return false;};
 //	在 unload 的時候呼叫 GUnload 以避免瀏覽器 memory leak。
 addListener(0,'unload',function(){try{GUnload();}catch(e){}});
 a=function(htm,t,js,ico){
  return '+')
 '+htm+'
 ';
 };
 if(m=mapO.map)
  //	use google's message
  i=function(i){try{
	eval('_map_tmp_message=p('+i+');',m);
	var a=_map_tmp_message;
	//sl('setContextMenu '+i+': '+a);
	return a&&a.length<8?a:'';
  }catch(e){}},
  mapO.setContextMenu([
	a(i(10985)||'Zoom in','將地圖於此放大','mapO.showContextMenu(0),mapO.map.zoomIn(mapO.clickLatLng,true);','http://www.google.com/mapfiles/zoom-plus.png')
	,a(i(10986)||'Zoom out','將地圖於此縮小','mapO.showContextMenu(0),mapO.map.zoomOut(mapO.clickLatLng,true);','http://www.google.com/mapfiles/zoom-minus.png')
	,a(/*i(11047)||*/'Set Center','將地圖於此置中','mapO.showContextMenu(0),mapO.setCenter(mapO.clickLatLng);','http://www.google.com/mapfiles/center.png')
	,'
'
	,a('Search near','搜尋附近','mapO.showContextMenu(0),showNeighbor(mapO.clickLatLng);','http://maps.google.com/mapfiles/kml/pal2/icon13.png')
  ].join('')),
  GEvent.addListener(m,"click",function(){
   mapO.showContextMenu(0);
  }),GEvent.addListener(m,"dragstart",function(){
   mapO.showContextMenu(0);
  });
}
function readLoc(){
 if(loadMapData.dataF)catchFile([loadMapData.dataF,mapO.locFP=loadMapData.dataF+'.adr.csv']);
 mapO.readLoc();
}
//loadMapData.baseD='';
//	預設可使用之模板
loadMapData.getHTM=function(d,type){
 var l=mData[d.name||d.address],a=[mapO.getPoint(d,type)],r=[];
 if(d.address||'')a.unshift(d.address);
 l=l?l.link:'';
 if(!loadMapData.baseD)loadMapData.baseD='';
 if(d.name)		//	不能用 this.baseD
  r.push(''+(l?''+d.name+'':d.name)+'');
 if(d.dscr)r.push(d.dscr);
 r.push(''+a.join('
')+'
');
 if(typeof d.getLength=='function')r.push('length: '+(d.getLength()/1000).toFixed(3)+'km');
 if(typeof d.getArea=='function')r.push('面積: '+d.getArea().toFixed(3)+'m²');
 //if(showNeighbor.pointer&&d.getLatLng)r.push('距離 '+showNeighbor.pointer.distanceFrom(d.getLatLng()));
 //r.push(,'
search near');
 return r.join('
').replace(/(<\/(div|p)>)\s*
/g,'$1');
};
loadMapData.lessItems=3;
loadMapData.forEach=function(mapData,index){};
/*
loadMapData.zIndexP=function(){
 sl('click '+this.name);
 return -1;
};
*/
function loadMapData(){
 /*	load: 這裡假設 data 中標題可作為id(獨一無二)
	map data: [標題	敘述(description)	link	_data_]
	_data_: search string/kind	additional description/data of different kind of data
		search string/additional description (用括弧框起來的)
		'marker'	lat	lng
		'polyline'	points	levels
		'polygon'	points	levels
	mData[標題||address]={};
 */
 mData={};
 var i=0,m,t,_f=arguments.callee;
 _f.run=1;
 try{t=getU(_f.dataF);}catch(e){sl('Get data file ['+_f.dataF+'] error: '+e.message);}
 if(t)t=parseCSV(t);//t.replace(/\r+/g,'').replace(/\n+$/,'').replace(/^\n+/,'').split('\n');
 else t=[],showML.write('No list got of ['+_f.dataF+'].');
 showML.write('總共 '+t.length+' 筆資料正處理中,請稍候…');
 sl('loadMapData: Found '+t.length+' lines. Parsing.. (stop)');
 for(;i').split('\t')).length>_f.lessItems)
  if(t[i].length>_f.lessItems)
   _f.forEach(t[i],i);
 }
 _f.run=0;
}
placeMapItem.done=function(i){
 //sl('placing done.');
 showML.refresh=1,showML();
 //	workaround 權宜之計: iconSize 的處理還是有問題。
 setTimeout('if(mapO)mapO.iconA[2].image=G_DEFAULT_ICON.image;',500);
};
placeMapItem.step=function(i){
 var _t=this;
 if(_t.run&&i<_t.stepA.length&&(!_t.loadMax||i<_t.loadMax))
  mapO.add(mData[_t.stepA[i++]]),setTimeout('placeMapItem.step('+i+');',0/*i>40?400:i+i*i/4*/);
 else if(_t.done)_t.done(i);
};
placeMapItem.loadMax=80;
function placeMapItem(){
 var _f=arguments.callee,i;
 if(_f.noPlace){	//	一開始不列出點
  if(typeof _f.noPlace=='function')_f.noPlace();
  return;
 }
 lostItem={};
 _f.run=1;
 //showML();
 showML.refresh=0;
 if(_f.step){
  _f.stepA=[];
  for(i in mData)
   lostItem[i]=mData[i],_f.stepA.push(i);//,mapO.add(mData[i]);
  setTimeout('placeMapItem.step(0);',0);
 }else{
  for(i in mData)mapO.add(mData[i]);
  if(_f.done)_f.done();
 }
}
//	interface
//	2008/9/6 15:7:34
//setSize.size=[880,320,240];	//	width, height, menuWidth
setSize.size='95%,70%,25%'.split(',');	//	width, height, menuWidth
setSize.setContainer=function(){
 try{
  this.menuC=(this.menu=document.getElementById('markerList')).parentNode;	//	menuC: menu container
  return this.container=document.getElementById('map_canvas').parentNode;
 }catch(e){}
};
function setSize(){
 var _f=arguments.callee,s=_f.size,_s=s.join('\0').split('\0'),m,a=function(i,k){
	if(!isNaN(s[i]))s[i]+='px';
	if(typeof _s[i]=='string'&&(m=_s[i].match(/^(\d+)%$/)))
	 k=k?'Height':'Width',
	 _s[i]=Math.floor((window.innerHeight?window['inner'+k]:document.documentElement&&document.documentElement.clientHeight?document.documentElement['client'+k]:document.body['offset'+k])*m[1]/100);
 };
/*
 //	from getWinStatus()
 with(document.body.style)width=height='100%';
 sl('setSize: window.inner: '+window.innerWidth+','+window.innerHeight);
 sl('setSize: window.page: '+window.pageXOffset+','+window.pageYOffset);
 sl('setSize: screen: '+screen.width+','+screen.height);
 sl('setSize: document.documentElement.client: '+document.documentElement.clientWidth+','+document.documentElement.clientHeight);
 sl('setSize: document.body.scroll: '+document.body.scrollWidth+','+document.body.scrollHeight);
 sl('setSize: document.body.offset: '+document.body.offsetWidth+','+document.body.offsetHeight);
 sl('setSize: document.body.client: '+document.body.clientWidth+','+document.body.clientHeight);
*/
 a(0);
 a(1,1);
 a(2);
 //sl('setSize: '+_s);
 a=_f.container;
 if(!a&&!(a=_f.setContainer()))return;
 with(a.style)width=s[0],height=s[1];
 with(_f.menuC.style)width=s[2],height=s[1];
 _f.menu.style.height=(_s[1]-_f.menu.offsetTop)+'px';
 //sl('setSize: '+a.offsetWidth+'-'+_f.menuC.offsetWidth+'='+(a.offsetWidth-_f.menuC.offsetWidth));
 //sl('setSize: '+_s[0]+'-'+_s[2]+'='+(_s[0]-_s[2]));
 initMap.flag.size=[
	a.offsetWidth-_f.menuC.offsetWidth-(navigator.userAgent.indexOf('MSIE')==-1?13:1),	//	13: 和 scrollbar 有關嗎??
	(navigator.userAgent.indexOf('MSIE')==-1?_s[1]:_s[1])	//	_s[1] 不能改成 a.offsetHeight
 ];
}
showML.refresh=1;
showML.closeMark='×';
showML.indexA='iA';
showML.selClass='sel';
showML.specialKind='sp';
showML.isSelR=new RegExp('(^|\\s+)'+showML.selClass);
//showML.selO=null;
showML.sel=function(o,removed){
 var _t=this;
 if(typeof o!='undefined'){
  //	GMarker.setImage(src)
  if(!removed&&_t.selO&&_t.selO.setImage)
   try{_t.selO.setImage(mapO.icon().image);}catch(e){}	//	用 try 是因為有時被刪了可是卻還是在(動作太快?),這時要 setImage 會出錯。
  _t.selO=o;
  if(o&&o.setImage)o.setImage(mapO.icon(showSP.selectedI).image);
 }
 return _t.selO;
};
showML.getName=function(o){
 var name=o.parentNode.attributes.getNamedItem(this.indexA),type;
 if(name&&(name=name.nodeValue)&&(type=name.match(/^([a-z]+),(.+)$/i))){
  //sl('showML.getName: ['+type[1]+'] '+type[2]+'('+getO.alias(type[2])+','+mapO.getO(type[1],getO.alias(type[2]))+')');
  //name=,type=type[1];
  return [getO.alias(type[2]),type[1]];//[name,type];
 }
};
showML.write=function(t){
 try{document.getElementById('markerList').innerHTML=t;}catch(e){}
};
function showML(o){
 if(!mapO)return;	//	尚未 initial?
 var _f=arguments.callee;
 if(o){
  var name,type;
  if(type=_f.getName(o)){
   name=type[0],type=type[1];
   if(o.className=='closeMark')
    mapO.remove(name,type);
   else{
    showML.sel(mapO.getO(type,name));//.setImage(mapO.icon(2).image);
    mapO.show(name,type);
    o=o.parentNode;
    for(var i=0,LI=library_namespace.get_tag_list('li', o.parentNode.parentNode);i'],a,i,j,id,OK={};
 for(j in mapO.supportKind()){
  a=mapO.getO(j);
  for(i in a){
   //sl(a[i].name+','+a[i].address);
   if(a[i].name in lostItem)delete lostItem[a[i].name];
   else if(('address' in a[i]) && (a[i].address in lostItem))delete lostItem[a[i].address];
   id=typeof a[i].getLatLng=='function'?a[i].getLatLng():a[i].name;
   if(!(id in OK))
    OK[id]=1,
	t.push(''
     +(a[i].name||i).replace(/<[^>]+>/g,'')
     +' ['+_f.closeMark+']');// title="remove marker"
  }
 }
 for(i in lostItem)t.push(''+i+'');
 t.push('');
 //sl(UnicodeToHTML(t.join('')),1);
 _f.write(t.join(''));
 //	see dealWithLink() @ link.js
 if(typeof dealWithLink=='function')setTimeout('dealWithLink(0,1);',0);
 return false;
}
//	show spot
showSP.defaultI=0;	//	default icon index
showSP.selectedI=2;	//	selected icon index
function showSP(o,i){
 if(o){
  var name,type;
  if(type=showML.getName(o)){
   name=type[0],type=type[1];
   o=mapO.getO(type,name);
   if(o&&o.setImage&&o!=showML.sel())
    //sl('showSP: set icon of ['+o.name+'] to '+i),
    o.setImage(mapO.icon(i).image);
  }
  return false;
 }
}
//	應用
function removeAll(){
 showML.refresh=0,lostItem={};
 if(mapO)mapO.removeAll();	//	尚未 initial?
 if(showML)showML.sel(null,1),showML.refresh=1,showML();
}
//	不能造成 type 改變!
function normalize_address(t) {
	var _f = arguments.callee, a = '0123456789';
	if (!_f.dc) {
		_f.nr = new RegExp('[' + a + ']', 'g');
		_f.dc = {};
		for ( var i = 0; i < a.length; i++)
			_f.dc[a.charAt(i)] = i;
	}
	return t.replace(/[\s ]+/g, '').replace(_f.nr, function($0) {
		return _f.dc[$0];
	})
	//.replace(/號([^樓]+樓|之.{1,2})$/,'號');
	;
};
/*
http://www.post.gov.tw/post/internet/f_searchzone/sz_a_b_ta.jsp#a
縣市
鄉鎮市區	【市】為縣轄市
村里	直轄市:台北市、高雄市及省轄市:基隆市、新竹市、台中市、嘉義市、台南市以外地區由於路名結構變化較大,有些地區沒有路、街,僅有「村」、「里」名稱
鄰
路街	路名中不可使用(全、半形)阿拉伯數字,必須一律使用中文數字,如中正二路等,惟門牌號不必輸入。	新村、山莊、新城、工業區等與街、路同級之名稱
段
巷	文字巷
弄
號
\d(之\d)樓(之\d)
縣市鄉鎮區村里鄰路街段巷弄號樓
TODO:
806台灣高雄市前鎮區光華二路413號
*/
_// JSDT:_module_
.
/**
 * 解析地址
 * @param {String} address	地址
 * @returns
 * @_memberOf	_module_
 */
parse_address = function (address) {
	var a = {}, i, v, w = '縣市鄉鎮區村里鄰路街段巷弄號樓',
	r = new RegExp('[^' + w + ']+([' + w + '])', 'g');
	var _ = address.replace(/[ \s]+/g, '').replace(/號([^樓F]{1,6})F$/, '號$1樓')
			.replace(/^(\d{3,5})?[台臺]灣/, '$1').replace(/^\d+/, function($0) {
				r.zip = $0;
				return '';
			}).replace(r, function($0, $1) {
				v = $0;
				if (/縣市/.test(i = $1) && !r.zip)
					v.replace(/^\d{3}\d{2}?}/, function($0) {
						r.zip = $0;
						return '';
					});
				a[i] = v;
				//sl(v);
				return '';
			});
	// sl('['+address+'] --- ['+_+']');
	return _ ? 0 : address;
};
//	地址轉 index
getO.n={};	//	name(address) to mapO.getO's name
getO.add=function(alias,name,type){
 if(alias&&name&&alias!=name){
  if(type&&mapO.getO(type,alias)&&!mapO.getO(type,name)){
   var t=name;name=alias,alias=t;
  }
  //sl('getO.add: ['+alias+'] set to ['+name+']'),
  this.n[alias]=name;
 }
};
getO.alias=function(name){return this.n[name]||name;};
function getO(name){
 return mapO.getO(arguments.callee.n[name]||name);
}
/*	search address
sA(index of mData)
sA({type(where):'',name:'',description:''})
sA(type(where),name,description)
*/
function sA(i,a,b){
 if(!mData)return;	//	尚未 initial?
 if(!(i in mData)||arguments.length>1)
  //sl('sA: search '+i),
  mapO.searchPoint.apply(mapO,arguments);
 else
  //sl('sA: call mData['+i+']('+mData[i].type+')'),
  mapO.searchPoint(mData[i]);
 return false;
}
//	先找尋現有資料
function sA2(adr,noFit){
 var _f=arguments.callee;
 if(!noFit){
  showFit(adr
	,function(k,o){return k&&(o.name+o.description).indexOf(k)!=-1;}
	,function(k){_f(adr,1);}
  );
  return;
 }
 if(typeof adr_to_mData!='object'||mapO.LatLngR.test(adr))return sA(adr);
 //return sA(adr_to_mData[adr]||adr);
 if(!_f.c)_f.c=document.getElementById('guess');
 if(!(adr in adr_to_mData)&&(adr.toLowerCase() in adr_to_mData))
  //sl('sA2: ['+adr+']→['+adr.toLowerCase()+']'),
  adr=adr.toLowerCase();
 if(adr_to_mData[adr] in mData){
  var a=adr_to_mData[adr];
  mData[a].show=1;	//	置中
  sA(a);
  if(showML.selO)mapO.showWindow(showML.selO);
 }else if(!_f.c)sA(adr);
 else mapO.getLocations(adr,function(r){
	 var cM='[×]
';
	 if(gLocal){gLocal.searcher.setCenterPoint(showNeighbor.pointer.getLatLng()||mapO.setCenter()||'台灣');gLocal.s(adr);}
	 if(!r.length){_f.c.innerHTML=cM+'使用 GClientGeocoder.getLocations 沒找到 ['+adr+']:
'+mapO.GeoStatus(mapO.getLocations.errno),_f.c.style.display='block';return;}
	 if(r.length==1&&adr==r[0][2]){sA(adr);if(showML.selO)mapO.showWindow(showML.selO);return;}
	 var i=0,t=[cM+'對於 ['+adr+'],您是不是指:'];
	 for(;i〒 '+r[i][2]+'');
	 t.push('
');
	 _f.c.innerHTML=t.join('');
	 _f.c.style.display='block';
	});//sA(adr);
 return false;
}
/*
從 mData show 符合條件的
*/
showFit.showZoom=40;	//	這以下就 zoom
showFit.limit=80;	//	最多取點數
function showFit(k,func,notFound){
 if(typeof k=='undefined'||!func)return;
 removeAll();
 showML.write('頁面資料讀取中,請稍候…');
 var i,p=[],b,_f=arguments.callee;
 for(i in mData)
  if(func(k,b=mData[i],i) && (b=mapO.searchPoint.call(mapO,b)))	//	確定有找到才 c++
   if(p.push(b), _f.limit&&p.length>_f.limit)break;
 if(p.length<_f.showZoom)
  if(p.length){
   //	zoom
   b=new GLatLngBounds();
   for(i=0;i搜尋附近';
  for(i=0;i'+p[i]+'';
  s+=' km';
  if(overlay==m)m.openInfoWindowHtml('經緯度: '+m.getLatLng()+s);
  else if(!overlay&&point)
   p=m.getLatLng(),m.setLatLng(point),
   m.openInfoWindowHtml(point+'
from: '+p+',
distance: '+(p.distanceFrom(point)/1000).toFixed(3)+'km'+s);
 });
 return this.pointer=m;
};
showNeighbor.arg={	//	傳給 .getNeighbor() 的參數
	//f:'n[i]=n[i][1][2];',	//	不能改變結構!因為需要 getBoundsZoomLevel
	d:30,
	c:9
};
showNeighbor.forEach=function(a){
 //sl('showNeighbor.forEach: ['+(typeof a[1][2])+'] '+a[1][2]);
 sA(a[1][2]);
};
showNeighbor.byD=function(d){
 var _t=this;
 if(d)_t.arg.d=d;
 if(_t.pointer)_t(_t.pointer.getLatLng());
 return false;
};
showNeighbor.notFound=function(address,address_not_found){
 showML.write('抱歉,找不到 '+address+''+(address_not_found?'':' 附近的點')+'。');
};
function showNeighbor(l,f){//(location | [location, address], addSelf)
 if(!l)return;
 showML.write('頁面資料讀取中,請稍候…');
 var _f=arguments.callee,i,o,adr;
 if(Array.isArray(l))adr=l[1],l=l[0];
 //sl('showNeighbor: ['+l+','+adr+'] '+(l instanceof GLatLng)+', '+mapO.getLatLng(l+''));
 if(!(l instanceof GLatLng))
  // 無此資料。嘗試取得 loc..
  return mapO.getLatLng(l+'',[function(p){_f([p,adr||l]);},function(p){if(p)return _f([p,adr||l]);_f.notFound&&_f.notFound(adr||l,1);}]);
 o=mapO.getNeighbor(l,_f.arg);
 if(o.length){
  removeAll();
  var bounds=new GLatLngBounds();
  bounds.extend(l);
  for(i=0;i'+adr+' ':l)+' 四周 '+_f.arg.d+' km
找到 '+o.length+'/(最多 '+_f.arg.c+') 個點。');
 //sl('showNeighbor: search around '+l+' (四周 '+_f.arg.d+' km) get '+o.length+'/(max '+_f.arg.c+') results.');
}
//	===================================================
/*
	** use Yahoo! Map to get position of a address
_=this
TODO:
HISTORY:
2008/7/31 19:56:29	create
http://tw.developer.yahoo.com/maps/
http://developer.yahoo.com/maps/ajax/V3.8/index.html
*/
var
getLatLon=
(function(){
var
//	class private	-----------------------------------
//	class name
n='getLatLon',
//	running now
r=0,
//	interval/timeout seed
s=''+Math.random()*1e12,
//	{ address: [function(lat, lng, address), not found function(address)], .. }
o={},
//	queue: [ adr, .. ]
q=[],
//	map object
m,
//	initial
i=function(){
 if(typeof YMap!='function'){
  //sl(n+': Please include YMap first!');
  return 1;
 }
 var o=document.createElement('div');
 document.body.appendChild(o);
 o.style.width=o.style.height='1px';	//	=0 會造成 .getArea() 出問題
 YEvent.Capture(m=new YMap(o),EventsList.onEndGeoCode,c);
 o.style.visibility='hidden';
 //o.style.display='none';	//	會造成 .getArea() 出問題
 //s=Math.random()*1e12+'';
},
//	do query
d=function(){
 //sl(n+'.do query: '+q[0]);
 if(!q||!q.length)r=0;
 else m.geoCodeAddress(q.shift());
},
//	catch function
c=function(r){
 var a=r.Address,f;
 if(f=_.interval)
  setTimeout(n+'("'+s+'");',f);
 else d();
 if(a in o)
  if(f=o[a],r.success)f[0](r.GeoPoint.Lat,r.GeoPoint.Lon,a);
  else f[1]&&f[1](a);
 delete o[a];
},
//	instance constructor	---------------------------
_=function(a,f,nf){	//	address, function, not found function
 if(a===s)return d();
 if(!a||!f || !m&&i())return 1;
 o[a+='']=[f,nf];
 //sl(n+': ('+q.length+')'+[a,f,nf]);
 q.push(a);
 if(!r)r=1,d();
};
//	class public interface	---------------------------
//	interval (ms)
_.interval=0;
//	class constructor	---------------------------
i();
return _;
})();	//	(function(){
//	===================================================
/*	old
//	use Yahoo! Map
//	interval
//getLatLon.t=200;
//	{ address: [function, not found function], .. }
getLatLon.o={};
//	queue: [ adr, .. ]
getLatLon.q=[];
//	initial
getLatLon.i=function(){
 if(typeof YMap!='function'){
  //sl('getLatLon: Please include YMap first!');
  return 1;
 }
 var c=document.createElement('div');
 document.body.appendChild(c);
 c.style.width=c.style.height=0;
 YEvent.Capture(this.m=new YMap(c),EventsList.onEndGeoCode,this.c);
 c.style.display='none';
 this.T=Math.random()*1e12+'';
};
//	catch function
getLatLon.c=function(r){
 var t=getLatLon;
 if(t.t)setTimeout('getLatLon.d("'+t.T+'");',t.t);else getLatLon.d();
 var f=t.o;
 if(r.Address in f)
  if(f=f[r.Address],r.success)f[0](r.GeoPoint.Lat,r.GeoPoint.Lon,r.Address);
  else f[1]&&f[1](r.Address);
 delete t.o[r.Address];
}
//	do query
getLatLon.d=function(){
 var _f=arguments.callee,_t=this,a,f,n;
 //sl('getLatLon.d: '+_t.q[0]);
 if(!_t.q||!_t.q.length)_t.r=0;
 else _t.m.geoCodeAddress(_t.q.shift());
};
//	running
//getLatLon.r=0;
function getLatLon(adr,f,nf){
 var _f=arguments.callee;
 if(adr===_f.T)return _f.d();
 if(!adr||!f || !_f.m&&_f.i())return;
 if(!_f.q)_f.q=[];
 //sl('getLatLon: ('+_f.q.length+')'+[adr,f,nf]);
 _f.o[adr]=[f,nf];
 _f.q.push(adr);
 if(!_f.r){_f.r=1;_f.d();}
}
*/
//	===================================================
/*
	main map function
_=this
TODO:
*/
//var
gMap=
(function(){
//	class private	-----------------------------------
var
//	class interface	-----------------------------------
_=function(){
 //	Dynamic Loading	http://code.google.com/apis/ajax/documentation/#Dynamic
 //if(typeof GMap=='undefined')google.load("maps","2",{language:"ja_JP",callback:mapsLoaded});
 //	init member
 var _t=this,i;
 //	initial instance object
 _t.locArray=[],_t.locArray2=[],_t.locArray_u={},_t.locArray2_u={},_t.iconA=[],_t.iconO={},_t.dMarkerO={};
 _t.kinds={marker:GMarker,polyline:GPolyline,polygon:GPolygon,xml:GGeoXml};	//	If this failed, maybe GMap didn't loaded?
 for(i in _t.kinds)
  if(i in _t)throw 'Error: ['+i+'] is already a member of me!';
  else _t[i]={};
 //	調整 GLatLng 的顯示
 GLatLng.prototype.toS=function(p){
  if(!p)p=_t.precision||0;
  return Number(this.lat()).toFixed(p)+','+Number(this.lng()).toFixed(p);
 };
 GLatLng.prototype.toString=function(p){return '('+this.toS(p)+')';};
/*
	http://blog.wctang.info/2007/07/use-google-map-api-without-api-key.html
	Geocode 查詢每天有 50000 次的限制	使用 Geocoder 就是要連到 Google 去做查詢,而現在 Google 在做 Geocode 查詢時會在 Server 端做 API key 的檢查,這個就躲不掉了
	http://blog.wctang.info/2007/07/use-google-map-geocoder-without-api-key.html
*/
 if(GBrowserIsCompatible()&&!_t.geocoder)
  with(_t.geocoder=new GClientGeocoder())
	setCache(null),	//	disable cache, 因為找到的都被管控了。
	setBaseCountryCode('tw');	//	語系
 //_t.readLoc();
 _t.initMap.apply(_t,arguments);//return _t.initMap.apply(_t,arguments);
};
//	class public	-----------------------------------
//	prototype	-----------------------------------
_.prototype={
//	這些函數可重寫
notFound:function(address,data){
 return 1;//throw 'Address ['+address+'] not found!';
},
//	增加 overlay 後
runAfterAdd:function(obj,type,data,name){},
//	移除 overlay 後
runAfterRemove:function(obj,type){},
//	按 overlay 時
runOnClick:function(obj,type){},
precision:6,	//	精度,算到小數點下第幾位。GMap 2008:6
defaultZoom:14,	//	預設縮放
/*
map,	//	GMap obj
TODO:
use GMarkerManager,	http://code.google.com/apis/maps/documentation/overlays.html#Marker_Manager
//handle array:
marker={'lat,lng':GMarker},	//	GMarker 地圖標記
polyline={points:GPolyline},	//	GPolyline 折線
polygon={points:GPolygon},	//	GPolygon 多邊形
xml={URL:GGeoXml},		//	GGeoXml: xml/kml
*/
kinds:{},
supportKind:function(k){
 return k?k in this.kinds:this.kinds;
},
getKind:function(o){
 for(var i in this.kinds)
  if(o instanceof this.kinds[i])return i;
},
//	讀入先前 catch 的經緯度,存loc而不必每次search
readLoc:function(){
 var _t=this,t,i=0,l,a;
 if(!_t.locFP)_t.locFP='map_loc.dat';	//	紀錄 LatLng/地址 可供 searchPoint() 使用
 //	GDownloadUrl(url,callback)
 try{t=getU(_t.locFP);}catch(e){}
 _t.adr_to_loc={};
 if(!t||!(t=t.replace(/\r/g,'').split('\n')).length)return;
 sl('Get '+t.length+' catched address records from ['+_t.locFP+'].');
 for(;i1 && (l=a[0].split(',')).length==2)
   _t.adr_to_loc[a[1]]=new GLatLng(l[0],l[1])
   //,sl('readLoc: ['+a[1]+'] '+_t.adr_to_loc[a[1]])
   ;
  else sl('readLoc: error data: '+t[i]);
},
//	** important ** 這邊不能作 object 之 initialization,否則因為 object 只會 copy reference,因此 new 時東西會一樣。initialization 得在 _() 中作!
//	locArray[]=[lat,lng,adr] sort by lat	給 writeLoc() & getNeighbor() 用,僅包含需要 search 的。
locArray:[],
//	寫入 catched 的經緯度
writeLoc:function(s){
 var _t=this,i,t=[],l,a=_t.precision,b,c;
 //sl('writeLoc: We will write data to ['+_t.locFP+'].');
 if(!_t.locFP)return;
 for(i in _t.adr_to_loc)
  if(l=_t.adr_to_loc[i])try{
   if(isNaN(b=Number(l.lat()))||isNaN(c=Number(l.lng())))throw new Error(1,'經緯度非數字');
   t.push([b.toFixed(a),c.toFixed(a),i]);
  }catch(e){sl('writeLoc: Error: '+e.message+': ['+l+'] '+i+', ('+l.lat()+','+l.lng()+')');}
 sl('writeLoc: '+_t.locArray.length+'→'+t.length);
 //	不相同時才作處理
 if(t.length!=_t.locArray.length){
  t.sort(function(l,r){return l[0]-r[0]||l[1]-r[1];});
  for(a=_t.locArray=[],b=_t.locArray_u={},c=[],i=0;iWarning: function.js is not included?');
 }
 if(s)sl('');
 return t;
},
//	locArray2[]=[lat,lng,adr] sort by lat	給 getNeighbor() 用,包括所有不需要 search 的地址。
locArray2:[],
locArray_u:{},locArray2_u:{},	//	預防重複: locArray_u['lat,lng']=obj of locArray or locArray2
/*	取得鄰近的地點: 經緯度, 最大距離(km)	http://blog.ben.idv.tw/2007/06/blog-post.html	http://hk.geocities.com/hk_weather/big5/others/calculators.html	http://blog.xuite.net/joy715/blog/9285691	http://iask.sina.com.cn/b/6263160.html
mapO.getNeighbor([22.620096,120.333381],"sl(n[i][1][2]);");
return:
	f.d:	距離(km)
	f.c:	最多取用點數,<=0:全取,未設:default
	f.s:	最後時選取與否的篩選設置之函數	傳回數值越大越後面
	f.D:	計算距離之函數,將用來比較
		default			[ [較準確的距離, [lat,lng,adr]],.. ]
		求得較大概的距離(以距離平方比計算,比較快)
					[ [距離, [lat,lng,adr]],.. ]	f.D=function(p,l){var a=l.lat()-p[0],b=l.lng()-p[1];return a*a+b*b;}
	f.f:	對選出之 spot 作最後處置之函數
		default			[ [較準確的距離, [lat,lng,adr]],.. ]
		傳回地址		[ adr1, adr2,.. ]		f.f=	'n[i]=n[i][1][2];'
		傳回 obj		[ [lat,lng,adr],.. ]		f.f=	'n[i]=n[i][1];'
		求得較準確的距離	[ [距離, [lat,lng,adr]],.. ]	f.f=	'n[i][1]=l.distanceFrom(n[i][1]);'
*/
getNeighbor:function(l,f){
 var _t=this,lat,lng,i,n=[],p=function(A){
	//	計算最接近上限mLat之loc
	//	c: 誤差
	var i=0,j=A.length,a,b,c=f._d,mLat=lat-c;
	if(!j)return;
	//sl(mLat+'~'+(lat+c));
	do{
	 //sl(Math.floor((i+j)/2)+'/'+A.length+','+A[a=Math.floor((i+j)/2)]);
	 b=A[a=Math.floor((i+j)/2)][0];
	 if(b>mLat)j=a;else if(bc);
	//sl('start: from ['+a+'/'+A.length+'] '+A[a].join(':')+' to '+(lat+c));var tt=[];
	for(i=a,mLat=lat+c,a=lng-c,b=lng+c;i'));
 };
 if(typeof l=='string')l=l.split(',');
 //if(typeof l=='function'&&l.lat&&l.lng)lat=typeof l.lat=='function'?l.lat():l.lat,lng=typeof l.lng=='function'?l.lng():l.lng;
 if(l instanceof GLatLng)lat=l.lat(),lng=l.lng();
 else lat=l[0],lng=l[1],l=new GLatLng(lat,lng);
 //	這邊起 l 為原始點之 GLatLng
 if(typeof f!='object')
  f=isNaN(f)?{f:f}:{d:f};
 f._d=(f.d>0?f.d:20)/111;	//	1度的實際長度~111公里。
 if(!f.D)f.D=function(p,l){
	//var a=lat-p[0],b=lng-p[1];return a*a+b*b;	//	大概的,比較快。
	return l.distanceFrom(new GLatLng(p[0],p[1]));	//	real distance
 };
 //sl(lng+', '+lat+'; '+f._d);
 _t.writeLoc();
 p(_t.locArray);
 _t.locArray2.sort(function(l,r){return l[0]-r[0]||l[1]-r[1];});
 //sl('['+_t.locArray2.length+']
* '+_t.locArray2.join('
* '));
 p(_t.locArray2);
 //sl('Get '+n.length+' records near ('+lat+','+lng+').');
 //	由近至遠 sort
 if(typeof f.s=='undefined')f.s=function(l,r){return l[0]-r[0];};	//	l, r: [distance by f.D,[lat,lng,adr]]
 if(f.s)n.sort(f.s);
 //for(i=0;if.c)
  n=n.slice(0,f.c>0?f.c:9);	//	預設取 9 個
 if(typeof f.f=='string')f.f=new Function('n','i','l',f.f);
 //sl('Run: [~'+n.length+'] by '+f.f);
 if(typeof f.f=='function')
  for(i=0;i]*>/ig,'\n').match(/[^\r\n]+[市區街路][^\r\n]+/))
   //sl('('+m[1]+','+m[3]+') ['+a[0]+']'),
   if(!((m[1]+','+m[3]) in _t.locArray2_u))_t.locArray2.push(_t.locArray2_u[m[1]+','+m[3]]=[m[1],m[3],a[0]]);
  m=new GLatLng(m[1],m[3]);
  return func?func(m):m;
 //	搜尋已知地址
 }else if((m=_t.adr_to_loc) && (m=m[adr]))//sl('getLatLng: handle adr_to_loc['+adr+']='+m[adr]+' get '+(func?c(m):m)/*+' by '+func*/),
  return func?c(m):m;
 //	搜尋未知地址
 else if(func)
  //sl('Not catched: '+adr+''),
  return _t.geocoder.getLatLng(adr,typeof f=='function'?function(m){f(m,adr);}:c);	//	 原來需要用 arguments.callee.f,但若已經用 var 定義則可直接使用。
},
/*
d={
 name:'',	//	這邊 name 被當作 id, title
 description:'HTML',
 type:'',
 data:['','']
//選用 optional:
 htm:'HTML' / function(obj){return 'HTML';},
//尚未用到︰
 link:'',
};
*/
add:function(d,force){
 if(!d||typeof d!='object')return this;
 var _t=this,o=_t.supportKind(d.type);
 if(!o){_t.searchPoint(d);return this;}
 //if(!(d.type in _t))_t[d.type]={};
 var _S=_t[d.type],_m=this.map,a;
 //if(typeof _S!='object')sl('add: typeof ['+d.type+'] = '+(typeof _S));
 if((d.name in _S)&&!force)return this;	//	已存在
 o=_t.kinds[d.type];
 if(d.type=='marker'){
  o=new o(new GLatLng(d.data[0],d.data[1]),_t.getMarkerO(d));
  //if(d.zIndexP)o._zIndexProcess=o._zIndexProcess,o.zIndexProcess=d.zIndexP;	//	** 可以利用 zIndexP 來在 infowindow is opened 時設定 z-index.. 沒用 @ 2008/6/30 19:43:43
 }else a={points:d.data[0],levels:d.data[1],numLevels:4,zoomFactor:16},
	o=new o.fromEncoded(d.type=='polyline'?a:{polylines:[a],fill:true,outline:true});//geodesic:true	Geodesic means 'along great circle'
 _t._add(o,d);
 return this;
},
searchPoint:function(adr,name,description){
 var _f=arguments.callee,_t=this,type='marker',_M=_t[type],_m=_t.map,latlng,d;
 if(typeof adr=='object')d=adr,adr=adr.type;else d={type:adr,show:_f.show};	//	預設 searchPoint.show
 if(!d.name)d.name=name||adr;
 if(typeof d.description=='undefined')
  if(description)d.description=description;
  else if(d.name!=adr)d.description=adr;
 if(!d.type)return;
 if(isNaN(d.retry)&&!_t.geocoder.getCache())d.retry=2;	//	找不到時重試次數
try{
 if(adr in _M)
  //sl('We already have ['+adr+']'),
  _t.show(_M[adr],type);
 else _t.getLatLng(adr+='',function(point){
	if(!point){
	 if(d.retry){
	  //sl('try once more('+d.retry+'): ['+adr+']');
	  d.retry--,_f.call(_t,d);return false;
	 }else{
	  //sl('searchPoint: not found function: '+_t.notFound);
	  return _t.notFound(adr,d);
	 }
	}else{
	 if(adr in _M)return;	//	可能經過太久才被 load?
	 // ** 注意:這邊沒設 _M[adr]=_M[point.toUrlValue(_t.precision)]
	 var p=new GMarker(latlng=point,_t.getMarkerO(d));
	 if(!d.name)d.name=p+'';
	 //sl('found '+point+' '+d.name+', icon: '+p.getIcon().iconSize);
	 //point='loc: '+point;
	 if(typeof d.description=='undefined')d.description=point;
	 else if(d.description==adr)d.description+='
'+point;
	 //_M=_M[adr];
	 if(!('address' in p))p.address=adr;else throw 'GMarker.address was used: ['+p.address+']!';
	 //sl('Last add '+adr+'..');
	 _t._add(p,d,type);
	}
  },d);
}catch(e){sl('searchPoint: Error: '+adr+', '+_M+': '+e.message);}//throw e;
 return latlng;
},
// private:	註冊 o 成為內容 d={},並設定 click 等 event
_add:function(o,d,type){
 if(!o)return;
 if(!d)d=o;
 if(!type)type=d.type;
 var _t=this,_S=_t[type],_m=this.map;
 //if(d.name)_S[d.name]=o;	//	或許已經設定過了,這邊就需要跳過。
 if(((d.name||d)+'') in _S)
  sl('_add: Warning: Type '+type+' 已存在 ['+(d.name||d)+']'+(_S[d.name||d].getLatLng?' '+_S[d.name||d].getLatLng():'')+('address' in _S[d.name||d]?' '+_S[d.name||d].address:'')+'!'
	//+'
_add: 將以 ['+(o.name||d.name||d)+']'+(o.getLatLng?' '+o.getLatLng():'')+(o.address?' '+o.address:'')+' 覆寫。'
	);
 _S[d.name||d]=o;	//	必設!!
 if(_m)_m.addOverlay(o);//_t._addOverlay(o);//
 //if(o.getIcon)sl('_add: show '+o.getIcon().iconSize+' '+o.getIcon().image);
 o.name=d.name,o.dscr=d.description;	//	GMarker 中這兩個本來就有被用,偵測也只會發現已使用。
 //	another way to add tooltip: GControlPosition
 if(!('sHtm' in o)){
  if('htm' in d)o.sHtm=typeof d.htm=='function'?d.htm.call(d,o,type):d.htm;
  else o.sHtm=(d.name?''+d.name+''+(d.description?'
':''):'')+(d.description||'');
 }else throw '['+type+'].sHtm was used: ['+o.sHtm+']!';
 if(!('sHtmF' in o)){
  if('htmF' in d)
   o.sHtmF=typeof d.htmF=='function'?d.htmF.call(d,o,type):d.htmF;
 }else throw '['+type+'].sHtmF was used: ['+o.sHtm+']!';
 //	openInfoWindowTabs: http://www.geocodezip.com/mapXmlTabsPlus.asp
 GEvent.addListener(o,"click",function(e){
  _t.showWindow(o);
  _t.runOnClick(o,type,e&&e.target||window.event&&window.event.srcElement);
 });
 if(d.show)_t.show(o,type);
 _t.runAfterAdd(o,type,d,d.name||d);
},
_addOverlay:function(o){
 var _t=this,_m=_t.map;
 if(!_t._aa)_t._aa=[];
 if(o){_t._aa.push(o);return;}
 var i;
 while(i=_t._aa.shift())
  _m.addOverlay(i);
},
//	icon setup
defaultIconIndex:0,
iconA:[],
iconO:{},
icon:function(index){
 var _t=this;
 if(Array.isArray(index)){
  //	設定 icon
  _t.iconA=[];
  for(var a,i=0,p,u;i=_t.iconA.length)index=_t.defaultIconIndex;
 //sl('icon: return icon['+index+'] '+(_t.iconA[index]?_t.iconA[index].iconSize+' '+_t.iconA[index].image:'G_DEFAULT_ICON'));
 return _t.iconA[index]||G_DEFAULT_ICON;
},
dMarkerO:{},	//	default marker option
getMarkerO:function(mo,setMO){	//	setMO: set default, 1: add, 2:reset
 var _t=this,i,a={icon:1,title:1,zIndexProcess:1,draggable:1};	//	class GMarkerOptions
 _t.dMarkerO.icon=_t.icon();
 if(setMO){
  if(setMO==2)_t.dMarkerO={};
  setMO=_t.dMarkerO;
 }else{
  //	複製一份
  setMO={};
  for(i in _t.dMarkerO)
   //sl('getMarkerO: from default ['+i+']=['+_t.dMarkerO[i]+']'),
   setMO[i]=_t.dMarkerO[i];
 }
 if(library_namespace.is_Object(mo))
  for(i in a)
   if(a[i]&&typeof mo[i]!='undefined')
    //sl('getMarkerO: set ['+i+']=['+mo[i]+']'),
	setMO[i]=mo[i];
 //sl('getMarkerO: icon: '+setMO.icon.iconSize+' '+setMO.icon.image);
 return setMO;
},
/*	增加自己控制的 marker,會自動顯現,但不會列入管控,得自己設定。
usage:
mapO.addMarker(dLoc.tw,{draggable:true});
*/
addMarker:function(loc,opt){
 var _t=this,_m=_t.map,m;
 if(_m){
  if(Array.isArray(loc))loc=new GLatLng(loc[0],loc[1]);
  m=new GMarker(loc,_t.getMarkerO(opt));
  //sl('addMarker icon: '+_t.getMarkerO(opt).icon.iconSize+' '+_t.getMarkerO(opt).icon.image);
  //sl('addMarker iconSize: '+_t.getMarkerO(opt).iconSize);
  _m.addOverlay(m);
 }
 return m;
},
//	f={p:position, m:method(pan/panBy/set), z:zoom}
setCenter:function(f){
 var _m=this.map;
 if(f instanceof GLatLng||!library_namespace.is_Object(f))f={p:f};
 //sl('setCenter: setZoom ['+(f.z||null)+'] @ '+f.p+' by method ['+(f.m||'setCenter')+'].');
 if(!isNaN(f.z))_m.setZoom(f.z);
 if(f.p){
  if(Array.isArray(f.p))f.p=new GLatLng(f.p[0],f.p[1]);
  if(f.m=='pan')_m.panTo(f.p);
  else if(f.m=='panBy')_m.panBy(f.p);
  else _m.setCenter(f.p);
 }
 return _m.getCenter();
},
//	zoom above 19	You can set zoom up to 30 by using setCenter() not by setZoom() or zoomIn()	firefox: 45.1238,-123.1138	http://esa.ilmari.googlepages.com/highres.htm
/*
eval('error_noImage=p(10121);',mapO.map);
sl(error_noImage);
*/
zoom:function(z){
 var _t=this,_m=_t.map,m;
 if(typeof z=='string'&&(m=z.match(/^[+-]/)))z=_m.getZoom()+(m[0]=='+'?z:-z);
 if(z)_m.setZoom(z);//try{_m.setCenter(_m.getCenter(),z);}catch(e){}	//	中文中, enableContinuousZoom()? 這麼搞會出錯
 return _m.getZoom();
},
//	show, or focus. f={noCenter:false, redraw: false}
show:function(name,type,f){
 var _t=this,_S=_t[type],_m=_t.map,inC;	//	inC: in control
 if(typeof name=='string')
  if(name in _S)_S=_S[name],inC=1;
  else _S=0;
 else _S=name;
 if(typeof _S!='object'||!_S)return;
 if(_S.isHidden&&_S.isHidden())_S.show();
 if(typeof f!='object')f={noCenter:f};	//	default: don't set to center
 if(!f.noCenter){
  var p=_t.getPoint(_S,type);
  //sl('show: center= '+p);
  if(_m){
   _m.setCenter(p);
   if(_m.getZoom()<9)_m.setZoom(_t.defaultZoom);
   if(inC)_t.showWindow(_S,p);	//	未管控就 showWindow 會有奇妙的結果。
  }
 }
 if(f.redraw && _S.redraw)_S.redraw(true);	//	Front/back order of markers can be messed simply by moving them in south-north direction. (v1) 	http://koti.mbnet.fi/ojalesa/exam/anim_v2.html
 return _t;
},
//	show HTML window (obj, point)	o.sHtmF=show HTML flag: {maxContent:'', ..}: see class GInfoWindowOptions
showWindow:function(o,p){
 //sl('showWindow: '+(p||o.openInfoWindowHtml));
 if(typeof o.openInfoWindowHtml=='function')
  o.openInfoWindowHtml(o.sHtm,o.sHtmF);	//	enableMaximize()
 else this.map.openInfoWindowHtml(p||this.getPoint(o),o.sHtm,o.sHtmF);
},
//	get the GLatLng of the object
getPoint:function(o,type){
 if(!type)type=this.getKind(o);
 //sl('getPoint: ['+type+']'+o.name);
 if(type=='marker'&&typeof o.getLatLng=='function')return o.getLatLng();
 if(typeof o.getBounds=='function')
  return o.getBounds().getCenter();
 if(typeof o.getCenter=='function')
  return o.getCenter();
 if(typeof o.getVertexCount=='function')
  return o.getVertex(Math.floor(o.getVertexCount()/2));
},
getZoom:function(o,type){
 if(!type)type=this.getKind(o);
 //sl('getPoint: ['+type+']'+o.name);
 if(typeof o.getBounds=='function')
  return this.getBoundsZoomLevel(o.getBounds());	//	得到適當的 zoom
 //if(type=='marker')return _t.defaultZoom;
 return _t.defaultZoom;
},
initMap:function(id,latlng,f){	//	container, center, other initial setting flags
 var _t=this,_m,a;
 //	檢查當前瀏覽器是否支持地圖 API 庫
 if(GBrowserIsCompatible()){
  //	指定GMap使用的圖層 @ id
  if(typeof id=='string')id=document.getElementById(id);
  if(!id)return _t;
  _t.canvas=id;	//	container object
  if(!f)f={};
  if(!f.size)
   f.size=f.x&&f.y?[f.x,f.y]:[640,320];
  if(Array.isArray(f.size))f.size=new GSize(f.size[0],f.size[1]);
  _m=_t.map=new GMap2(id,f);//=new google.maps.Map2();
  //	設定中心點座標
  _m.setCenter(latlng||new GLatLng(0,0),7);	//	default center.
  //_m.setMapType(G_HYBRID_MAP);
  _m.addMapType(G_PHYSICAL_MAP);	//	地形圖
  _m.addMapType(G_SATELLITE_3D_MAP);	//	with the Google Earth Browser Plug-in
  //	控制元件	客制化: http://julian.norway.idv.tw/index.php/archives/322
  //_m.addControl((new GHierarchicalMapTypeControl()).addRelationship(G_SATELLITE_MAP, G_HYBRID_MAP, "Labels", true));
  //_m.removeMapType(G_HYBRID_MAP);
  _m.addControl(a=_t.overviewMap=new GOverviewMapControl(new GSize(_m.getSize().width/2.5,_m.getSize().height/2)));	//	可折疊的縮小圖
  a.hide();	//	show(), hide().
  //a.getOverviewMap().addControl(new GMenuMapTypeControl(1));	must use setTimeout: getOverviewMap() is not available until after the module has loaded.
  _m.addControl(new GLargeMapControl());	//	加入地圖縮放工具
  _m.addControl(new GMenuMapTypeControl(1));//GMapTypeControl(1)	//	切換地圖型態的按鈕
  _m.addControl(new GScaleControl());	//	地圖比例尺
  _m.enableScrollWheelZoom();
  _m.enableContinuousZoom();	//	平滑放大
  GEvent.addListener(_m,'mouseover',function(){_m.showControls();});
  GEvent.addListener(_m,'mouseout',function(){_m.hideControls();});
 }else{
  sl('抱歉,您的瀏覽器不支援 Google Maps!');
 }
 return _t;
},
/*	移除所有管控項
c.f.,	this.map.clearOverlays()
*/
removeAll:function(type){
 var _t=this,i,o;
 if(!type)for(i in _t.kinds)
  arguments.callee.call(this,i);
 else{
  //sl('removeAll: ('+(typeof type)+') ['+type+'], '+(typeof _t[type]));
  //o=[];for(i in _t[type])o.push(i);for(i=0;iw&&w>0)x=w;
   if(y>h&&h>0)y=h;
   (new GControlPosition(G_ANCHOR_TOP_LEFT,new GSize(x,y))).apply(o);
   _t.showContextMenu(1);
  });
 _t.showContextMenu(0);
 return o;
},
showContextMenu:function(v){
 var o=this.contextMenu;
 if(o)o.style.visibility=v||typeof v=='undefined'?'visible':'hidden';
},
//	get overlay
getO:function(type,name){
 var s=this[type];
 return name?name in s?s[name]:null:s;
},
//	get name of the type
getOArray:function(type){
 var i,a=[],o=this[type];
 if(o)for(i in o)a.push(i);
 return a;
},
/*
var i,t=[],o;
o=GGeoXml.prototype;//GMap2.prototype
sl('['+(typeof o)+'] '+(o+'').replace(/\n/g,'
')+'
',1);for(i in o)t.push('['+(typeof o[i])+'] '+i);sl(t.sort().join('
'));
TODO:
GEvent.addListener(map,"addoverlay",function(overlay){if(overlay.name){}});
*/
loadXML:function(URL){
 var _t=this,x=new GGeoXml(URL);
 //	.getDefaultCenter(), .getDefaultBounds() 可能是 null
 _t.setCenter({p:x.getDefaultCenter(),z:x.getDefaultBounds(),m:'pan'});
 _t.map.addOverlay(x);
 return _t.xml[URL]=x;
},
//resize map
resize:function(x,y){
 with(this.map.getContainer().style)
  width=x+'px',height=y+'px';
},
//	去除商標, Copyright message
removeTM:function(l){
 var a=this.canvas;
 if(!a)return;
 a=library_namespace.get_tag_list('a'),i=a.length,t=1;
 //sl('removeTM: '+UnicodeToHTML(document.getElementById('map_canvas').innerHTML));
 for(;i>0&&(t||l);){
  i--;
  //	http://www.google.com/intl/en_ALL/help/terms_maps.html
  if(t && a[i].href.indexOf('terms_maps')!=-1 && a[i].parentNode.tagName.toLowerCase()=='div'){
   //sl('removeTM: remove copyright: '+a[i].href);
   //sl('removeTM: remove copyright: '+UnicodeToHTML(a[i].parentNode.innerHTML));
   removeNode(a[i].parentNode,1);	//	連這div都刪除會有奇怪現象發生
   t=0;
  }else if(l && a[i].innerHTML.indexOf('poweredby.png')!=0){
   //sl('removeTM: remove logo: '+UnicodeToHTML(a[i].parentNode.innerHTML));
   removeNode(a[i].parentNode,1);
   l=0;
  }
 }
}
};	//	_.prototype=
return _;
})();	//	(function(){
//	===================================================
/*	2008/9-10/1
	搜尋用代理工具
usage:
google.load("search","1",{language:"ja_JP",callback:loadSearch});
function loadSearch(){
 gSearch=new getSearch(function(r,p){
  sl(''+r.title+'
'+r.content+'
');
 });
}
 
 
TODO:
Yahoo! Search BOSS	http://developer.yahoo.com/search/boss/
LocalSearch:
http://www.google.com/uds/samples/apidocs/static-tiles.html
http://code.google.com/apis/ajaxsearch/documentation/reference.html#_class_GlocalSearch
*/
function getSearch(fn,kind){	//	handle function, kind: Web/Local
 if(!kind)kind='Web';
 var _t=this,_s=typeof google!='undefined'?google.search:0;
 if(!_s||!_s[kind+'Search'])return;
 _s=_t.searcher=new _s[kind+'Search']();
 if(kind=='Local'){
  //sl('Set center: '+'Taiwan');
  _s.setCenterPoint('台灣');//Taiwan
  _s.setResultSetSize(google.search.Search.LARGE_RESULTSET);
  //_s.setCenterPoint("93108");
 }else{
  _s.setNoHtmlGeneration();
  //.addSearcher(_s,(new google.search.SearcherOptions()).setExpandMode(google.search.SearchControl.EXPAND_MODE_OPEN));
 }
 _s.setResultSetSize(google.search.Search.LARGE_RESULTSET);
 _s.setSearchCompleteCallback(_t,_t.searchComplete[kind],[_s]);
 if(fn)_t.sf=fn;
 return _t;
}
getSearch.prototype={
//	country translate
countryT:{Taiwan:'台灣'},
searchComplete:{
Local:function(searcher){
 var r=searcher.results,i=0,a,b,j;
 if(r&&r.length>0)for(;ipage '+p+':');
 if(r&&r.length)for(;i