﻿//*******************************************************************************
//    File name: common.js
//    Date: 2008/01/29
//    Remark: The java script of common utilities.
//    Author: Mark Yang
//    Note:
//*******************************************************************************

var _MSIE = 1;
var _NN = 2;
var _MACIE = 3;
var _MOZ = 4;
var _SAFARI = 5;
var _OPERA  =6;
var _GECKO = 7;
var _FF = 8;

var _MSFT = 1;
var _MAC = 2;
var _LINUX = 3;
var _UNIX = 4;
var _OTHERS = 5;

var _dom_Others = 0;
var _dom_IE4 = 1;
var _dom_IE5up = 2;
var _dom_NN4 = 3;
var _dom_NN6up = 4;

var g_nUA = null;
var g_nUAVer = null;
var g_OS = null;
var g_dom = null;

var g_bBusy = false;
var g_MainFrame = null;
var g_summary = [];

var _MaTypeVal = {
	'photo':0,
	'placemark':18
}

var _EnableVal = {
	'enable':1,
	'disable':0
}

var _PicTypeVal = {
	'URL':0,
	'EMBED':18
}

try {
	var _SupGMapType = [
	G_NORMAL_MAP,
	G_SATELLITE_MAP,
	G_HYBRID_MAP,
	G_PHYSICAL_MAP
	];
}
catch (err) {
	//alert(lstr_GMapConnErr);
}


// for mini-album list symbolic index!
/* 	o: photoId
	1: time stamp
	2: Lat
	3: Lng
	4: trackId
	5: marker icon Id
	6: Original photo [URL, type, width, height]
	7: Middle size photo [URL, type, width, height]
	8: thumbnail size photo [URL, type, width, height]
	9: title
	10: description
*/
var _MaId = 0; // Photo(item) Id.
var _MaTStamp = 1; // TimeStamp
var _MaLat = 2; // Lat
var _MaLng = 3; // Lng
var _MaTrkId = 4; // track Id.
var _MaMkrIcon = 5; // marker icon Id.
//var _MaScrIcon = 6; // small info icon Id.
//var _MaType = 7; // type Id
var _MaOri = 6; //_MaOri
var _MaMid = 7; //
var _MaThm = 8; //_MaThm
var _MaTitle = 9;
var _MaDesc = 10;
var _MaGMarker = 11;
var _MaState = 12;

var _sbURLAddr = 0;
var _sbType = 1;
var _sbURLW = 2;
var _sbURLH = 3;
var _sbImgObj = 4;


// Define the measure unit:
var _msMetric = 0;
var _msUS = 1;

// Metric translate to US. All data are Metric unit. 
// If display measure unit is set to US, template have to convert by itself.
function _Km2Mile(data) {
	// 1 kilometre(km) = 0.621  mile
	return (data*0.621);
}

function _M2Ft(data) {
	// 1 metre(m) = 3.28  foot(ft)
	return (data*3.28);
}

function _M2Yd(data) {
	// 1 metre(m) = 1.09  yard(yd)
	return (data*1.09);
}

/*
    Example:
        attrlstr = { 'alt':lstr_Tips1,
                     'title':lstr_Tips2,
                     'desc':lstr_Tips3 };
*/
function _applyAttr(strId, attrlstr) {
	var tmpObj = $(strId);
	if (tmpObj != null) {
	    for (var i in attrlstr) {
	        var strCmd = 'tmpObj.'+i+'="'+attrlstr[i]+'";';
	        eval(strCmd);
	    }
	}
}
	
function __get(id) {
    return g_MainFrame.getObj(id);
}

//-------------------------------------------------------------------------
function GetBrowserCap() {
	//confirm("userAgent = \""+navigator.userAgent+"\"");
	//confirm("appName = \""+navigator.appName+"\"");
	//confirm("appVersion = \""+navigator.appVersion+"\"");
	//confirm("language = \""+navigator.language+"\"");
	//confirm("mimeType = \""+navigator.mimeType+"\"");
	//confirm("platform = \""+navigator.platform+"\"");
	//window.status = navigator.userAgent;
	
	// _mac : true = macintosh, false = other os
	//_mac = (navigator.userAgent.indexOf('Mac') != -1);
	// _ie512 : true = MSIE 5.12(mac), false = others
	//_ie512 = (navigator.userAgent.indexOf('MSIE 5.12') != -1);
	// _dom : kind of DOM.
	//        IE4 = 1, IE5+ = 2, NN4 = 3, NN6+ = 4, others = 0
	
	//var isIE = (document.all && document.getElementById && !window.opera)?true:false;
	//var isMozilla=(!document.all&&document.getElementById&&!window.opera)?true:false;
	//var isOpera=(window.opera)?true:false;

	g_dom = document.all ? (document.getElementById ? _dom_IE5up : _dom_IE4) 
						 :(document.getElementById ? _dom_NN6up 
						   						   : (document.layers ? _dom_NN4 : _dom_Others));
				   
	var strUsrAgent = navigator.userAgent.toLowerCase();
	var strAppName = navigator.appName.toLowerCase();
	var strAppVer = navigator.appVersion.toLowerCase();
	//if (strAppName.indexOf("microsoft internet explorer") != -1) {
	if (document.all && document.getElementById && !window.opera) {
		g_nUA = _MSIE;
		if (strAppVer.match(/7./i)=='7.') {
			g_nUAVer = 7;
			//confirm("Current web browser is IE 7.");
		}
		else {
			g_nUAVer = 6;
			//confirm("Current web browser is IE 6.");
		}
	}
	//else if(strAppName.indexOf("netscape") != -1) {
	else if (!document.all && document.getElementById && !window.opera) {
		g_nUA = _NN;
		if (strUsrAgent.indexOf("firefox") != -1) {
			g_nUA = _FF;
		}
		//confirm("Current web browser is Mozilla FireFox.");
	}
	else if (window.opera) {
		g_nUA = _OPERA;
		//confirm("Unknown browser.");
	}
	else if (strUsrAgent.indexOf("safari") != -1) {
		g_nUA = _SAFARI;	
	}
	else if (strUsrAgent.indexOf("gecko") != -1) {
		g_nUA = _GECKO;	
	}
}

// Get browser capability first!
if (g_nUA == null) {
	GetBrowserCap();
}

			
function getWindowWidth (){
/*  if(g_dom==_dom_NN6up || g_dom==_dom_NN4) {
	  return window.innerWidth;
  }
  if(g_dom==_dom_IE5up || g_dom==_dom_IE4) {
	  return document.body.clientWidth;
  }
  return 0;
*/
  if (document.documentElement.clientWidth) {
	return document.documentElement.clientWidth;
  }
  return 0;
}

function getWindowHeight(){
/*  if(g_dom==_dom_NN6up || g_dom==_dom_NN4) {
	  return window.innerHeight;
  }
  if(g_dom==_dom_IE5up || g_dom==_dom_IE4) {
	  return document.body.clientHeight;
  }
  return 0;
*/
  if (document.documentElement && document.documentElement.clientHeight) {
	return document.documentElement.clientHeight;
  }
  return 0;
}


function _IsPhotoAni(photodata) {
	if (photodata != null) {
		return (photodata[_MaTStamp] > 0);
	}
	return false;
}

function _adjImgPad(imgobj, srcW, srcH, maxW, maxH, bInsideWnd) {
	//var imgobj = $(this.strImgLeadText+photodata[_MaId]);
	if (imgobj != null) {
		var retParams = getResizeInfo(imgobj, srcW, srcH, maxW, maxH, bInsideWnd);
		if (retParams != null) {
			//imgobj.style.width = retParams.newW+'px';
			//imgobj.style.height = retParams.newH+'px';
			imgobj.width = retParams.newW; // +'px';
			//imgobj.height = retParams.newH+'px';
			if (retParams.topPad != 0) {
				imgobj.style.marginTop = retParams.topPad+'px';
			}
			if (retParams.leftPad != 0) {
				imgobj.style.marginLeft = retParams.leftPad+'px';
			}
		}
	}
}

function _createDateTime(nTime, tzOffset) {
	
	var time_obj = new Date();
	var time_value = (nTime + tzOffset) * 1000;
	time_obj.setTime(time_value);
	return time_obj;	
	
//	var time1 = new Date(nTime*1000);
//	var UTCtime = time1.getTime();// + (time1.getTimezoneOffset() * 60000);
//	var curlocTime = new Date(UTCtime + tzOffset*1000);
//	return curlocTime;
}

function _SWOFFOBJ() {
    for (var i=0; i<arguments.length; i++) {
        if (arguments[i] != null) {
            arguments[i].style.display = "none"; 
            arguments[i].style.visibility = "hidden";
        }
    }
}

function _SWONOBJ() {
    for (var i=0; i<arguments.length; i++) {
        if (arguments[i] != null) {
            arguments[i].style.display = "block"; 
            arguments[i].style.visibility = "visible";
        }
    }
}

function _SWOFF() {
    for (var i=0; i<arguments.length; i++) {
        var obj = $(arguments[i]);
        if (obj != null) {
            _SWOFFOBJ(obj);
        }
    }
}

function _SWON() {
    for (var i=0; i<arguments.length; i++) {
        var obj = $(arguments[i]);
        if (obj != null) {
            _SWONOBJ(obj);
        }
    }
}

function _setOpt(obj, val) { // set opacity style.
    if (obj != null && obj.complete) {
        if (g_nUA == _MSIE) {
            obj.filters.alpha.opacity = (val*100);
        }
        else {
            obj.style.opacity = val;
        }
    }
}

function exchangeBtn(src, dst) {
    var tmp;
    tmp = $(src).src; 
    $(src).src = $(dst).src; 
    $(dst).src = tmp;
    tmp = $(src).alt; 
    $(src).alt = $(dst).alt; 
    $(dst).alt = tmp;
    tmp = $(src).title; 
    $(src).title = $(dst).title; 
    $(dst).title = tmp;
    tmp = $(src).onclick; 
    $(src).onclick = $(dst).onclick; 
    $(dst).onclick = tmp;
}

//-------------------------------------------------------------------------
function checkUserData() {
	if (typeof(g_aryIconOnMap) != 'undefined'
		&& typeof(g_aryTrackInfo) != 'undefined'
		&& typeof(g_aryAlbumInfo) != 'undefined') {
		return true;	
	}
	return false;
}


function getDateTimeStr(objDate) {
	
    var YYYY = objDate.getUTCFullYear();
    var MM = objDate.getUTCMonth()+1;
    MM = (MM < 10) ? '0'+MM : MM;
    var DD = objDate.getUTCDate();
    DD = (DD < 10) ? '0'+DD : DD;
    var hh = objDate.getUTCHours();
    hh = (hh < 10) ? '0'+hh : hh;
    var mm = objDate.getUTCMinutes();
    mm = (mm < 10) ? '0'+mm : mm;
    var ss = objDate.getUTCSeconds();
    ss = (ss < 10) ? '0'+ss : ss;
    var strTmp = YYYY + "/" + MM + "/" + DD + " " + hh + ":" + mm + ":" + ss;
    return strTmp;
}

//-------------------------------------------------------------------------
// $() simulate a simple macro to 'getElementById'.
// example:
//		var obj = $('myId'); // typeOf(obj) == 'object'
function $()
{
	if (arguments.length == 1) {
		return document.getElementById(arguments[0]);
	}
	
	var objRetAry = [];
	for (var i=0; i<arguments.length; i++) {
		if (typeof(arguments[i]) == 'string') {
			objRetAry.push(document.getElementById(arguments[i]));
		}
	}
	return objRetAry;
}


function _Exec() {
    var Params = [];
    for (var i=0; i<arguments.length; i++) {
        Params.push(arguments[i]);
    }
    var strId = Params[0];
    var strFuncName = Params[1];
    var PassToParams = [];
    for (var i=0; i<Params[2].length; i++) {
        PassToParams.push(Params[2][i]);
    }    
    var tmpObj = g_MainFrame.getObjById(strId);
    if (tmpObj != null) {
        var strCmd = "tmpObj."+strFuncName+"(";
        var strCaller = PassToParams.shift();
        for (var j=0; j<PassToParams.length; j++) {
            if (j > 0) {
                strCmd += ",";
            }
            if (typeof(PassToParams[j]) == 'string') {
                strCmd += ("'" + PassToParams[j] + "'");
            }
            else {
                strCmd += PassToParams[j];
            }
            
        }
        strCmd += ")";
        return eval(strCmd);
    }
    return null;
}
//-------------------------------------------------------------------------
// ReplaceAll() will replace all specified string which we wanna take in source text.
// ***NOTE: String.replace() only replace the first found string if you do not use regular expression!
function ReplaceAll(strSrc, strFind, strReplace){
	if (strFind != strReplace) {
		while(strSrc.indexOf(strFind) != -1){
			strSrc = strSrc.replace(strFind, strReplace);
		}
	}
	return strSrc;
}

// New added function for Template Converter 
function ConvertLatLng2Str(lat, lng)
{ 
  var strlatLeadText = (lat > 0) ? lstr_N : lstr_S;
  var strlngLeadText = (lng > 0) ? lstr_E : lstr_W;
  return strlatLeadText + " " + Math.abs(lat) + ", " + strlngLeadText + " " + Math.abs(lng);
}

//-------------------------------------------------------------------------
function TransDivTitle(strSrcText){
	var strOutput = strSrcText;
	strOutput = strOutput.replace(/ /g, "&#32;");	
	strOutput = strOutput.replace(/\r\n/g, "&#10;");
	strOutput = strOutput.replace(/\n\r/g, "&#10;");
	strOutput = strOutput.replace(/\n/g, "&#10;");
	strOutput = strOutput.replace(/\r/g, "&#10;");
	strOutput = strOutput.replace(/</g, "&lt;");
	strOutput = strOutput.replace(/>/g, "&gt;");
	strOutput = strOutput.replace(/\"/g, "&quot;");
	strOutput = strOutput.replace(/'/g, "&#39;");
	if (strOutput.length == 0) {
	    strOutput = '""';
	}
	return strOutput;
}

//-------------------------------------------------------------------------
// TransHtmlSrc() will translate all special chars in source text into Html escape symbol.
function TransHtml2(strSrcText) {
	var strOutput = strSrcText;
	//strOutput = strOutput.replace(/ /g, "&nbsp;");
	//strOutput = strOutput.replace(/^ /g, "&nbsp;");
	strOutput = strOutput.replace(/&/g, "&amp;");
	strOutput = strOutput.replace(/</g, "&lt;");
	strOutput = strOutput.replace(/>/g, "&gt;");
	strOutput = strOutput.replace(/\"/g, "&quot;");
	strOutput = strOutput.replace(/'/g, "&#39;");
	strOutput = strOutput.replace(/\n/g, "<br \\>");
	
	return strOutput;
}

function TransHtmlSrc(strSrcText){
	var strOutput = strSrcText;

	strOutput = strOutput.replace(/&/g, "&amp;amp;");
	strOutput = strOutput.replace(/</g, "&amp;lt;");
	strOutput = strOutput.replace(/>/g, "&amp;gt;");
	
	//strOutput = strOutput.replace(/&amp;amp;/g, "&amp;amp;");
	//strOutput = strOutput.replace(/&amp;lt;/g, "&amp;lt;");

	strOutput = strOutput.replace(/^ /g, "&amp;nbsp;");
	strOutput = strOutput.replace(/\n /g, "&#10;");//"<br><kbd>&lt;br&gt;</kbd>&amp;nbsp;");
	strOutput = strOutput.replace(/\n/g, "&#10;");//"<br><kbd>&lt;br&gt;</kbd>");
	strOutput = strOutput.replace(/  /g, " &amp;nbsp;");
	strOutput = strOutput.replace(/\"/g, "&amp;quot;");

	strOutput = strOutput.replace(/©/g, "&amp;copy;");
	strOutput = strOutput.replace(/®/g, "&amp;reg;");
	strOutput = strOutput.replace(/™/g, "&amp;trade;");
	strOutput = strOutput.replace(/¢/g, "&amp;#162;");
	strOutput = strOutput.replace(/£/g, "&amp;#163;");
	strOutput = strOutput.replace(/¤/g, "&amp;#164;");
	strOutput = strOutput.replace(/¥/g, "&amp;#165;");
	strOutput = strOutput.replace(/€/g, "&amp;euro;");
	strOutput = strOutput.replace(/¿/g, "&amp;#191;");
	strOutput = strOutput.replace(/¡/g, "&amp;#161;");
	strOutput = strOutput.replace(/×/g, "&amp;#215;");
	strOutput = strOutput.replace(/÷/g, "&amp;#247;");
	strOutput = strOutput.replace(/±/g, "&amp;#177;");
	strOutput = strOutput.replace(/¼/g, "&amp;#188;");
	strOutput = strOutput.replace(/½/g, "&amp;#189;");
	strOutput = strOutput.replace(/¾/g, "&amp;#190;");
	strOutput = strOutput.replace(/‰/g, "&amp;#8240;");
	strOutput = strOutput.replace(/À/g, "&amp;#192;");
	strOutput = strOutput.replace(/à/g, "&amp;#224;");
	strOutput = strOutput.replace(/Á/g, "&amp;#193;");
	strOutput = strOutput.replace(/á/g, "&amp;#225;");
	strOutput = strOutput.replace(/Â/g, "&amp;#194;");
	strOutput = strOutput.replace(/â/g, "&amp;#226;");
	strOutput = strOutput.replace(/Ã/g, "&amp;#195;");
	strOutput = strOutput.replace(/ã/g, "&amp;#227;");
	strOutput = strOutput.replace(/Ä/g, "&amp;#196;");
	strOutput = strOutput.replace(/ä/g, "&amp;#228;");
	strOutput = strOutput.replace(/Å/g, "&amp;#197;");
	strOutput = strOutput.replace(/å/g, "&amp;#229;");
	strOutput = strOutput.replace(/È/g, "&amp;#200;");
	strOutput = strOutput.replace(/è/g, "&amp;#232;");
	strOutput = strOutput.replace(/É/g, "&amp;#201;");
	strOutput = strOutput.replace(/é/g, "&amp;#233;");
	strOutput = strOutput.replace(/Ê/g, "&amp;#202;");
	strOutput = strOutput.replace(/ê/g, "&amp;#234;");
	strOutput = strOutput.replace(/Ë/g, "&amp;#203;");
	strOutput = strOutput.replace(/ë/g, "&amp;#235;");
	strOutput = strOutput.replace(/Ì/g, "&amp;#204;");
	strOutput = strOutput.replace(/ì/g, "&amp;#236;");
	strOutput = strOutput.replace(/Í/g, "&amp;#205;");
	strOutput = strOutput.replace(/í/g, "&amp;#237;");
	strOutput = strOutput.replace(/Î/g, "&amp;#206;");
	strOutput = strOutput.replace(/î/g, "&amp;#238;");
	strOutput = strOutput.replace(/Ï/g, "&amp;#207;");
	strOutput = strOutput.replace(/ï/g, "&amp;#239;");
	strOutput = strOutput.replace(/Ò/g, "&amp;#210;");
	strOutput = strOutput.replace(/ò/g, "&amp;#242;");
	strOutput = strOutput.replace(/Ó/g, "&amp;#211;");
	strOutput = strOutput.replace(/ó/g, "&amp;#243;");
	strOutput = strOutput.replace(/Ô/g, "&amp;#212;");
	strOutput = strOutput.replace(/ô/g, "&amp;#244;");
	strOutput = strOutput.replace(/Õ/g, "&amp;#213;");
	strOutput = strOutput.replace(/õ/g, "&amp;#245;");
	strOutput = strOutput.replace(/Ö/g, "&amp;#214;");
	strOutput = strOutput.replace(/ö/g, "&amp;#246;");
	strOutput = strOutput.replace(/Ø/g, "&amp;#216;");
	strOutput = strOutput.replace(/ø/g, "&amp;#248;");
	strOutput = strOutput.replace(/Ù/g, "&amp;#217;");
	strOutput = strOutput.replace(/ù/g, "&amp;#249;");
	strOutput = strOutput.replace(/Ú/g, "&amp;#218;");
	strOutput = strOutput.replace(/ú/g, "&amp;#250;");
	strOutput = strOutput.replace(/Û/g, "&amp;#219;");
	strOutput = strOutput.replace(/û/g, "&amp;#251;");
	strOutput = strOutput.replace(/Ü/g, "&amp;#220;");
	strOutput = strOutput.replace(/ü/g, "&amp;#252;");
	strOutput = strOutput.replace(/Æ/g, "&amp;#198;");
	strOutput = strOutput.replace(/æ/g, "&amp;#230;");
	strOutput = strOutput.replace(/ß/g, "&amp;#223;");
	strOutput = strOutput.replace(/Ç/g, "&amp;#199;");
	strOutput = strOutput.replace(/ç/g, "&amp;#231;");
	strOutput = strOutput.replace(/Ñ/g, "&amp;#209;");
	strOutput = strOutput.replace(/ñ/g, "&amp;#241;");
	strOutput = strOutput.replace(/Œ/g, "&amp;#140;");
	strOutput = strOutput.replace(/œ/g, "&amp;#156;");
	strOutput = strOutput.replace(/Þ/g, "&amp;#222;");
	strOutput = strOutput.replace(/þ/g, "&amp;#254;");
	strOutput = strOutput.replace(/Ð/g, "&amp;#208;");
	strOutput = strOutput.replace(/ð/g, "&amp;#240;");
	strOutput = strOutput.replace(/ý/g, "&amp;#253;");
	strOutput = strOutput.replace(/①/g, "&amp;#9312;");
	strOutput = strOutput.replace(/②/g, "&amp;#9313;");
	strOutput = strOutput.replace(/③/g, "&amp;#9314;");
	strOutput = strOutput.replace(/④/g, "&amp;#9315;");
	strOutput = strOutput.replace(/⑤/g, "&amp;#9316;");
	strOutput = strOutput.replace(/⑥/g, "&amp;#9317;");
	strOutput = strOutput.replace(/⑦/g, "&amp;#9318;");
	strOutput = strOutput.replace(/⑧/g, "&amp;#9319;");
	strOutput = strOutput.replace(/⑨/g, "&amp;#9320;");
	strOutput = strOutput.replace(/⑩/g, "&amp;#9321;");

	strOutput = strOutput.replace(/&amp;/g, "<samp>&amp;</samp>");
	return strOutput;
}


// [BEGIN] These functions are use to fade in/out a object via opacity attribute!
function higherImg(obj){
	theobject = obj;
	highlighting = setInterval("higherLight(theobject)", 10);
}

//-------------------------------------------------------------------------
function lowerImg(obj){
	clearInterval(highlighting);
	if (obj.filters != null) { //_MSIE
	    obj.filters.alpha.opacity = 60;
	}
    //else if (g_nUA == _FF) {
    //    obj.style.MozOpacity = 0.6;
    //}
    else if (g_nUA != _MSIE) {
	    //obj.style.setProperty("-moz-opacity","0.6", null);
	    //obj.style.mozopacity = 0.6;
	    //obj.filters.mozopacity += 0.05;	    
	    obj.style.opacity = 0.6;
    }	
}

	
//-------------------------------------------------------------------------
function higherLight(obj){
	if (g_nUA == _MSIE && obj.filters != null && obj.filters.alpha.opacity < 100) {
	    obj.filters.alpha.opacity += 5;
	    return;
	}
	else if (g_nUA != _MSIE && obj.style.opacity < 100) {
		//obj.style.setProperty("-moz-opacity", obj.filters.alpha.opacity/100, null);
		//obj.style.mozopacity += 0.05;
		//obj.filters.mozopacity += 0.05;
		var tmp = (obj.style.opacity != null) ? parseFloat(obj.style.opacity) : 0.6;
		tmp += 0.05;
		obj.style.opacity = tmp;
		//if (g_nUA == _FF) {
        //    changecss(obj.className, 'MozOpacity', obj.style.opacity);
        //}
		return;
    }
	else if (window.highlighting) {
		clearInterval(highlighting);
	}
}


function getResizeInfo(imageObj, oriW, oriH, maxW, maxH, bInsideWnd) {
	if (imageObj != null) {
		if (oriW < 0 && oriH < 0) {
		    if (!imageObj.complete) {
				return null;
			}
			else {	
				oriW = imageObj.width;
				oriH = imageObj.height;
		    }	
		}
	}
	var width_ratio = oriW / Math.max(maxW, 1);
	var height_ratio = oriH / Math.max(maxH, 1);
	if (bInsideWnd) {
		if (width_ratio > 1.0 && width_ratio >= height_ratio) {
			oriW = maxW;
			oriH = Math.floor(oriH / width_ratio);
		}
		else if (height_ratio > 1.0 && width_ratio < height_ratio) { 
			oriW = Math.floor(oriW / height_ratio);
			oriH = maxH;
		}
		var topPad = Math.floor(Math.max((maxH - oriH), 0)/2);
		var leftPad = Math.floor(Math.max((maxW - oriW), 0)/2);
		var retParams = {
			'newW':oriW,
			'newH':oriH,
			'topPad':topPad,
			'leftPad':leftPad
		};
		return retParams;
	}
	else {
		if (width_ratio > 1.0) {
			if (width_ratio < height_ratio) {
				oriW = maxW;
				oriH = Math.floor(oriH / width_ratio);
			}
			else { 
				oriW = Math.floor(oriW / height_ratio);
				oriH = maxH;
			}
		}
		var topPad = Math.floor((maxH - oriH)/2);
		var leftPad = Math.floor((maxW - oriW)/2);
		var retParams = {
			'newW':oriW,
			'newH':oriH,
			'topPad':topPad,
			'leftPad':leftPad
		};
		return retParams;
	}

	return null;
}

//[END]


//Construct all parameters by Kent Hsu.
//Please write correct path for below fields
//(string)    s_imgControl : picture path/trackBar.gif
//(string)    s_imgSlider : picture path/trackBar_Point.gif
/*
var A_TPLh = {
  'b_vertical' : false,
  'b_watch': true,
  'n_controlWidth': 158,
  'n_controlHeight': 21,
  'n_sliderWidth': 9,
  'n_sliderHeight': 21,
  'n_pathLeft' : 1,
  'n_pathTop' : 0,
  'n_pathLength' : 148,
  's_imgControl': 'http://farm3.static.flickr.com/2112/2105259740_260665eb7b_o.gif', // 'MHTTemp/bmp/trackBar.gif'
  's_imgSlider': 'http://farm3.static.flickr.com/2359/2104481601_48a190e734_o.gif', // 'MHTTemp/bmp/trackBar_Point.gif'
  'n_zIndex': 1
}

var A_INITh = {
  's_form' : 0,
  's_name': 'sliderValue6h',
  'n_minValue' : 0,
  'n_maxValue' : poscount, //Total Position
  'n_value' : 0, //initial value
  'n_step' : 1,
  's_SlideBarBaseId' : '',
  's_SlideRunnerId' : ''
}
*/


function CSlideCtrl(strSlideId, objMainFrame) {
	this.mf = objMainFrame;
	this.id = strSlideId + '_' + this.mf.getUniqueId();
	this.curSlidePos = 0;
	this.n_pathLeft  = 1;
    this.n_minValue = 0;
    this.n_maxValue = 0;
    this.n_value = 0;
    this.n_step = 1;
    this.n_pix2value = 0;
    
	// register in the global collection	
	if (!window.A_SLIDERS) {
		window.A_SLIDERS = [];
	}
	this.n_id = window.A_SLIDERS.length;
	window.A_SLIDERS[this.n_id] = this;


	// safely hook document/window events
// 	if (document.onmousemove != f_sliderMouseMove) {
// 		window.f_savedMouseMove = document.onmousemove;
// 		document.onmousemove = f_sliderMouseMove;
// 	}
// 	if (document.onmouseup != f_sliderMouseUp) {
// 		window.f_savedMouseUp = document.onmouseup;
// 		document.onmouseup = f_sliderMouseUp;
// 	}
	// preset to the value in the input box if available
	//var e_input = (this.s_form == null) ? get_element(this.s_name) : 
	//	(document.forms[this.s_form] ? document.forms[this.s_form].elements[this.s_name] : null);
	
	//-------------------------------------------------------------------------
	// CSlideCtrl methods:
	this.sliderError = function (n_id, s_message) {
		alert("Slider #" + n_id + " Error:\n" + s_message);
		//window.n_activeSliderId = null; //n_activeSliderId is used fot mouse draging!
	}
	
	//-------------------------------------------------------------------------
	this.clipSlidePos = function (nPos) {
		nPos = Math.max(this.n_minValue, nPos);
		nPos = Math.min(this.n_maxValue, nPos);		
		return nPos;
	}
	
	//-------------------------------------------------------------------------
	this.setValue  =  function (nNewValue, b_noInputCheck) {  //f_setValue
	//function f_sliderSetValue (n_value, b_noInputCheck);

	
		if (nNewValue == null) {
			nNewValue = (this.curSlidePos == null) ? this.n_minValue : this.curSlidePos;
		}
		if (isNaN(nNewValue)) {
			return false;
		}
		
		// round to closest multiple if step is specified
		if (this.n_step) {
			nNewValue = Math.round((nNewValue - this.n_minValue) / this.n_step) * this.n_step + this.n_minValue;
		}
		
		// smooth out the result
		if (nNewValue % 1) {
			nNewValue = Math.round(nNewValue * 1e5) / 1e5;
		}
		nNewValue = this.clipSlidePos(nNewValue);
		this.curSlidePos = nNewValue;
		
		// move the slider
		if (this.b_vertical) {
			this.e_slider.style.top  =
				(this.n_pathTop + this.n_pathLength 
				 - Math.round((nNewValue - this.n_minValue) * this.n_pix2value)) + 'px';
		}
		else {
			var TMP = Math.round((nNewValue - this.n_minValue) * this.n_pix2value);
			this.e_slider.style.left = 
				(this.n_pathLeft 
				 + Math.round((nNewValue - this.n_minValue) * this.n_pix2value)) + 'px';
		}
		
		// save new value
		/*
		var e_input;
		if (this.s_form == null) {
			e_input = get_element(this.s_name);
			if (!e_input) {
		  		return b_noInputCheck ? null : sliderError(this.n_id, "Can not find the input with ID='" + this.s_name + "'.");
			}
		}
		else {
			var e_form = document.forms[this.s_form];
			if (!e_form) {
		  		return b_noInputCheck ? null : sliderError(this.n_id, "Can not find the form with NAME='" + this.s_form + "'.");
			}
			e_input = e_form.elements[this.s_name];
			if (!e_input) {
		  		return b_noInputCheck ? null : sliderError(this.n_id, "Can not find the input with NAME='" + this.s_name + "'.");
			}
		}
		e_input.value = nNewValue;
		*/
	}		
	
	//-------------------------------------------------------------------------
	this.OnSetSlideValue = function (nNewValue) {
		this.setValue(nNewValue);	
	}

/*	this.getPos = function (b_vertical, b_base) { //f_getPos
	// function f_sliderGetPos (b_vertical, b_base) {
		var n_pos = 0,
		s_coord = (b_vertical ? 'Top' : 'Left');
		var o_elem = o_elem2 = b_base ? this.e_base : this.e_slider;
		
		while (o_elem) {
			n_pos += o_elem["offset" + s_coord];
			o_elem = o_elem.offsetParent;
		}
		o_elem = o_elem2;
		
		var n_offset;
		while (o_elem.tagName != "BODY") {
			n_offset = o_elem["scroll" + s_coord];
			if (n_offset) {
				n_pos -= o_elem["scroll" + s_coord];
			}
			o_elem = o_elem.parentNode;
		}
		return n_pos;
	}	
*/
	//-------------------------------------------------------------------------
	this.initialize = function (a_init, a_tpl) {
		// save config parameters in the slider object
		if (a_tpl) {
			for (var i in a_tpl) {
				this[i] = a_tpl[i];
			}
		}
		
		for (var i in a_init) {
			this[i] = a_init[i];
		}
	
		this.n_pix2value = this.n_pathLength / Math.max(1, (this.n_maxValue - this.n_minValue));
		if (this.n_value != null) {
			this.curSlidePos = this.n_value;
			this.n_value = null; 
		}
		this.curSlidePos = this.clipSlidePos(this.curSlidePos);
		
		this.e_base   = $(this.s_SlideBarBaseId); //get_element('sl' + this.n_id + 'base');
		this.e_slider = $(this.s_SlideRunnerId); //get_element('sl' + this.n_id + 'slider');
		
		this.setValue(this.curSlidePos); //(e_input&&(e_input.value != '') ? e_input.value : null), 1);
		this.e_slider.style.visibility = 'visible';			
		this.mf.bindUsrEvent(this.id, _evtMf_ThumbPos, "OnSetSlideValue");
	}
	

}

/*
<div 
style="border: 0pt none ; width: 158px; height: 21px; background-image: url(http://farm3.static.flickr.com/2112/2105259740_260665eb7b_o.gif);" 
id="sl0base">
	<img 
	src="http://farm3.static.flickr.com/2359/2104481601_48a190e734_o.gif" 
	style="position: relative; left: 1px; top: 0px; z-index: 1; visibility: visible;" 
	name="sl0slider" 
	id="sl0slider" 
	border="0" 
	height="21" 
	width="9">
</div>

*/

function cloneArray(srcAry) {
	var tmpAry = [];
	for (var i=0; i<srcAry.length; i++) {
		tmpAry.push(srcAry[i]);
	}
	return tmpAry;
}

Number.prototype.toRad = function() {  // convert degrees to radians
  return this * Math.PI / 180;
}

Number.prototype.toDeg = function() {  // convert radians to degrees (signed)
  return this * 180 / Math.PI;
}

Number.prototype.toBrng = function() {  // convert radians to degrees (as bearing: 0...360)
  return (this.toDeg()+360) % 360;
}

function GetNextPtDir(lat1, lng1, lat2, lng2, dircount) {
    // Formula: θ = atan2( sin(Δlong).cos(lat2),
    // 					cos(lat1).sin(lat2) - sin(lat1).cos(lat2).cos(Δlong) ) 
    // JavaScript:
    //      var y = Math.sin(dLon) * Math.cos(lat2);
    //      var x = Math.cos(lat1)*Math.sin(lat2) -
    //              Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
    //      var brng = Math.atan2(y, x).toBrng(); 			
    var dLon = lng2-lng1;
    var y = Math.sin(dLon) * Math.cos(lat2);
    var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
    var brng = Math.atan2(y, x).toBrng(); 			

    var onedirdegree = 360/dircount;
    var tmpDir = (brng + (onedirdegree / 2)) / onedirdegree;
    tmpDir = Math.floor(tmpDir)%dircount;
    return tmpDir;
/*
    if ((brng >= 315 && brng <= 360) || (brng >=0 && brng < 45)) {
        return 0; // Go North.
    }
    if (brng >= 45 && brng < 135) {
        return 1; // Go East.
    }
    if (brng >= 135 && brng < 225) {
        return 2; // Go South.
    }
    if (brng >= 225 && brng < 315) {
        return 3; // Go West.
    }
    return 0; //-1; // to avoid error!
*/    
}
//
//
function getCurZoomLevel() {
	var parObj = __get(GMId);		
	var center = parObj.myGmap.getCenter();
	var lat = center.lat().toString().substring(0,8);
	var lng = center.lng().toString().substring(0,8);
	var zoom = parObj.myGmap.getZoom();
	// change the waypoints in the track!
	var curBnds = parObj.myGmap.getBounds(); //GLatLngBounds
	var curSize = parObj.myGmap.getSize(); //GSize in pixels
	var bndSize = parObj.myGmap.getBounds().toSpan();
	var tmpdist = curBnds.getSouthWest().distanceFrom(curBnds.getNorthEast());
	var dist = Math.sqrt(Math.pow(curSize.width, 2) + Math.pow(curSize.height, 2));
	var tmpZoomLevel = Math.min(Math.floor((tmpdist / dist) / 10), 100);
	return tmpZoomLevel;
}
//---------------------------------------------------------------------------------------
var _UndefTrkId = '_XXX_UNDEFINED_TRACK_ID_XXX_';
//
var _CUROPT = 1.0;
var _SELOPT = 0.7;
var _NOROPT = 0.8;
var _CURWET = 4;
var _SELWET = 12;
var _NORWET = 4;

// for array use! //'time stamp', 'lat', 'lng', 'speed', 'elevation' , 'type' , 'zoom', 'distance'
var _TRKTMT = 0;
var _TRKLAT = 1;
var _TRKLNG = 2;
var _TRKSPD = 3;
var _TRKELE = 4;
var _TRKTYP = 5;
var _TRKZOOM = 6;
var _TRKDIST = 7;
var _TRKEXT = 8;
//
var _GRHAOD = 0; // Graph: Altitude over Distance graph
var _GRHSOD = 1; // Graph: Speed over Distance graph
var _GRHAOT = 2; // Graph: Altitude over Time graph
var _GRHSOT = 3; // Graph: Speed over Time graph
var _GRH_UNKNOW = -1; // Graph: Speed over Time graph
//

var g_curChartType = _GRH_UNKNOW;

var _SUMTST = 0; // Summary:  Track Start Time
var _SUMTET = 1; // Summary:  Track end time.
var _SUMTDN = 2; // Summary:  Track duration. unit=second
var _SUMTTD = 3; // Summary:  Track total distance. unit=meter
var _SUMTAS = 4; // Summary:  Track average speed. unit=km/h
var _SUMTMS = 5; // Summary:  Track maximum Speed. unit=km/h
var _SUMTHA = 6; // Summary:  Track highest altitude. unit=meter
var _SUMTLA = 7; // Summary:  Track lowest altitude.  unit=meter
//
// Track attribute Id declaration:
var _ATTRCOLR = 'color';
var _ATTRRUNR = 'runner';
var _ATTRGRAH = 'graph';
var _ATTRSUMY = 'summary';
var _ATTRTRANS = 'transparent';
//
function setGMarkerZIdx(refGMkr, b) {
	return GOverlay.getZIndex(refGMkr.getPoint().lat())+100;
}

function setGMarkerHigherZIdx(refGMkr, b) {
	return GOverlay.getZIndex(refGMkr.getPoint().lat())+500;
}
//
function CTrack (objMainFrame, strTrkId, strTrkDesc, arywaypts) {
	this.mf = objMainFrame;
	this.id = strTrkId;
	this.desc = strTrkDesc;
	this.curZoomLevel = 0;
	this.waypts = [];
	this.curWyptIdx = 0;
	this.attrs = [
		[_ATTRCOLR, '#ffffff'],
		[_ATTRTRANS, 10],
		[_ATTRRUNR, ''],
		[_ATTRGRAH, []],
		[_ATTRSUMY,[]]
	]; 
	// attributes:  ['color', '#ffff00'],
	//				['runner', 'runnerVar1'], 
	this.objGpl = null; //GPolyLine	
	this.timeCond = 10*1000; //10sec
	this.spaceCond = 0.001;
	
	this.objSelGpl = null; //selected GPolyLine
	this.t1 = -1;
	this.t2 = -1;
	this.gmkr1 = null;
	this.gmkr2 = null;
	
	this.setwaypts = function (aryPts) {
		this.waypts.length = 0;
		this.waypts = cloneArray(aryPts)
	}
    //-------------------------------------------------------------------------
	if (arywaypts != null) {
		this.setwaypts(arywaypts);		
	}
    //-------------------------------------------------------------------------
    this.getWypt = function (nIdx) {
        if (nIdx == null) {
            nIdx = this.curWyptIdx;
        }
        return this.waypts[nIdx];
    }
    //-------------------------------------------------------------------------
    this.Gmap = null;
	this.nMode = 0;
	//-------------------------------------------------------------------------
	this.setAttr = function (strAttr, strValue) {
		for (var i=0; i<this.attrs.length; i++) {
			if (this.attrs[i][0].toLowerCase() == strAttr.toLowerCase()) {
				//var oneAttr = [nStartIdx, nStopIdx, strValue];
				//this.attrs[i][1].attrs.push(oneAttr);
				this.attrs[i][1] = strValue;
			}
		}
	}
	//-------------------------------------------------------------------------
	this.getAttr = function (strAttr) {
		for (var i=0; i<this.attrs.length; i++) {
			if (this.attrs[i][0].toLowerCase() == strAttr.toLowerCase()) {
				return this.attrs[i][1];
			}
		}
		return null;
	}
	//-------------------------------------------------------------------------
	this.CompareFunc = function(a, b) {
		return (a[0] - b[0]);	
	}
	//-------------------------------------------------------------------------
	this.qsearch = function (nStartIdx, nStopIdx, nTimeStamp) {
		if ((nStopIdx-nStartIdx) <= 1) {
			var t1 = Math.abs(this.waypts[nStartIdx][0]-nTimeStamp);
			var t2 = Math.abs(this.waypts[nStopIdx][0]-nTimeStamp);
			return ((t1<t2) ? nStartIdx : nStopIdx);
		}
		var newIdx = nStartIdx + Math.floor((nStopIdx-nStartIdx)/2);
		if (this.waypts[newIdx][0] == nTimeStamp) {
			return newIdx;
		}
		else if (this.waypts[newIdx][0] > nTimeStamp) {
			return this.qsearch(nStartIdx, newIdx, nTimeStamp);
		}
		else {
			return this.qsearch(newIdx, nStopIdx, nTimeStamp);
		}
	}
	//
	this.getNearPtIdx = function(nTimeStamp) {
		if (this.waypts	&& this.waypts.length > 0) {
			var nRetIdx = this.qsearch(0, (this.waypts.length-1), nTimeStamp);
			if (nRetIdx < 0) {
				debugger;
			}
			return nRetIdx; //((nRetIdx >= 0) ? this.waypts[nRetIdx] : null);
		}
		debugger;
	/*
		if (this.waypts && this.waypts.length > 0) {
			var nIdx = -1;
			var retAry = [];
			for (var i=0; i<this.waypts.length; i++) {
				var nDiff = Math.abs(this.waypts[i][0] - nTimeStamp);
				if (nDiff <= this.timeCond) {
					var tmp = [nDiff, i];
					retAry.push(tmp);
				}
			}
			if (retAry.length > 0) {
				retAry.sort(this.CompareFunc);
				return retAry[0][1];
			}		
		}
		return null;
	*/
	}
	//-------------------------------------------------------------------------
	this.getNearLatLngIdx = function(Lat, Lng) {
		if (this.waypts != null && this.waypts.length > 0) {
			var nIdx = -1;
			var retAry = [];
			for (var i=0; i<this.waypts.length; i++) {
				var nDiff = Math.abs(this.waypts[i][1] - Lat);
				nDiff += Math.abs(this.waypts[i][2] - Lng);
				if (nDiff <= this.spaceCond) {
					var tmp = [nDiff, i];
					retAry.push(tmp);
				}
			}
			if (retAry.length > 0) {
				retAry.sort(this.CompareFunc);
				return retAry[0][1];
			}
		}
		return null;
	}	
	//-------------------------------------------------------------------------
	this.setGMapObj = function (obj) {
	    this.Gmap = obj;
	}
	//-------------------------------------------------------------------------
	this.aryRunner = [];
	//-------------------------------------------------------------------------
	this.prepareRunner = function () 
	{
		var runnerInfo = this.getAttr('runner');
        var strRunnerName = runnerInfo[0];
        if (strRunnerName != null) {
			var tmp = [];
			tmp[0] = strRunnerName;
			tmp[1] = [];
            for (var j=0; j<eval(strRunnerName).length; j++) {
                var onefile = eval(strRunnerName+"["+j+"]");
                if (onefile != null) {
                	
               	    var marker_opt = {draggable: false};
               		    	
                    var aniIcon = new GIcon();
                    aniIcon.image = onefile; 
           
//                  aniIcon.iconSize = new GSize(runnerInfo[1], runnerInfo[2]);
//                  aniIcon.iconAnchor = new GPoint(32, 32);
//                  var runner = new GMarker(new GLatLng(0,0), aniIcon, true);
//		//var zzz = GOverlay.getZIndex(runner.getPoint().lat());

			// bug#40905
                    
                    var w = parseInt(runnerInfo[1]);
                    var h = parseInt(runnerInfo[2]);
                    
                    aniIcon.iconSize = new GSize(w, h);     
                    aniIcon.iconAnchor = new GPoint(w / 2, h / 2);  
                    marker_opt.icon = aniIcon;
		    var runner = new GMarker(new GLatLng(0,0), marker_opt);

                    runner.hide();
					tmp[1].push(runner);
			
                    this.Gmap.addOverlay(runner);
                }
            }
            this.aryRunner.push(tmp);
        }
    }
	//-------------------------------------------------------------------------    
    this.getRunner = function (strId) {
        for (var i=0; i<this.aryRunner.length; i++) {
            if (this.aryRunner[i][0] == strId) {
                return this.aryRunner[i][1];
            }
        }
        return null;
    }
	//-------------------------------------------------------------------------
    this.setRunnerHide = function () {
        for (var i=0; i<this.aryRunner.length; i++) {
            for (var j=0; j<this.aryRunner[i][1].length; j++) {
                this.aryRunner[i][1][j].hide();
            }
        }
    }
	//-------------------------------------------------------------------------
    this.setRunningMode = function (nMode) {
        this.nMode = nMode;
    }
    
    
    this.drawRunner_no_move = function(lat, lng)	{
    	if (this.Gmap == null) {
	        return false;
	}
	    var curLat = 0;
	    var curLng = 0;
	    var nextLat = 0;
	    var nextLng = 0;
	    
	    if (lat == null && lng == null) {
	        if (this.waypts.length == 0 || this.curWyptIdx == null || this.curWyptIdx >= this.waypts.length) {
	            //ERROR!
	            // alert("index is exceed the range!");
				return;
	        }
	        curLat = this.waypts[this.curWyptIdx][1];
	        curLng = this.waypts[this.curWyptIdx][2];
	    }
	    else {
	        curLat = lat;
	        curLng = lng;
	    }
	    
		var runnerInfo = this.getAttr('runner');
		var strRunnerName = runnerInfo[0];
		var runner = this.getRunner(strRunnerName);
		
    	    if (runner != null) {
	        var next = this.curWyptIdx + 6;
	        if (next < this.waypts.length) {
	            g_nRunnerDir = GetNextPtDir(curLat, curLng, this.waypts[next][1], this.waypts[next][2], runner.length);
	   	 }
	    }
	    
	    
	    var curPos = new GLatLng(parseFloat(curLat), parseFloat(curLng));
            // this.moveMapByMode(curPos);
            
            g_nRunnerDir = g_nRunnerDir%runner.length; // to avoid not enought runner animations!
            
            // always set to 0
            g_nRunnerDir = 0;		// bug#40882
          
            runner[g_nRunnerDir].setPoint(curPos); //new GLatLng(curLat, curLng));
           
            
            //if (runner[g_nRunnerDir].isHidden()) {
                this.setRunnerHide();
                runner[g_nRunnerDir].show();
            //}  	
    	
    	
	}
    
    
    //-------------------------------------------------------------------------
    this.moveMapByMode = function (objLatLng) {
        // NOTE: objLatLng = new GLatLng(lat, lng);
        
       
        var pp = new GLatLng(objLatLng.lat(), objLatLng.lng());
        
        if (this.nMode == 0) { // Mode 1:
            // check boundary first!
                            
                         
            	var bounds = this.Gmap.getBounds();
		var size = bounds.toSpan();
		var sw = bounds.getSouthWest();
		var ne = bounds.getNorthEast();
		sw = new GLatLng(sw.lat() + size.lat() / 6, sw.lng() + size.lng() / 6);
		ne = new GLatLng(ne.lat() - size.lat() / 6, ne.lng() - size.lng() / 6);
		bounds = new GLatLngBounds(sw, ne);

		
		/*
            var tmpBound = this.Gmap.getBounds();
            var size = tmpBound.toSpan();
	    var sw = tmpBound.getSouthWest();
	    var ne = tmpBound.getNorthEast();
            sw = new GLatLng(sw.lat() + size.lat() / 6, sw.lng() + size.lng() / 6);
	    ne = new GLatLng(ne.lat() - size.lat() / 6, ne.lng() - size.lng() / 6);
	    tmpBound = new GLatLngBounds(sw, ne);
	    */
		
            
	        if (bounds.containsLatLng(pp) == false) { // if not contain inside, move to center!
                	//this.Gmap.panTo(objLatLng);
			//this.Gmap.setCenter(objLatLng);	// bug#652

			this.Gmap.panTo(pp);

	        }
        }
        else if (this.nMode = 1) { // Mode 2:
	        //this.Gmap.setCenter(objLatLng);	// bug#652
			this.Gmap.setCenter(objLatLng);
		}
    
	    
	}
	//-------------------------------------------------------------------------
		
	this.drawRunner = function (lat, lng)
	{
	
	    if (this.Gmap == null) {
	        return false;
	    }
	    var curLat = 0;
	    var curLng = 0;
	    var nextLat = 0;
	    var nextLng = 0;
	    if (lat == null && lng == null) {
	        if (this.waypts.length == 0 || this.curWyptIdx == null || this.curWyptIdx >= this.waypts.length) {
	            //ERROR!
	            // alert("index is exceed the range!");
				return;
	        }
	        curLat = this.waypts[this.curWyptIdx][1];
	        curLng = this.waypts[this.curWyptIdx][2];
	    }
	    else {
	        curLat = lat;
	        curLng = lng;
	    }
		var runnerInfo = this.getAttr('runner');
        var strRunnerName = runnerInfo[0];
        var runner = this.getRunner(strRunnerName);
		
        if (runner != null) {
	        var next = this.curWyptIdx + 6;
	        if (next < this.waypts.length) {
	            g_nRunnerDir = GetNextPtDir(curLat, curLng, this.waypts[next][1], this.waypts[next][2], runner.length);
	        }
	    
	    
	    var curPos = new GLatLng(parseFloat(curLat), parseFloat(curLng));
            this.moveMapByMode(curPos);
            
            g_nRunnerDir = g_nRunnerDir%runner.length; // to avoid not enought runner animations!
            
            // always set to 0
            g_nRunnerDir = 0;		// bug#40882
          
            runner[g_nRunnerDir].setPoint(curPos); //new GLatLng(curLat, curLng));
           
            
            //if (runner[g_nRunnerDir].isHidden()) {
                this.setRunnerHide();
                runner[g_nRunnerDir].show();
            //}
        }
	}    
    	
	//-------------------------------------------------------------------------
	this.drawTrack = function (nZoomLevel) {
		if (this.objGpl == null || (this.objGpl != null && nZoomLevel != this.curZoomLevel)) {
			var tmpLatLngAry = [];
			var tt1 = new Date();
			// original version! all waypoints are add into map!
			//for (var i=0; i<this.waypts.length; i++) {
			//	tmpLatLngAry.push(new GLatLng(this.waypts[i][1], this.waypts[i][2]));
			//}
			// improved version! Only higher level will add into map!
			
			// 2008/08/05 Ryan 
			/*
			for (var i=0; i<this.waypts.length; i++) {
				if (this.waypts[i][_TRKZOOM] >= nZoomLevel) {
					tmpLatLngAry.push(new GLatLng(this.waypts[i][_TRKLAT], this.waypts[i][_TRKLNG]));
				}
			}
			*/
			
			for (var i=0; i<this.waypts.length; i++) {
				if (this.waypts[i][_TRKTYP] >= 1) {
					tmpLatLngAry.push(new GLatLng(this.waypts[i][_TRKLAT], this.waypts[i][_TRKLNG]));
				}
			}			
			
			var tt2 = new Date();
			
			var original_trans = this.getAttr(_ATTRTRANS);
				
			// var opacity = _NOROPT;
			var opacity = parseInt(original_trans) / 10;
			
			var weight = _NORWET;

			
			var curTrk = g_MainFrame.getCurSelTrk();
			if (curTrk != null && curTrk.id == this.id) {
		        	// opacity = _CUROPT;
		        	opacity = (opacity + 0.2);	
		        	if(opacity > 1)	opacity = 1;	        	
		        weight = _CURWET;
			}
			
			
			var tt3 = new Date();
			//if (this.objGpl == null || (this.objGpl != null && opacity != this.objGpl.opacity)) {	
			
			//}
				if (this.objGpl != null) {
					this.Gmap.removeOverlay(this.objGpl);
					this.objGpl = null;
				}
				var strColor = this.getAttr('color');
				this.objGpl = new GPolyline(tmpLatLngAry, strColor, weight, opacity);
				this.Gmap.addOverlay(this.objGpl);

	        // 		if (opacity = 1) {
	        // 		    // current selected track!
	        // 		    this.drawRunner();
	        // 		}
			this.curZoomLevel = nZoomLevel;
			var tt4 = new Date();
			var dt1 = (tt2.getTime() - tt1.getTime());
			var dt2 = (tt3.getTime() - tt2.getTime());
			var dt3 = (tt4.getTime() - tt3.getTime());
		}
	}
	
	this.drawSelection = function (t1, t2, nZoomLevel) {
		if (this.objSelGpl == null || (this.objSelGpl != null && t1 != this.t1 && t2 != this.t2)) {
			if (this.objSelGpl != null) { // remove selection!
				this.Gmap.removeOverlay(this.objSelGpl);
				this.objSelGpl = null;
			}
			if (this.gmkr1 != null) { // remove t1 Gmarker
				this.Gmap.removeOverlay(this.gmkr1);
				this.gmkr1 = null;
			}
			if (this.gmkr2 != null) { // remove t2 Gmarker
				this.Gmap.removeOverlay(this.gmkr2);
				this.gmkr2 = null;
			}				
			if ((t1 < 0 && t2 < 0)) {
				this.t1 = -1;
				this.t2 = -1;
				return;
			}

			var tmpLatLngAry = [];
			// original version! all waypoints are add into map!
			//for (var i=0; i<this.waypts.length; i++) {
			//	tmpLatLngAry.push(new GLatLng(this.waypts[i][1], this.waypts[i][2]));
			//}
			// improved version! Only higher level will add into map!
			var i;
			for (i=0; i<this.waypts.length; i++) {
				if (this.waypts[i][_TRKTMT] >= t1) {
					break;
				}
			}
			for ( ; i<this.waypts.length; i++) {
				if (this.waypts[i][_TRKTMT] > t2) {
					break;
				}
				if (this.waypts[i][_TRKZOOM] >= nZoomLevel) {
					tmpLatLngAry.push(new GLatLng(this.waypts[i][_TRKLAT], this.waypts[i][_TRKLNG]));
				}
			}
			var opacity = _SELOPT;
			var weight = _SELWET;			
			//if (this.objGpl == null || (this.objGpl != null && opacity != this.objGpl.opacity)) {				
			//}
				var strColor = "#FFA0A0"; //this.getAttr('color');
				this.objSelGpl = new GPolyline(tmpLatLngAry, strColor, weight, opacity);
				this.Gmap.addOverlay(this.objSelGpl);
				// add  t1 & t2 Gmarker!
				var baseIcon = new GIcon();
				baseIcon.iconSize=new GSize(32,32);
				baseIcon.shadowSize=new GSize(59,32);
				baseIcon.iconAnchor=new GPoint(16,32);
				baseIcon.infoWindowAnchor=new GPoint(16,0);				
				var iconSelPin = new GIcon(baseIcon, "http://maps.google.com/mapfiles/ms/micons/red-pushpin.png", null, "http://maps.google.com/mapfiles/ms/icons/pushpin_shadow.png");
				this.gmkr1 = new GMarker(new GLatLng(tmpLatLngAry[0].lat(), tmpLatLngAry[0].lng()), {zIndexProcess:setGMarkerHigherZIdx, icon:iconSelPin});
				this.Gmap.addOverlay(this.gmkr1);
				this.gmkr2 = new GMarker(new GLatLng(tmpLatLngAry[tmpLatLngAry.length-1].lat(), tmpLatLngAry[tmpLatLngAry.length-1].lng()), {zIndexProcess:setGMarkerHigherZIdx, icon:iconSelPin});
				this.Gmap.addOverlay(this.gmkr2);				
	        // 		if (opacity = 1) {
	        // 		    // current selected track!
	        // 		    this.drawRunner();
	        // 		}
			this.t1 = t1;
			this.t2 = t2;
		}
	}
    //-------------------------------------------------------------------------
    this.setCurPosIdx = function (nIdx) {
		if (nIdx != null) {
			this.curWyptIdx = nIdx;
		}
    }
    this.getCurPosIdx = function () {
        return this.curWyptIdx;
    }
}
//---------------------------------------------------------------------------



//---------------------------------------------------------------------------
function sortAlbumByTime(a, b) {
	//return a - b; //from smaller to bigger sorting! 
	var a1 = a[_MaTStamp];
	var b1 = b[_MaTStamp];
	var retVal = a1 - b1;
	if (retVal == 0) {
		retVal = a[_MaId].localeCompare(b[_MaId]);
	}
	else {
		if (a1 <= 0 || b1 <= 0) {
			retVal *= (-1);
		}
	}
	return retVal;
}
//---------------------------------------------------------------------------
function CMyAlbum (strTrkId) {
	this.id = strTrkId;
	this.aryItems = [];
	//
	this.resetAry = function () {
		this.aryItems.length = 0;
	}
	//
	this.addItem = function (oneItem) {
		this.aryItems.push(oneItem);
		this.aryItems[this.aryItems.length-1][_MaState] = _EnableVal['enable']; // 
	}
	// 
	this.sortItems = function () {
		this.aryItems.sort(sortAlbumByTime);
	}
	//
	this.retrieveAllImgObj = function () {
		for (var i=0; i<this.aryItems.length; i++) {
			this.retrieveImgObj(i);
		}
	}
	//
	this.retrieveImgObj = function (nIdx) {
		//debugger;
		var onePhoto = this.aryItems[nIdx];
		if (onePhoto != null) {
			if (onePhoto[_MaOri][_sbURLAddr].length > 0 
				&& onePhoto[_MaOri][_sbType] == 'URL'
				&& onePhoto[_MaOri][_sbImgObj] == null) { // only dyna load user photo!
				var imgObj = new Image;
				imgObj.src = onePhoto[_MaOri][_sbURLAddr];
				onePhoto[_MaOri][_sbImgObj] = imgObj;
			}
			if (onePhoto[_MaMid][_sbURLAddr].length > 0 
				&& onePhoto[_MaMid][_sbType] == 'URL'
				&& onePhoto[_MaMid][_sbImgObj] == null) {
				var imgObj = new Image;
				imgObj.src = onePhoto[_MaMid][_sbURLAddr];
				onePhoto[_MaMid][_sbImgObj] = imgObj;
			}
			if (onePhoto[_MaThm][_sbURLAddr].length > 0 
				&& onePhoto[_MaThm][_sbType] == 'URL'
				&& onePhoto[_MaThm][_sbImgObj] == null) {
				var imgObj = new Image;
				imgObj.src = onePhoto[_MaThm][_sbURLAddr];
				onePhoto[_MaThm][_sbImgObj] = imgObj;
			}
		}
	}
	//
	this.getItemBy = function (nFieldIdx, compareObj) {
		var obj = null;
		for (var j=0; j<this.aryItems.length; j++) {
			if (this.aryItems[j][nFieldIdx] == compareObj) {
				obj = this.aryItems[j];
				break;
			}
		}
		return obj;
	}	
	//
	this.getItemById = function (strId) {
		return this.getItemBy(_MaId, strId);
	}
	//
	this.delItemById = function (strId) {
		var obj = null;
		for (var j=0; j<this.aryItems.length; j++) {
			if (this.aryItems[j][_MaId] == strId) {
				obj = this.aryItems.splice(j, 1);
				//obj = this.aryItems[j];
				break;
			}
		}
		return obj;
	}	
	//
	this.getAllItems = function () {
		return this.aryItems;
	}
	//
	this.getIdxById = function (strId) {
		for (var i=0; i<this.aryItems.length; i++) {
			if (this.aryItems[i][_MaId] == strId) {
				return i;
			}
		}
	}
	
	this.getNextItemFromTime = function (timeStamp) {
		var idx = -1;
		for (var i=0; i<this.aryItems.length; i++) {
			var tmpTime = this.aryItems[i][_MaTStamp];
			if (tmpTime >= 0) {
				if (tmpTime >= timeStamp) {
					idx = i;
					break;
				}
			}
			//else { // return the time stamp = -1
			//	idx = i;
			//	break;
			//}
		}
		return {'idx':idx, 'item':((idx>=0) ? this.aryItems[idx] : null)};
	}	
}




//---------------------------------------------------------------------------
var _evtMf_Play = "_PLAY_";
var _evtMf_Pause = "_PAUSE_";
var _evtMf_Resume = "_RESUME_";
var _evtMf_Stop = "_STOP_";
var _evtMf_PrevAlbumEntry = "_PREVIOUS_ALBUM_ENTRY_";
var _evtMf_NextAlbumEntry = "_NEXT_ALBUM_ENTRY_";
var _evtMf_Forward = "_FORWARD_ONE_STEP_";
var _evtMf_Rewind = "_REWIND_ONE_STEP_";
var _evtMf_FF = "_FORWARD_10_STEP_";
var _evtMf_RR = "_REWIND_10_STEP_";
var _evtMf_ThumbPos = "_THUMB_POSITION_";
var _evtMf_SpeedUp = "_SPEED_UP_";
var _evtMf_SpeedDown = "_SPEED_DOWN_";
var _evtMf_SelChgTrack = "_SEL_CHANGE_TRACK_";
var _evtMf_SelChgWaypt = "_SEL_CHANGE_LOCATION_";
var _evtMf_SelChgAlbumEntry = "_SEL_CHANGE_PHOTO_";
var _evtMf_MouseOver = "_MOUSE_MOVE_OVER_";
var _evtMf_MouseOut = "_MOUSE_MOVE_OUT_";
var _evtMf_LeftClick = "_MOUSE_LEFT_CLICK_";
var _evtMf_RightClick = "_MOUSE_RIGHT_CLICK_";
var _evtMf_LeftDbClick = "_MOUSE_LEFT_DOUBLE_CLICK_";
var _evtMf_RightDbClick = "_MOUSE_RIGHT_DOUBLE_CLICK_";
var _evtMf_NavigateHome = "_NAVIGATE_HOME_PAGE_";
var _evtMf_SwitchMode = "_SWITCH_MODE_";
var _evtMf_MarkerMoved = "_GMARKER_MOVED_";
var _evtMf_AlbumChanged = "_ALBUM_CONTENT_CHANGED_";


function CMainFrame (strId) {
	this.id = strId;
	
	this.uniqueIdx = 1;
	//-------------------------------------------------------------------------
	this.getUniqueId = function () {
		return (this.uniqueIdx++);
	}
	
	this.resize = function (w, h) {
		$(this.id).style.height = h+"px";
		$(this.id).style.width = w+"px";
	}



/*	// version1 :
	this.aryUsrAlbum = [];
	//-------------------------------------------------------------------------
	this.resetUsrAlbum = function () {
		this.aryUsrAlbum.length = 0;	
	}
	this.retrieveAllImgObjs = function () {
        for (var i=0; i<this.aryUsrAlbum.length; i++) {
			var onePhoto = this.aryUsrAlbum[i];
			this.retrieveOneImgObj(onePhoto);
		} 
	}
	this.retrieveOneImgObj = function (onePhoto) {
		//debugger;
		if (onePhoto[_MaOri][_sbURLAddr].length > 0 
			&& onePhoto[_MaOri][_sbType] == 'URL'
			&& onePhoto[_MaOri][_sbImgObj] == null) { // only dyna load user photo!
			var imgObj = new Image;
			imgObj.src = onePhoto[_MaOri][_sbURLAddr];
			onePhoto[_MaOri][_sbImgObj] = imgObj;
		}
		if (onePhoto[_MaMid][_sbURLAddr].length > 0 
			&& onePhoto[_MaMid][_sbType] == 'URL'
			&& onePhoto[_MaMid][_sbImgObj] == null) {
			var imgObj = new Image;
			imgObj.src = onePhoto[_MaMid][_sbURLAddr];
			onePhoto[_MaMid][_sbImgObj] = imgObj;
		}
		if (onePhoto[_MaThm][_sbURLAddr].length > 0 
			&& onePhoto[_MaThm][_sbType] == 'URL'
			&& onePhoto[_MaThm][_sbImgObj] == null) {
			var imgObj = new Image;
			imgObj.src = onePhoto[_MaThm][_sbURLAddr];
			onePhoto[_MaThm][_sbImgObj] = imgObj;
		}
	}	
	//-------------------------------------------------------------------------
	this.setUsrAlbum = function (usrDataAry) {
        for (var i=0; i<usrDataAry.length; i++) {
            this.aryUsrAlbum.push(usrDataAry[i]);
			this.aryUsrAlbum[this.aryUsrAlbum.length-1][_MaState] = _EnableVal['enable']; // 1=
        }
		this.retrieveAllImgObjs();
	}
	this.getSpecPhoto = function (curTrkId, curTimeStamp, curLat, curLng) {
		for (var i=0; i<this.aryUsrAlbum.length; i++) {
			if (this.aryUsrAlbum[i][_MaTStamp] == curTimeStamp
				&& this.aryUsrAlbum[i][_MaTrkId] == curTrkId
				&& this.aryUsrAlbum[i][_MaLat] == curLat
				&& this.aryUsrAlbum[i][_MaLng] == curLng) {
				return i;
			}
		}
		return null;
	}
	
	this.getOneAlbumById = function (strId) {
		for (var i=0; i<this.aryUsrAlbum.length; i++) {
			if (this.aryUsrAlbum[i][_MaId] == strId) {
				return this.aryUsrAlbum[i];
			}
		}
		return null;
	}
*/
	//-------------------------------------------------------------------------

	
	// Tracks:
	//-------------------------------------------------------------------------
	this.aryUsrTrack = [];
	this.curSelTrkIdx = 0;
	//-------------------------------------------------------------------------
	this.resetUsrTracks = function () {
		this.aryUsrTrack.length = 0;	
	}
	//-------------------------------------------------------------------------
	this.addOneUsrTrack = function (strTrkId, strDesc, wayptAry) {
		var oneTrk = new CTrack(this, strTrkId, strDesc, wayptAry);
		this.aryUsrTrack.push(oneTrk);
		return oneTrk;
	}
	//-------------------------------------------------------------------------	
    this.sortTrackByTime = function (a, b) {
	    //return a - b; //from smaller to bigger sorting! 
		var retVal = 0;
		if (a.id != b.id) {
			if (a.id == '') {
				return 1;
			}
			if (b.id == '') {
				return -1;
			}
			var a1 = a.waypts[0][_TRKTMT];
			var b1 = b.waypts[0][_TRKTMT];
			var retVal = a1 - b1;
			if (retVal == 0) {
				retVal = a.id.localeCompare(b.id);
			}
		}
		return retVal;
    }	
	//-------------------------------------------------------------------------
	this.setUsrTracks = function (aryTrkInfo) {
	    // add all track!
	    for (var i=0; i<aryTrkInfo.length; i++) {
		    var oneTrk = this.addOneUsrTrack(aryTrkInfo[i][0], aryTrkInfo[i][1], aryTrkInfo[i][2]);
		    if (oneTrk != null) {
		        // cache album's data index which belongs to it.
		        //oneTrk.cacheMaIdx(this.getUsrAlbum());
		        // setup its attributes!
			    for (var j=0; j<aryTrkInfo[i][3].length; j++) {
				    oneTrk.setAttr(aryTrkInfo[i][3][j][0], aryTrkInfo[i][3][j][1]);
			    }
		    }
	    }
		// sort track by its begin dot time!
		this.aryUsrTrack.sort(this.sortTrackByTime);
    }
	//-------------------------------------------------------------------------
	this.getUsrTrack = function (strTrkId) {
		for (var i=0; i<this.aryUsrTrack.length; i++) {
			if (this.aryUsrTrack[i].id == strTrkId) {
				return this.aryUsrTrack[i];
				break;
			}
		}
		return null;
	}
	//-------------------------------------------------------------------------
	this.setCurSelTrk = function (strTrkId) {
		for (var i=0; i<this.aryUsrTrack.length; i++) {
			if (this.aryUsrTrack[i].id == strTrkId) {
				this.curSelTrkIdx = i;
				
				// bug#40882
				this.aryUsrTrack[i].drawRunner();
				__get(CPId).update_progress(0, this.aryUsrTrack[i].waypts.length);			
				 
				// bug#40943
				var status = __get(CPId).nPlayStatus;
				if(status == _cpsPause || status == _cpsStop)	{
					__get(CPId).onCpStop();										
				}
				 
				return true;
				break;
			}
		}
		return false;
	}
	//-------------------------------------------------------------------------
	this.getCurSelTrk = function () {
		if (this.curSelTrkIdx >=0 && this.curSelTrkIdx < this.aryUsrTrack.length) {
			return this.aryUsrTrack[this.curSelTrkIdx];
		}
		return null;	
	}
	//-------------------------------------------------------------------------
	this.getTrackArray = function () {
		return this.aryUsrTrack;
	}
	//-------------------------------------------------------------------------
	this.updateTrk = function () {
		
		for (var i=0; i<this.aryUsrTrack.length; i++) {
						
			var original_trans = this.aryUsrTrack[i].getAttr(_ATTRTRANS);					
						
		  	//var opacity = _NOROPT;
		    	var opacity = parseInt(original_trans) / 10;		    		    
		    var weight = _NORWET;
		    	
		    if (i == this.curSelTrkIdx) {
	            		// opacity = _CUROPT;
	            		opacity = (opacity + 0.2);
	            weight = _CURWET;
	            		if(opacity > 1)	opacity = 1;
		    }		    
			else {
				this.aryUsrTrack[i].setRunnerHide();
			}
			
            if (this.aryUsrTrack[i].objGpl.opacity != opacity || this.aryUsrTrack[i].objGpl.weight != weight) {
                this.aryUsrTrack[i].objGpl.opacity = opacity;
                this.aryUsrTrack[i].objGpl.weight = weight;
                this.aryUsrTrack[i].objGpl.redraw(true);
            }
		}
		
		update_sliderbar();		
		SwitchGraph(g_curChartType);
		__get(SMId).updataSummary();
			
	}
	//
	this.getAllTrackName = function () {
		var aryTrkName = [];
		for (var i=0; i<this.aryUsrTrack.length; i++) {
			aryTrkName.push(this.aryUsrTrack[i].id);
		}
		aryTrkName.push('');
		return aryTrkName;
	}
	//	
	this.getNextTrackFromId = function (curTrkId) {
		var curTrk = null;
		var aryTrks = this.getTrackArray();
		var nTrksCount = aryTrks.length;
		var nNextTrkIdx = -1;
		for (var i=0; i<nTrksCount; i++) {
			if (curTrkId == null) {
				nNextTrkIdx = i;
				break;
			}
			else {
				if (aryTrks[i].id == curTrkId) {
					nNextTrkIdx = (i+1)%nTrksCount;
					break;
				}
			}
		}
		// skip the CMyAlbum object without any album items.
		if (nNextTrkIdx >= 0) {
			for (var i=0; i<nTrksCount; i++) {
				var tmpIdx = (nNextTrkIdx+i)%nTrksCount;
				var nextAlbum = this.getAlbumByTrkId(aryTrks[tmpIdx].id);
				if (nextAlbum != null && nextAlbum.getAllItems().length > 0) {
					curTrk = aryTrks[tmpIdx];
					break;
				}
			}
		}
		return curTrk;
	}
	//
	this.getNextTrackFromTrk = function (curTrk) {
		return this.getNextTrackFromId(((curTrk != null) ? curTrk.id : null)); 
	}
	//
	this.getTrkIdx = function (strTrkId) {
		var nIdx = -1;
		if (strTrkId == null) {
			nIdx = this.curSelTrkIdx;
		}
		else {
			for (var i=0; i<this.aryUsrTrack.length; i++) {
				if (this.aryUsrTrack[i].id == strTrkId) {
					nIdx = i;
					break;
				}
			}
		}
		return nIdx;		
	}
	//-------------------------------------------------------------------------
	
	//-------------------------------------------------------------------------
	// version 2:
	this.aryAllAlbums = [];
	//
	this.resetUsrAlbum = function () {
		for (var i = 0; i<this.aryAllAlbums.length; i++) {
			this.aryAllAlbums[i].resetAry();
		}
		this.aryAllAlbums.length = 0;
	}	
	//
	this.retrieveAllImgObjs = function () {
        for (var i=0; i<this.aryAllAlbums.length; i++) {
			this.aryAllAlbums[i].retrieveAllImgObj();
		} 
	}
	// 
	this.getAlbumByTrkId = function (strTrkId) {
        for (var i=0; i<this.aryAllAlbums.length; i++) {
			if (this.aryAllAlbums[i].id == strTrkId) {
				return this.aryAllAlbums[i];
			}
		}
		var newAlbum = new CMyAlbum(strTrkId);
		this.aryAllAlbums.push(newAlbum);
		return newAlbum;
	}
	//
//	this.sortAlbumByTrkOrder = function (a, b) {
//		var trka = this.getUsrTrack(a.id);
//		var trkb = this.getUsrTrack(b.id);
//		return this.sortTrackByTime(trka, trkb);
//	}
	//
	this.setUsrAlbum = function (usrDataAry) {
        for (var i=0; i<usrDataAry.length; i++) {
			var curAlbum = this.getAlbumByTrkId(usrDataAry[i][_MaTrkId]);
            curAlbum.addItem(usrDataAry[i]);
        }
        for (var i=0; i<this.aryAllAlbums.length; i++) {
			this.aryAllAlbums[i].sortItems();
        }
		// sort album!
		//this.aryAllAlbums.sort(this.sortAlbumByTrkOrder);
		this.retrieveAllImgObjs();
	}
	//
	this.getOneAlbumItemBy = function (nFieldIdx, compareObj) {
		var obj = null;
        for (var i=0; i<this.aryAllAlbums.length && obj == null; i++) {
			obj = this.aryAllAlbums[i].getItemBy(nFieldIdx, compareObj);
		}
		return obj;
	}
	//
	this.getOneAlbumItemById = function (strId) {
		return this.getOneAlbumItemBy(_MaId, strId);
	}	
	this.delOneAlbumItemById = function (strId) {
		var obj = null;
        for (var i=0; i<this.aryAllAlbums.length && obj == null; i++) {
			obj = this.aryAllAlbums[i].delItemById(strId);
		}
		return obj;
	}
	//-------------------------------------------------------------------------
	this.getUsrAlbum = function () {
		return this.aryAllAlbums;
	}
	//-------------------------------------------------------------------------
	this.getTotalAlbumItemCount = function () {
		var nCount = 0;
        for (var i=0; i<this.aryAllAlbums.length; i++) {
			nCount += this.aryAllAlbums[i].length;
		}
		return nCount;
	}
	
	
	this.aryObjs = [];
	this.createObj = function (strAccId, strTagId, ClassName) {
	    var oneObj = new ClassName(strTagId, this);
        if (oneObj != null) {
            var OneEntry = [strAccId, strTagId, oneObj];
            this.aryObjs.push(OneEntry);
            oneObj.initialize();
            return oneObj;
        }	    
        return null;	
	}
	
	this.getObj = function (strAccId) {
	    for (var i=0; i<this.aryObjs.length; i++) {
    	    if (strAccId == this.aryObjs[i][0]) {
    	        return this.aryObjs[i][2];
    	    }
	    }
	    return null;
	}
	
	this.getObjById = function (strId) {
	    for (var i=0; i<this.aryObjs.length; i++) {
    	    if (strId == this.aryObjs[i][2].id) {
    	        return this.aryObjs[i][2];
    	    }
	    }
	    return null;
	}
	

    this.removeObj = function(strAccId) {
	    for (var i=0; i<this.aryObjs.length; i++) {
    	    if (strAccId == this.aryObjs[i][0]) {
    	        return this.aryObjs.splice(i, 1);
    	    }
	    }
	    return null;
    }	
    
	//
	//this.prepareTrackRunner = function () {
	//	for (var i=0; i<this.aryUsrTrack.length; i++) {
	//		this.aryUsrTrack[i].prepareRunner();
	//	}
	//}    
	
	this.aryFuncTable = [
		[_evtMf_Play, []],
		[_evtMf_Pause, []],
		[_evtMf_Resume, []],
		[_evtMf_Stop, []],
		[_evtMf_PrevAlbumEntry, []],
		[_evtMf_NextAlbumEntry, []],
		[_evtMf_Forward, []],
		[_evtMf_Rewind, []],
		[_evtMf_FF, []],
		[_evtMf_RR, []],
		[_evtMf_SpeedUp, []],
		[_evtMf_SpeedDown, []],
		[_evtMf_ThumbPos, []],
		[_evtMf_SelChgTrack, []],
		[_evtMf_SelChgWaypt, []],
		[_evtMf_SelChgAlbumEntry, []],
		[_evtMf_MouseOver, []],
		[_evtMf_MouseOut, []],
		[_evtMf_LeftClick, []],
		[_evtMf_RightClick, []],
		[_evtMf_LeftDbClick, []],
		[_evtMf_RightDbClick, []],
		[_evtMf_NavigateHome, []],
		[_evtMf_SwitchMode, []],
		[_evtMf_MarkerMoved, []],
		[_evtMf_AlbumChanged, []]
	];
	
	//-------------------------------------------------------------------------
	// aryParams[0] = 'caller Id'; aryParams[?] = actual parameters.
	this.executeEvent = function (nEvtIdx, aryParams) {
		if (nEvtIdx >= 0 && nEvtIdx < this.aryFuncTable.length 
		&& this.aryFuncTable[nEvtIdx][1].length > 0) {
			var aryResult = [];
			var strCallerId = aryParams[0];
			for (var i=0; i<this.aryFuncTable[nEvtIdx][1].length; i++) {
				var tmpFuncStruct = this.aryFuncTable[nEvtIdx][1][i];
				// to avoid infinite recursived call!
				if (tmpFuncStruct != null 
				&& tmpFuncStruct[0].toLowerCase() != strCallerId.toLowerCase()) {
					// retAry = ['calledId', 'return value'];
					var result = _Exec(tmpFuncStruct[0], tmpFuncStruct[1], aryParams);
					var retAry = [tmpFuncStruct[0], result];
					aryResult.push(retAry);
				}
			}
			return aryResult;
		}
		return null;
	}

	//-------------------------------------------------------------------------
	// fireUsrEvent( 'caller', 'Event name', 'arguments...');
	this.fireUsrEvent = function () {
		if (arguments.length >= 2) {
		    var params = [];
		    for (var k=0; k<arguments.length; k++) {
		        params.push(arguments[k]);
		    }
			var strCallerId = params.shift();
			var strEvtName = params.shift();
			params.unshift(strCallerId);
			for (var i=0; i<this.aryFuncTable.length; i++) {
				if (strEvtName == this.aryFuncTable[i][0]) {
					return this.executeEvent(i, params);
					break;
				}
			}
		}
		return false;
	}
	
	//-------------------------------------------------------------------------
	this.bindUsrEvent = function (strOwnerId, strEventName, strFuncCbMethod) {
		if (typeof(strFuncCbMethod) != 'string') {
			return false;	
		}
		for (var i=0; i<this.aryFuncTable.length; i++) {
			if (strEventName == this.aryFuncTable[i][0]) {
				var tmpEvtStruct = [strOwnerId, strFuncCbMethod];
				this.aryFuncTable[i][1].push(tmpEvtStruct);
				return true;
				break;
			}
		}
		return false;		
	}
	
	//-------------------------------------------------------------------------
	this.unbindUsrEvent = function (strOwnerId, strEventName) {
		for (var i=0; i<this.aryFuncTable.length; i++) {
			if (strEventName == this.aryFuncTable[i][0]) {
				var bFound = true;
				while (bFound) {
					bFound = false;					
					var tmpEvtAry = this.aryFuncTable[i][1];
					for (var j=0; j<tmpEvtAry.length; j++) {
						if (tmpEvtAry[j][0] == strOwnerId) {
							tmpEvtAry.splice(j, 1);
							bFound = true;
							break;
						}
					}					
				}
				return true;
				break;
			}
		}
		return false;		
	}
	
	

    
}

if (g_MainFrame == null) {
	g_MainFrame = new CMainFrame("myHtmlBody");		
}

function _LogDbgMsgOUT(strMsg) {
	var time1 = new Date();
	var strMyMsg = "<font color=\"#606060\">[" + time1.toLocaleString() + ":" + time1.getMilliseconds() + "] " + strMsg + "</font>";
	var DBGWND = $("DEBUG_MSG_WND");
	if (DBGWND != null) {
		DBGWND.innerHTML += (strMyMsg+"<br />");
		DBGWND.scrollTop = DBGWND.scrollHeight;
	}
}

function _LogDbgMsgIN(strMsg) {
	var time1 = new Date();
	var strMyMsg = "<font color=\"#0000FF\">[" + time1.toLocaleString() + ":" + time1.getMilliseconds() + "] " + strMsg + "</font>";
	var DBGWND = $("DEBUG_MSG_WND");
	if (DBGWND != null) {
		DBGWND.innerHTML += (strMyMsg+"<br />");
		DBGWND.scrollTop = DBGWND.scrollHeight;
	}
}


function toRad(value)	{
	return (value * Math.PI / 180);
}

function cal_distance(lat1, lon1, lat2, lon2)	{

	var R = 6371; // km
	var dLat = toRad((lat2-lat1));
	var dLon = toRad((lon2-lon1)); 
	
	var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(toRad(lat1)) * 
			Math.cos(toRad(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2); 
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
	var d = R * c;
	
	return d;
}


function update_sliderbar()
{
	var curTrk = g_MainFrame.getCurSelTrk();
	var waypoint_count = curTrk.waypts.length;
	var ctrlPanel = __get(CPId);
	ctrlPanel.setupSlideBar(waypoint_count);
}

function m_to_feet(m)
{
	return ( m * 3.280839);	
}

function km_to_mile(km)
{
	return (km * 0.621371);
}


function check_alt(alt, is_km_unit)
{

	var max_alt = 50000; 
	if(is_km_unit)	{
		if(alt >= max_alt)	{
			return 0;
		}
	}
	else	{
		if(alt >= parseInt(m_to_feet(alt)))	{
			return 0;
		}			
	}
	return alt;
}


function make_summary_info()
{
	var is_km_unit = (g_nMeasure == 0) ? true :  false;
	
	var curTrk = g_MainFrame.getCurSelTrk();
	var waypoint_count = curTrk.waypts.length;
	
	if(waypoint_count <= 0)
		return;


	// time, lat, long, alt, speed
	g_summary.start_time = parseInt(curTrk.waypts[0][0]);	
	g_summary.end_time = parseInt(curTrk.waypts[waypoint_count-1][0]);
	g_summary.duration = g_summary.end_time - g_summary.start_time;
	
	var pt0 = curTrk.waypts[0];	

	var st_alt = (pt0[4] > 0) ? parseInt(pt0[4]+0.5) : parseInt(pt0[4]);
	
	pt0.total_distance = 0;
	// pt0.speed = 0;

	pt0.speed = pt0[3];
	if(!is_km_unit)	{
		pt0.speed = parseInt(km_to_mile(pt0.speed));
	}
	else	{
		pt0.speed = parseInt(pt0.speed);
	}				
	
	pt0.time_duration = 0;
	pt0.alt = (is_km_unit) ? st_alt : parseInt(m_to_feet(st_alt));
	pt0.alt = check_alt(pt0.alt, is_km_unit);
	
	// var max_speed = 0;
	var max_speed = pt0.speed;
	
	var highest_alt = (is_km_unit) ? st_alt : parseInt(m_to_feet(st_alt));
	var lowest_alt = (is_km_unit) ? st_alt : parseInt(m_to_feet(st_alt));
	
	highest_alt = check_alt(highest_alt, is_km_unit);
	lowest_alt = check_alt(lowest_alt, is_km_unit);	
	
	
	if(waypoint_count >= 2)	{
		for(var i=1; i<waypoint_count; i++)	{			
			var pt2 = curTrk.waypts[i]
			var pt1 = curTrk.waypts[i-1];				
			pt2.total_distance = cal_distance(pt1[1], pt1[2], pt2[1], pt2[2]);					
			
			if(!is_km_unit)	{
				pt2.total_distance = km_to_mile(pt2.total_distance);
			}
			
			pt2.time_duration = parseInt(pt2[0]) - parseInt(pt1[0]);	
			
			/*
			var speed = 0;
			if(pt2.time_duration > 0)	{
				speed = pt2.total_distance / pt2.time_duration;
			}
			*/			
			pt2.speed = pt2[3];
			
			if(!is_km_unit)	{
				pt2.speed = parseInt(km_to_mile(pt2.speed));
			}
			else	{
				pt2.speed = parseInt(pt2.speed);
			}									
			
			if(pt2.speed > max_speed)	{
				max_speed = pt2.speed;
			}
			
			var alt = (pt2[4] > 0) ? parseInt(pt2[4]+0.5) : parseInt(pt2[4]);		
			alt = (is_km_unit) ? alt : parseInt(m_to_feet(alt));
			
			alt = check_alt(alt, is_km_unit);			
			 
			if(alt >= highest_alt)	{
				highest_alt = alt;		
			}
			
			if(alt <= lowest_alt)	{
				lowest_alt = alt;
			}			
			
			pt2.alt = alt;			
			pt2.total_distance += pt1.total_distance;
			pt2.time_duration += pt1.time_duration;
		}	
	}	
		
	var last_pt = curTrk.waypts[waypoint_count-1]
	g_summary.total_distance = last_pt.total_distance;
	g_summary.max_speed = max_speed;
	g_summary.highest_alt = highest_alt;
	g_summary.lowest_alt = lowest_alt;
				
	if(g_summary.max_speed <= 0)	{
		g_summary.avg_speed = 0;
	}
	else	{
	var avg_s = (g_summary.total_distance / g_summary.duration) * 60 * 60;
	avg_s = avg_s + 0.5;	
	g_summary.avg_speed = parseInt(avg_s);
	}	
		
}