/**
 * LICENCE[[
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1/CeCILL 2.O
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is kelis.fr code.
 *
 * The Initial Developer of the Original Code is 
 * samuel.monsarrat@kelis.fr
 *
 * Portions created by the Initial Developer are Copyright (C) 2008
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * or the CeCILL Licence Version 2.0 (http://www.cecill.info/licences.en.html),
 * in which case the provisions of the GPL, the LGPL or the CeCILL are applicable
 * instead of those above. If you wish to allow use of your version of this file
 * only under the terms of either the GPL, the LGPL or the CeCILL, and not to allow
 * others to use your version of this file under the terms of the MPL, indicate
 * your decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL, the LGPL or the CeCILL. If you do not
 * delete the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL, the LGPL or the CeCILL.
 * ]]LICENCE
 */

/** SCENARI Photo album manager 
 */

var albMgr = {
	fPathAlbFra : null,
	fPathPgeFra : null,
	fMinWidth: null,
	fMinHeight: null,
	fZmMaxFact : null,
	fZmMinFact : 1,
	fZmInc : null,
	fAlbMaxH : null,
	fCurrSsAlb : null,
	fSsOverAlpha : null, 
	fSsDefaultStep : null,
	fStrings : {en:["zoom in","zoom in",                           //0
	            "zoom out","zoom out",                             //2
	            "slide-show","Start slide-show",                   //4
	            "download","download image",                       //6
	            "previous","previous image (left arrow)",          //8
	            "next","next image (right arrow)",                 //10
	            "close","close slide-show (ESC)",                  //12
	            "play","play the slide-show (space)",              //14
	            "pause","pause the slide-show (space)",            //16
	            "This page is currently loading. Please wait.",""]}//18
};

/** albMgr.init - initialize the manager must be called once per page.
 * @pPathAlbFra  : MAND - absolute scPaLib path to find albums.
 * @pPathAlbTi   : OPT -  relative scPaLib path to find the album title. 
 * @pPathPgeFra  : OPT - absolute scPaLib path to page root element (used to set slide-show background mask height).
 * @pPvMinWidth  : OPT - minimum width of preview thumbnails - default = 120px.
 * @pPvMinHeight : OPT - minimum height of preview thumbnails - default = 80px.
 * @pZmMaxFact   : OPT - maximun zoom factor of preview thumbnails - default = 2.
 * @pZmInc       : OPT - preview zoom factor increment - default = 1.
 * @pSsStep      : OPT - slide-show step in seconds - default = 10.
 * @pSsOverAlpha : OPT - opacity of the slide-show mask (masking the page content) - default = 0.9.
 * @pAlbMaxH     : OPT - maximum height of the album (ratio of original height) - default = 0 (no maximum height).
 */
albMgr.init = function(pPathAlbFra, pPathAlbTi, pPathPgeFra, pPvMinWidth, pPvMinHeight, pZmMaxFact, pZmInc, pSsStep, pSsOverAlpha, pAlbMaxH) {
	this.fPathAlbFra = pPathAlbFra;
	this.fPathAlbTi = pPathAlbTi || "chi:div.albTi";
	this.fPathPgeFra = pPathPgeFra || "des:div";
	this.fMinWidth = pPvMinWidth || 120;
	this.fMinHeight = pPvMinHeight || 80;
	this.fZmMaxFact = pZmMaxFact || 2;
	this.fZmInc = pZmInc || 1;
	this.fAlbMaxH = pAlbMaxH || 0;
	this.fNavie6 = scCoLib.isIE && parseFloat(scCoLib.userAgent.substring(scCoLib.userAgent.indexOf("msie")+5)) < 7;
	this.fIsIeQuirks = scCoLib.isIE && document.compatMode == "BackCompat";
	this.fMaxWidth = 2 * this.fMinWidth;
	this.fMaxHeight = 2 *  this.fMinHeight;
	this.fSsDefaultStep = (pSsStep || 10) * 1000;
	this.fSsOverAlpha = pSsOverAlpha || .9;
	scOnLoads[scOnLoads.length] = this;
}
/** albMgr.onLoad - called by the scenari framework, inits the album manager.
 */
albMgr.onLoad = function() {
	scCoLib.util.log("albMgr.onLoad");
	this.fAlbFras = scPaLib.findNodes(this.fPathAlbFra);
	for(var i = 0; i < this.fAlbFras.length; i++) {
		var vAlbFra = this.fAlbFras[i];
		try {
			vAlbFra.fTi = scPaLib.findNode("chi:div.albTi", vAlbFra);
			vAlbFra.fTlb = scPaLib.findNode("chi:div.albTlb", vAlbFra);
			vAlbFra.fCo = scPaLib.findNode("chi:div.albCo", vAlbFra);
			vAlbFra.fBskt = scPaLib.findNode("chi:div.albBskt", vAlbFra);
			vAlbFra.fAncs = scPaLib.findNodes("des:a.aPv", vAlbFra.fCo);
			vAlbFra.fRws = scPaLib.findNodes("des:a.aRw", vAlbFra.fBskt);
			vAlbFra.fZmActive = vAlbFra.fAncs[0] && vAlbFra.fAncs[0].className.indexOf("aPvS") == -1 && vAlbFra.fAncs[0].className.indexOf("aPvL") == -1;
			
			// Init anchors & images
			for(var j = 0; j < vAlbFra.fAncs.length; j++) {
				var vAnc = vAlbFra.fAncs[j];
				vAnc.fSsUri = vAnc.href;
				vAnc.fIdx = j;
				vAnc.href = "#";
				vAnc.target = "_self";
				vAnc.fName="aPv";
				if(!scCoLib.isIE) vAnc.style.display = "table-cell";
				vAnc.onclick=function(){return albMgr.xBtnMgr(this);}
				vAnc.fImg = scPaLib.findNode("des:img.imgPv", vAnc);
				vAnc.fImg.fBaseWidth = albMgr.xInt(albMgr.xReadStyle(vAnc.fImg,"width"));
				vAnc.fImg.fBaseHeight = albMgr.xInt(albMgr.xReadStyle(vAnc.fImg,"height"));
				vAnc.fImg.fBaseBorder = albMgr.xInt(albMgr.xReadStyle(vAnc.fImg,"borderTopWidth"));
				vAnc.fAlbFra = vAlbFra;
			}
			// Init Container
			if (this.fAlbMaxH > 0){
				vAlbFra.fCo.style.maxHeight = albMgr.xInt(albMgr.xReadStyle(vAlbFra.fCo,"height"))*this.fAlbMaxH+"px";
				vAlbFra.fCo.style.overflow = "auto";
			}

			// Init SlideShow elements
			this.xInitSs(vAlbFra);

			// Init Toolbar
			this.xInitToolBar(vAlbFra);
			
			vAlbFra.fZmFact = albMgr.fZmMinFact;
			vAlbFra.fSsStep = albMgr.fSsDefaultStep;
			
	} catch(e){
			scCoLib.util.logError("albMgr.onLoad::Error", e);
		}
	}
}
/** albMgr.loading -.
 */
albMgr.loading = function() {
	alert(albMgr.xGetStr(18));
}

/* ================== Album manager =====================*/
albMgr.xInitToolBar = function(pAlbFra) {
	scCoLib.util.log("albMgr.xInitToolBar");
	
	if (pAlbFra.fZmActive){
		pAlbFra.fZmBtnIn = albMgr.xAddBtn(pAlbFra.fTlb,pAlbFra,"albZmBtnIn",albMgr.xGetStr(0),albMgr.xGetStr(1));
		albMgr.xAddSep(pAlbFra.fTlb);
	
		pAlbFra.fZmBtnOut = albMgr.xAddBtn(pAlbFra.fTlb,pAlbFra,"albZmBtnNoOut",albMgr.xGetStr(2),albMgr.xGetStr(3));
		albMgr.xAddSep(pAlbFra.fTlb);
	}
	albMgr.xAddBtn(pAlbFra.fTlb,pAlbFra,"albSsStart",albMgr.xGetStr(4),albMgr.xGetStr(5));
	
	var vTbrClr = document.createElement("div");
	vTbrClr.className = "albClr";
	pAlbFra.fTlb.appendChild(vTbrClr);
}
albMgr.xZmIn = function(pAlbFra) {
	scCoLib.util.log("albMgr.xZmIn");
	pAlbFra.fZmFact = Math.min(albMgr.fZmMaxFact, pAlbFra.fZmFact + albMgr.fZmInc);
	albMgr.xResize(pAlbFra);
}
albMgr.xZmOut = function(pAlbFra) {
	scCoLib.util.log("albMgr.xZmOut");
	pAlbFra.fZmFact = Math.max(albMgr.fZmMinFact, pAlbFra.fZmFact - albMgr.fZmInc);
	albMgr.xResize(pAlbFra);
}
albMgr.xResize = function(pAlbFra) {
	for(var i = 0; i < pAlbFra.fAncs.length; i++) {
		var vAnc = pAlbFra.fAncs[i];
		vAnc.style.width = Math.round(2 * vAnc.fImg.fBaseBorder + albMgr.fMinWidth * pAlbFra.fZmFact)+"px";
		vAnc.style.height = Math.round(2 * vAnc.fImg.fBaseBorder +  albMgr.fMinHeight * pAlbFra.fZmFact)+"px";
		vAnc.fImg.width = Math.round(vAnc.fImg.fBaseWidth * pAlbFra.fZmFact);
		vAnc.fImg.height = Math.round(vAnc.fImg.fBaseHeight * pAlbFra.fZmFact);
	}
	var vHasZmOut = pAlbFra.fZmFact > albMgr.fZmMinFact;
	var vHasZmIn = pAlbFra.fZmFact < albMgr.fZmMaxFact;
	albMgr.xSwitchClass(pAlbFra.fZmBtnOut,(vHasZmOut?"albZmBtnNoOut":"albZmBtnOut"),(vHasZmOut?"albZmBtnOut":"albZmBtnNoOut"));
	albMgr.xSwitchClass(pAlbFra.fZmBtnIn,(vHasZmIn?"albZmBtnNoIn":"albZmBtnIn"),(vHasZmIn?"albZmBtnIn":"albZmBtnNoIn"));
}

/* ================== Slide-show manager =====================*/
albMgr.xSsStart = function(pAlbFra) {
	scCoLib.util.log("albMgr.xSsStart");
	albMgr.xOpenSs(pAlbFra,pAlbFra.fAncs[0]);
	albMgr.xPlySs(pAlbFra);
}
albMgr.xInitSs = function(pAlbFra) {
	scCoLib.util.log("albMgr.xInitSs");
	pAlbFra.fSsOver = albMgr.xAddEltNoDisp("div",document.body,"albSsOver");
	pAlbFra.fSsFra = albMgr.xAddEltNoDisp("div",document.body,"albSsFra");
	if(this.fNavie6 && this.xReadStyle(pAlbFra.fSsFra,"position") == "fixed") pAlbFra.fSsFra.style.position = "absolute"; // IE6 does not display fixed content properly.
	
	pAlbFra.fSsCo = albMgr.xAddElt("div",pAlbFra.fSsFra,"albSsCo");
	pAlbFra.fSsImgFras = [];
	for(var i = 0; i < pAlbFra.fAncs.length; i++) {
		pAlbFra.fSsImgFras[i] = albMgr.xAddEltHidden("div",pAlbFra.fSsCo,"albSsImgFra");
		pAlbFra.fSsImgFras[i].fImg = albMgr.xAddElt("img",pAlbFra.fSsImgFras[i],null);
		pAlbFra.fSsImgFras[i].fImg.setAttribute("alt",pAlbFra.fAncs[i].title ? pAlbFra.fAncs[i].title : "");
	}	
	pAlbFra.fSsTbr = albMgr.xAddElt("div",pAlbFra.fSsFra,"albSsTbr")
	pAlbFra.fSsTi = albMgr.xAddElt("div",pAlbFra.fSsTbr,"albSsTi")
	pAlbFra.fSsBtnDwn = albMgr.xAddBtn(pAlbFra.fSsTbr,pAlbFra,"albSsBtnDwn",albMgr.xGetStr(6),albMgr.xGetStr(7),true);
	pAlbFra.fSsBtnDwn.target="_blank";
	albMgr.xAddSep(pAlbFra.fSsTbr);
	pAlbFra.fSsBtnPrv = albMgr.xAddBtn(pAlbFra.fSsTbr,pAlbFra,"albSsBtnPrv",albMgr.xGetStr(8),albMgr.xGetStr(9));
	albMgr.xAddSep(pAlbFra.fSsTbr);
	pAlbFra.fSsBtnPly = albMgr.xAddBtn(pAlbFra.fSsTbr,pAlbFra,"albSsBtnPly",albMgr.xGetStr(14),albMgr.xGetStr(15));
	pAlbFra.fSsBtnPse = albMgr.xAddBtn(pAlbFra.fSsTbr,pAlbFra,"albSsBtnPse",albMgr.xGetStr(16),albMgr.xGetStr(17));
	pAlbFra.fSsBtnPse.style.display = "none";
	albMgr.xAddSep(pAlbFra.fSsTbr);
	pAlbFra.fSsBtnNxt = albMgr.xAddBtn(pAlbFra.fSsTbr,pAlbFra,"albSsBtnNxt",albMgr.xGetStr(10),albMgr.xGetStr(11));
	albMgr.xAddSep(pAlbFra.fSsTbr);
	pAlbFra.fSsBtnCls = albMgr.xAddBtn(pAlbFra.fSsTbr,pAlbFra,"albSsBtnCls",albMgr.xGetStr(12),albMgr.xGetStr(13));
	albMgr.xAddSep(pAlbFra.fSsTbr);
	pAlbFra.fSsCount = albMgr.xAddElt("span",pAlbFra.fSsTbr,"albSsCount")
}
albMgr.xOpenSs = function(pAlbFra,pAnc) {
	scCoLib.util.log("albMgr.xOpenSs");
	if(this.xReadStyle(pAlbFra.fSsFra,"position") == "absolute") window.scroll(0,0); // if position:absolute, we must scroll the SS into view.
	albMgr.startSsTask.initTask(pAlbFra);
	scTiLib.addTaskNow(albMgr.startSsTask);
	albMgr.xUdtSs(pAlbFra,pAnc);
	albMgr.fCurrSsAlb = pAlbFra;
	pAlbFra.fKeyUpOld = document.onkeyup;
	document.onkeyup = albMgr.xKeyMgr;
}
albMgr.xUdtSs = function(pAlbFra,pNewAnc) {
	pAlbFra.fSsHasPrv = pNewAnc.fIdx != 0;
	pAlbFra.fSsHasNxt = pNewAnc.fIdx != pAlbFra.fAncs.length - 1;
	if(!pAlbFra.fSsImgFras[pNewAnc.fIdx].fImg.src) pAlbFra.fSsImgFras[pNewAnc.fIdx].fImg.setAttribute("src", pNewAnc.fSsUri);
	if (pAlbFra.fSsHasNxt){
		pAlbFra.fNxtSsAnc = pAlbFra.fAncs[Math.min(pNewAnc.fIdx + 1,pAlbFra.fAncs.length - 1)];
		if(!pAlbFra.fSsImgFras[pAlbFra.fNxtSsAnc.fIdx].fImg.src) pAlbFra.fSsImgFras[pAlbFra.fNxtSsAnc.fIdx].fImg.setAttribute("src", pAlbFra.fNxtSsAnc.fSsUri);
	} else if(pAlbFra.fSsAutoPly) albMgr.xPseSs(pAlbFra);
	if (pAlbFra.fSsHasPrv){
		pAlbFra.fPrvSsAnc = pAlbFra.fAncs[Math.max(pNewAnc.fIdx - 1,0)];
		if(!pAlbFra.fSsImgFras[pAlbFra.fPrvSsAnc.fIdx].fImg.src) pAlbFra.fSsImgFras[pAlbFra.fPrvSsAnc.fIdx].fImg.setAttribute("src", pAlbFra.fPrvSsAnc.fSsUri);
	}
	pAlbFra.fSsTi.innerHTML = (pNewAnc.title ? pNewAnc.title : "");
	pAlbFra.fSsCount.innerHTML = (pNewAnc.fIdx+1)+"/"+pAlbFra.fAncs.length;
	if (pAlbFra.fRws && pAlbFra.fRws[pNewAnc.fIdx]) {
		pAlbFra.fSsBtnDwn.href = pAlbFra.fRws[pNewAnc.fIdx].href;
		albMgr.xSwitchClass(pAlbFra.fSsBtnDwn,"albSsBtnNoDwn","albSsBtnDwn");
	} else {
		albMgr.xSwitchClass(pAlbFra.fSsBtnDwn,"albSsBtnDwn","albSsBtnNoDwn");
	}
	albMgr.xSwitchClass(pAlbFra.fSsBtnPrv,(pAlbFra.fSsHasPrv?"albSsBtnNoPrv":"albSsBtnPrv"),(pAlbFra.fSsHasPrv?"albSsBtnPrv":"albSsBtnNoPrv"));
	albMgr.xSwitchClass(pAlbFra.fSsBtnNxt,(pAlbFra.fSsHasNxt?"albSsBtnNoNxt":"albSsBtnNxt"),(pAlbFra.fSsHasNxt?"albSsBtnNxt":"albSsBtnNoNxt"));

	albMgr.switchSsTask.initTask(pAlbFra,pNewAnc);
	scTiLib.addTaskNow(albMgr.switchSsTask);
}
albMgr.xNxtSs = function(pAlbFra) {
	scCoLib.util.log("albMgr.xNxtSs");
	if (!pAlbFra.fSsHasNxt) return;
	albMgr.xUdtSs(pAlbFra,pAlbFra.fNxtSsAnc);
}
albMgr.xPrvSs = function(pAlbFra) {
	scCoLib.util.log("albMgr.xPrvSs");
	if (!pAlbFra.fSsHasPrv) return;
	albMgr.xUdtSs(pAlbFra,pAlbFra.fPrvSsAnc);
}
albMgr.xClsSs = function(pAlbFra) {
	scCoLib.util.log("albMgr.xClsSs");
	albMgr.stopSsTask.initTask(pAlbFra);
	scTiLib.addTaskNow(albMgr.stopSsTask);
	document.onkeyup = pAlbFra.fKeyUpOld;
	pAlbFra.fSsAutoPly = false;
	albMgr.fCurrSsAlb = null;
}
albMgr.xPlySs = function(pAlbFra) {
	scCoLib.util.log("albMgr.xPlySs");
	pAlbFra.fSsAutoPly = true;
	pAlbFra.fSsBtnPly.style.display="none";
	pAlbFra.fSsBtnPse.style.display="";
	if (!pAlbFra.fSsHasNxt) albMgr.xUdtSs(pAlbFra,pAlbFra.fAncs[0]);
	pAlbFra.fNxtSsProc = window.setTimeout(albMgr.xAutoSs, pAlbFra.fSsStep);
}
albMgr.xPseSs = function(pAlbFra) {
	scCoLib.util.log("albMgr.xPseSs");
	pAlbFra.fSsAutoPly = false;
	pAlbFra.fSsBtnPly.style.display="";
	pAlbFra.fSsBtnPse.style.display="none";
	pAlbFra.fNxtSsProc = -1;
}
albMgr.xAutoSs = function() {
	scCoLib.util.log("albMgr.xAutoSs");
	if (albMgr.fCurrSsAlb){
		if (albMgr.fCurrSsAlb.fSsAutoPly){
			albMgr.xNxtSs(albMgr.fCurrSsAlb);
			albMgr.fCurrSsAlb.fNxtSsProc = window.setTimeout(albMgr.xAutoSs, albMgr.fCurrSsAlb.fSsStep);
		}
	}
}
/* ================== tasks =====================*/
albMgr.startSsTask = {
	fIdx: -1,
	fRate: [.1, .2, .3, .4, .5, .6, .7, .8, .9],
	execTask : function(){
		while(this.fEndTime < (Date.now ? Date.now() : new Date().getTime()) && this.fIdx < this.fRate.length) {
			this.fIdx++;
			this.fEndTime += 100;
		}
		this.fIdx++;
		this.fEndTime += 100;
		if(this.fIdx >= this.fRate.length) {
			this.setOpacity(this.fAlbFra.fSsOver,albMgr.fSsOverAlpha);
			this.resetOpacity(this.fAlbFra.fSsFra);
			return false;
		}
		this.setOpacity(this.fAlbFra.fSsOver, Math.min(this.fRate[this.fIdx], albMgr.fSsOverAlpha));
		this.setOpacity(this.fAlbFra.fSsFra, this.fRate[this.fIdx]);
		return true;
	},
	setOpacity: function(pNode, pRate){
		if(scCoLib.isIE) pNode.style.filter = "Alpha(opacity="+pRate*100+")";
		else pNode.style.opacity = pRate;
	},
	resetOpacity: function(pNode){
		if(scCoLib.isIE) pNode.style.filter = "Alpha(opacity=100)";
		else pNode.style.opacity = "1";
	},
	terminate : function(){
		this.fIdx = this.fRate.length;
		this.execTask();
	},
	initTask : function(pAlbFra){
		scCoLib.util.log("startSsTask.initTask");
		this.fAlbFra = pAlbFra;
		this.fEndTime = ( Date.now  ? Date.now() : new Date().getTime() ) + 100;
		this.setOpacity(this.fAlbFra.fSsOver, .0);
		this.setOpacity(this.fAlbFra.fSsFra, .0);
		this.fAlbFra.fSsOver.style.display = "";
		this.fAlbFra.fSsOver.style.height = Math.max(albMgr.xPageHeight(),albMgr.xClientHeight())+"px";
		this.fAlbFra.fSsFra.style.display = "";
		this.fIdx = -1;
	}
}
albMgr.stopSsTask = {
	fIdx: -1,
	fRate: [.8, .6, .4, .3, .2, .1],
	execTask : function(){
		while(this.fEndTime < (Date.now ? Date.now() : new Date().getTime()) && this.fIdx < this.fRate.length) {
			this.fIdx++;
			this.fEndTime += 100;
		}
		this.fIdx++;
		this.fEndTime += 100;
		if(this.fIdx >= this.fRate.length) {
			this.resetOpacity(this.fAlbFra.fSsOver);
			this.resetOpacity(this.fAlbFra.fSsFra);
			this.fAlbFra.fSsOver.style.display = "none";
			this.fAlbFra.fSsFra.style.display = "none";
			if (this.fAlbFra.fCurrSsAnc) this.setOpacity(this.fAlbFra.fSsImgFras[this.fAlbFra.fCurrSsAnc.fIdx],0);
			if (this.fAlbFra.fCurrSsAnc) this.fAlbFra.fSsImgFras[this.fAlbFra.fCurrSsAnc.fIdx].style.visibility = "hidden";
			return false;
		}
		this.setOpacity(this.fAlbFra.fSsOver, Math.min(this.fRate[this.fIdx], albMgr.fSsOverAlpha));
		this.setOpacity(this.fAlbFra.fSsFra, this.fRate[this.fIdx]);
		return true;
	},
	setOpacity: function(pNode, pRate){
		if(scCoLib.isIE) pNode.style.filter = "Alpha(opacity="+pRate*100+")";
		else pNode.style.opacity = pRate;
	},
	resetOpacity: function(pNode){
		if(scCoLib.isIE) pNode.style.filter = "Alpha(opacity=0)";
		else pNode.style.opacity = "0";
	},
	terminate : function(){
		this.fIdx = this.fRate.length;
		this.execTask();
	},
	initTask : function(pAlbFra){
		scCoLib.util.log("stopSsTask.initTask");
		this.fAlbFra = pAlbFra;
		this.fEndTime = ( Date.now  ? Date.now() : new Date().getTime() ) + 100;
		this.fIdx = -1;
	}
}
albMgr.switchSsTask = {
	fIdx: -1,
	fRateOld: [.9, .8, .7, .6, .5, .4, .3, .2, .1],
	fRateNew: [.1, .2, .3, .4, .5, .6, .7, .8, .9],
	execTask : function(){
		while(this.fEndTime < (Date.now ? Date.now() : new Date().getTime()) && this.fIdx < this.fRateOld.length) {
			this.fIdx++;
			this.fEndTime += 100;
		}
		this.fIdx++;
		this.fEndTime += 100;
		if(this.fIdx >= this.fRateOld.length) {
			if (this.fAlbFra.fCurrSsAnc) this.setOpacity(this.fAlbFra.fSsImgFras[this.fAlbFra.fCurrSsAnc.fIdx],0);
			if (this.fAlbFra.fCurrSsAnc && this.fAlbFra.fCurrSsAnc.fIdx != this.fNewAnc.fIdx) this.fAlbFra.fSsImgFras[this.fAlbFra.fCurrSsAnc.fIdx].style.visibility = "hidden";
			this.setOpacity(this.fAlbFra.fSsImgFras[this.fNewAnc.fIdx],1);
			this.fAlbFra.fCurrSsAnc = this.fNewAnc;
			this.fIsRunning = false;
			return false;
		}
		if (this.fAlbFra.fCurrSsAnc) this.setOpacity(this.fAlbFra.fSsImgFras[this.fAlbFra.fCurrSsAnc.fIdx], this.fRateOld[this.fIdx]);
		this.setOpacity(this.fAlbFra.fSsImgFras[this.fNewAnc.fIdx], this.fRateNew[this.fIdx]);
		return true;
	},
	setOpacity: function(pNode, pRate){
		if(scCoLib.isIE) pNode.style.filter = "Alpha(opacity="+pRate*100+")";
		else pNode.style.opacity = pRate;
	},
	terminate : function(){
		this.fIdx = this.fRateOld.length;
		this.execTask();
	},
	initTask : function(pAlbFra,pNewAnc){
		scCoLib.util.log("switchSsTask.initTask");
		this.fAlbFra = pAlbFra;
		if (this.fIsRunning) this.terminate();
		this.fNewAnc = pNewAnc;
		this.setOpacity(this.fAlbFra.fSsImgFras[this.fNewAnc.fIdx],0);
		this.fAlbFra.fSsImgFras[this.fNewAnc.fIdx].style.visibility = "";
		
		this.fEndTime = ( Date.now  ? Date.now() : new Date().getTime() ) + 100;
		this.fIdx = -1;
		this.fIsRunning = true;
	}
}
albMgr.nxtSsTask = {
}
/* ================== managers =====================*/
albMgr.xBtnMgr = function(pBtn) {
	scCoLib.util.log("albMgr.xBtnMgr");
	var vAlbFra = pBtn.fAlbFra;
	switch(pBtn.fName){
		case "aPv":
			albMgr.xOpenSs(vAlbFra,pBtn);break;
		case "albZmBtnIn":
			albMgr.xZmIn(vAlbFra);break;
		case "albZmBtnNoOut":
			albMgr.xZmOut(vAlbFra);break;
		case "albSsStart":
			albMgr.xSsStart(vAlbFra);break;
		case "albSsBtnPrv":
			if (albMgr.fCurrSsAlb.fSsAutoPly) albMgr.xPseSs(vAlbFra);
			albMgr.xPrvSs(vAlbFra);break;
		case "albSsBtnNxt":
			if (albMgr.fCurrSsAlb.fSsAutoPly) albMgr.xPseSs(vAlbFra);
			albMgr.xNxtSs(vAlbFra);break;
		case "albSsBtnCls":
			albMgr.xClsSs(vAlbFra);break;
		case "albSsBtnPly":
			albMgr.xPlySs(vAlbFra);break;
		case "albSsBtnPse":
			albMgr.xPseSs(vAlbFra);break;
	}
	return false;
}
albMgr.xKeyMgr = function(pEvent){
	var vEvent = pEvent || window.event;
	var vCharCode = vEvent.which || vEvent.keyCode;
	scCoLib.util.log("albMgr.xKeyMgr: "+vCharCode);
	if (!albMgr.fCurrSsAlb) return;
	switch(vCharCode){
		case 34://pg_dwn
		case 39://left
			if (albMgr.fCurrSsAlb.fSsAutoPly) albMgr.xPseSs(albMgr.fCurrSsAlb);
			albMgr.xNxtSs(albMgr.fCurrSsAlb);
			return false;
		case 8://bksp
		case 33://pg_up
		case 37://right
			if (albMgr.fCurrSsAlb.fSsAutoPly) albMgr.xPseSs(albMgr.fCurrSsAlb);
			albMgr.xPrvSs(albMgr.fCurrSsAlb);
			return false;
		case 27://escape
			albMgr.xClsSs(albMgr.fCurrSsAlb);
			return false;
		case 32://space
		case 80:// p
			if(albMgr.fCurrSsAlb.fSsAutoPly) albMgr.xPseSs(albMgr.fCurrSsAlb);
			else albMgr.xPlySs(albMgr.fCurrSsAlb);
	}
}

/* ================== toolbox =====================*/
/** albMgr.xReadStyle : cross-browser css rule reader
 */
albMgr.xReadStyle = function(pElt, pProp) {
	if (pElt.style[pProp]) {
		return pElt.style[pProp];
	} else if (pElt.currentStyle) {
		return pElt.currentStyle[pProp];
	} else if (document.defaultView && document.defaultView.getComputedStyle) {
		var vStyle = document.defaultView.getComputedStyle(pElt, null);
		if (vStyle[pProp]) return vStyle[pProp];
		else return vStyle.getPropertyValue(pProp);
	} else {
		return null
	}
}
/** albMgr.xPageHeight.
 */
albMgr.xPageHeight = function() {
	if (albMgr.fPathPgeFra){
		var vPgeFra = scPaLib.findNode(albMgr.fPathPgeFra);
		if(vPgeFra){
			if(vPgeFra.offsetHeight) return vPgeFra.offsetHeight;
			else if(vPgeFra.clientHeight) return vPgeFra.clientHeight;
		}	
	}
}
/** albMgr.xClientHeight.
 */
albMgr.xClientHeight = function() {
	if (window.innerHeight >= 0) {
		return window.innerHeight;
	} else if (document.documentElement) {
		return document.documentElement.clientHeight;
	} else if (document.body.clientHeight >= 0) {
		return document.body.clientHeight;
	} else {
		return 0;
	}
}
/** albMgr.xInt : parseInt that always returns 0 if not an int.
 */
albMgr.xInt = function(pVar){
	var vRet;
	return isNaN(vRet = parseInt(pVar))? 0 : vRet;
}
/** albMgr.xAddSep : Add a simple textual separator : " | ".
 */
albMgr.xAddSep = function(pParent){
	var vSep = document.createElement("span");
	vSep.className = "albSep";
	vSep.innerHTML = " | "
	pParent.appendChild(vSep);
}
/** albMgr.xAddElt : Add an HTML element to a parent node.
 */
albMgr.xAddElt = function(pName,pParent,pClassName,pNoDisplay,pHidden){
	var vElt = document.createElement(pName);
	if (pClassName) vElt.className = pClassName;
	if (pNoDisplay) vElt.style.display = "none";
	if (pHidden) vElt.style.visibility = "hidden";
	pParent.appendChild(vElt);
	return vElt;
}
/** albMgr.xAddEltNoDisp : Add a non displayed HTML element to a parent node.
 */
albMgr.xAddEltNoDisp = function(pName,pParent,pClassName){
	var vElt = albMgr.xAddElt(pName,pParent,pClassName,true,false);
	return vElt;
}
/** albMgr.xAddEltHidden : Add a hidden HTML element to a parent node.
 */
albMgr.xAddEltHidden = function(pName,pParent,pClassName){
	var vElt = albMgr.xAddElt(pName,pParent,pClassName,false,true);
	return vElt;
}
/** albMgr.xAddBtn : Add a HTML button to a parent node.
 */
albMgr.xAddBtn = function(pParent,pAlbFra,pClassName,pCapt,pTitle,pNoCmd){
	var vBtn = document.createElement("a");
	vBtn.className = pClassName;
	vBtn.fName = pClassName;
	vBtn.href = "#";
	vBtn.target = "_self";
	if (!pNoCmd) vBtn.onclick=function(){return albMgr.xBtnMgr(this);}
	vBtn.setAttribute("title",pTitle);
	vBtn.innerHTML="<span>"+pCapt+"</span>"
	vBtn.fAlbFra = pAlbFra;
	pParent.appendChild(vBtn);
	return vBtn;
}
/** albMgr.xGetStr : Reteive a localized string.
 */
albMgr.xGetStr = function(pStrId) {
	var vLang = navigator.userLanguage || navigator.language;
	vLang = vLang.slice(0,2).toLowerCase();
	if (this.fStrings[vLang])	return this.fStrings[vLang][pStrId];
	else return this.fStrings["en"][pStrId];
}
/** albMgr.xSwitchClass : Replace a CSS class.
 */
albMgr.xSwitchClass = function(pNode, pClassOld, pClassNew) {
	if (pClassOld && pClassOld != '') {
		var vCurrentClasses = pNode.className.split(' ');
		var vNewClasses = new Array();
		var vClassFound = false;
		for (var i = 0, n = vCurrentClasses.length; i < n; i++) {
			if (vCurrentClasses[i] != pClassOld) {
				vNewClasses.push(vCurrentClasses[i]);
			} else {
				if (pClassNew && pClassNew != '') vNewClasses.push(pClassNew);
				vClassFound = true;
			}
		}
		pNode.className = vNewClasses.join(' ');
	}
}


