	// general utils
	function getPixelValue(attr){
		
		attr=(attr+'').toLowerCase();
		var i=attr.indexOf('px');
		if(i>0){
			return parseInt(attr.substring(0,i));
		}else{		
			return parseInt(attr);
		}
	}
	function resolveInclude(include){
		bb.command.load(include.getAttribute('href'),'GET',null,null,include,'replace');
	}
	function resolveAllIncludes(){
		var incls=bb.evaluate('//include',document);	
		//alert(incls.length);
		for(var i=0;i<incls.length;i++){
			resolveInclude(incls[i]);	
		}
	}
	// generic string operations
	function isEmptyString(str){
		return str==null || bb.string.normalize(str).length<=0;
	}
	function trimString(str){
		if(str==null){
			return null;	
		}
		return bb.string.normalize(str);	
	}
	function parseNumber(str,defaultNumber){
		str=trimString(str);
		if(str==null){
			return defaultNumber;	
		}
		return bb.string.parseIntToDecimal(str,defaultNumber);
	}
	// general css operations
	function hasClass(ele,cls) {
		return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
	}
	function addClass(ele,cls) {
		if (!this.hasClass(ele,cls)) ele.className += " "+cls;
	}
	function removeClass(ele,cls) {
		if (hasClass(ele,cls)) {
			var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
			ele.className=ele.className.replace(reg,' ');
		}
	}
	// general DOM node operations
	function getInnerHTML(ele){
		var html='';
		var node=ele.firstChild;
		while(node!=null){
			html+=bb.xml.serialize(node);
			node=node.nextSibling;	
		}
		return html;
	}
		
	// loading message operations
	var loadingCount=0;
	function hideLoading(){
		loadingCount--;
		var loading=bb.document.getElementById('loadingMessage');
		if(loading!=null && loadingCount<=0){
			loading.hide();		
		}
	}
	
	function showLoading(){
		loadingCount++;		
		var loading=bb.document.getElementById('loadingMessage');
		if(loading!=null){
			loading.show();		
		};	
	}
	function forceHideLoading(){
		loadingCount--;
		var loading=bb.document.getElementById('loadingMessage');
		if(loading!=null){
			loading.hide();		
		}
	}
		
	// tool bar operatins
	function toolBarItemHover(td){
		if(!hasClass(td,'selected')){
			addClass(td,'hover');
		}

		
	}
	function toolBarItemNormal(td){
		if(!hasClass(td,'selected')){
			removeClass(td,'hover');
		}
	}
	function toolBarItemSelected(td){
		var index=parseInt(td.getAttribute('deckIndex'));
		//alert(index);
		if(index==0){
			showHome();
		}else if(!showNonHome(index)){
			alert('please wait a second ... ');
			return;
		
		}
		//alert(index);
		removeClass(td,'hover');
		addClass(td,'selected');
		// unselect all the rest
		var toolbar=document.getElementById('toolbar');
		var tds=toolbar.getElementsByTagName('td');
		for(var i=0;i<tds.length;i++){
			if(td!=tds[i]){
				toolBarItemUnselected(tds[i]);
			}
		}
		
	}
	function toolBarItemUnselected(td){
		removeClass(td,'selected');
		removeClass(td,'hover');
	}
	
	function showHome(){
		// to workaround backbase bug, select the 1st one that doesn't contain iframe
		bb.evaluateSmart("id('main-deck')/b:deckItem[1]",bb.document).setProperty('selected',true);
		bb.command.hide(document.getElementById('main-bb'));
		bb.command.show(document.getElementById('home'));

	}
	function showNonHome(index){
		var eles=bb.document.selectNodes('//b:balloon');
		for(var i=0;i<eles.length;i++){
			ele=eles[i];
			ele.setAttribute('open','false');
		}
		
		var deckItem=bb.evaluateSmart("id('main-deck')/b:deckItem["+index+"]",bb.document);
		//alert(deckItem);
		if(deckItem==null){
			return false;
		}else{
			bb.command.hide(document.getElementById('home'));
			bb.command.show(document.getElementById('main-bb'));
			deckItem.setProperty('selected',true);			
			return true;
		}
	}

	function evalWordScript(word, before){
		var scriptEle=before?bb.evaluateSmart('@before',word):bb.evaluateSmart('@after',word);
	
		if(scriptEle){
			var script=bb.xml.serialize(scriptEle);
			eval(script);
		}		
	}
	
	// language bar operations
	function showLanguage(lang){
		// load the static words
		var success=function(request,response){
			var words=bb.evaluate('/*/word',response);
			
			for(var i=0;i<words.length;i++){
				// the id of a html element, NB! it can't be a backbase nor a user component, cuz its innerHTML will be changed!
				var id=bb.xml.serialize(bb.evaluateSmart('@id',words[i]));				
				
				var bbEle=bb.document.getElementById(id);
				
				if(bbEle){
					evalWordScript(words[i],true);
					var children=bb.evaluate('node()',bbEle.modelNode);
					
					for(var j=children.length-1;j>=0;j--){
						bb.command.destroy(children[j]);	
					}
					
					bbEle.viewNode.innerHTML='';
					
					children=bb.evaluate('node()',words[i]);
				
					for(var j=0;j<children.length;j++){
						bb.command.create(children[j],bbEle,'lastChild');	
					}
									  
					evalWordScript(words[i],false);
					
				}else{
				
					var ele=document.getElementById(id);
				
					if(ele){
						evalWordScript(words[i],true);
						ele.innerHTML=getInnerHTML(words[i]);
						evalWordScript(words[i],false);
					}
				}
				
			}

			hideLoading();
		}
		
		showLoading();
		
		bb.command.load("languages/"+lang+".xml",'GET',null,null,null,null,success,function(x,y){ hideLoading(); });
		
		loadMultilingualMedia(lang, 'news','news');
		loadMultilingualMedia(lang,'menu-rest','menu');
		loadMultilingualMedia(lang,'menu-afhalen','menu');
		loadMultilingualMedia(lang,'menu-tourist','menu');
		
		
	}
	
	function loadMultilingualMedia(lang,category,mediaType){
		var url=getMultilingualMediaUrl(lang,category,mediaType);
		var containerElement=getMultilingualContainer(category);
		showLoading();
		var stop=function(request,response){
			hideLoading();
		}
		//alert(url+"\r\n"+(isBb?containerElement.modelNode.id:containerElement.id));
		bb.command.load(url,"GET",null,null,containerElement,'replaceChildren',stop,stop);
	}
	
	function getMultilingualContainer(category){
		var id=category+"-root";
		//alert(id);
		var c=bb.document.getElementById(id);			
		if(!c){
			c=document.getElementById(id);	
		}
		return c;

		
	}
	function getMultilingualMediaUrl(lang, category, mediaType){
		if(category==null){
			return mediaType+"/"+lang+"."+mediaType;
		}else{
			return category+"/"+lang+"."+mediaType;
		}
	}
	
	var imageMarqueeScrolling=true;
	function imageMarqueeStart(previous){
		if(!imageMarqueeScrolling){
			return;
		}
		var container=document.getElementById('image-marquee');
		if(container==null){
			return;	
		}
		var delta=1;
		//alert(container.style.top);
		var existing=getPixelValue(container.style.top);
		if(previous-delta > existing){
			return;
		}
		if(existing < -190){
			// set to 0 and shuffle the image from top to bottom
			var first=bb.evaluateSmart('div[1]',container);
			bb.command.move(first,container,'lastChild');
			container.style.top='0px';
			// pause for 2 seconds and continue;
			setTimeout('imageMarqueeStart('+existing+')',2000);
		}else{
			// continue scrolling up
			container.style.top=(existing-delta)+'px';
			setTimeout('imageMarqueeStart('+existing+')',100);
		}
	}
	
	function imageMarqueePause(){
		imageMarqueeScrolling=false;
	}
	function imageMarqueeResume(){
		imageMarqueeScrolling=true;
		imageMarqueeStart();
	}
	
	/**** Scrolling Menu class ****/
	function ScrollingMenu(idSuffix){
		this.menuHeadScrolling=null;
		this.idSuffix=idSuffix;
		
		// element getters
		this.getDishImageDisplay=function(){
			return document.getElementById('dish-image-display-'+this.idSuffix);
		}
		this.getMenu=function(){
			return bb.document.getElementById('a-menu-'+this.idSuffix);
		}
		
		this.getMenuHeadScrollPanel=function(){
			return document.getElementById('menu-head-scroll-panel-'+this.idSuffix);
		}	
		this.getMenuHeadContainer=function(){
			return document.getElementById('menu-head-container-'+this.idSuffix);
		}	
		
		
		// menu operations	
		this.menuHeaderItemMouseOver = function(div){
			//alert(0);
			if(!this.isMenuHeaderItemSelected(div)){
				addClass(div.viewNode,'hover');
			}
		}
		this.menuHeaderItemMouseOut=function (div){

			removeClass(div.viewNode,'hover');				

		}
		
		this.getMenuGroupByMenuHeaderItem=function (div){
			return bb.document.getElementById(div.getAttribute('groupId'));
		}
		
		this.isMenuHeaderItemSelected=function (div){
			return hasClass(div.viewNode,'selected');
		}
		this.menuHeaderItemClick=function (div){
			
			// select the corresponding menu group
			var group=this.getMenuGroupByMenuHeaderItem(div);
			if(this.selectMenuGroup(group.viewNode)){

				// unselect the siblings
				var siblings=bb.evaluate('preceding-sibling::div | following-sibling::div',div.viewNode);
				for(var i=0;i<siblings.length;i++){
					removeClass(siblings[i],'selected');
				}
				// select itself
				addClass(div.viewNode,'selected');
				removeClass(div.viewNode,'hover');
				// scroll the menu displayer to top
				group.viewNode.parentNode.parentNode.scrollTop=0;
			}
		}
		this.selectMenuGroup=function (group){
			var siblings=bb.evaluate('preceding-sibling::div | following-sibling::div',group);
			//alert(siblings.length);
			for(var i=0;i<siblings.length;i++){
				
				// in the construction phase where no nodes are in the dom
				siblings[i].style.display='none';
				
			}
			//alert(group.id);
			//bb.command.setStyle(group,{'display':'block'});
			group.style.display='block';
			
			return true;
		}
		
		this.menuItemMouseOver=function (menuItem){
			addClass(menuItem.viewNode,'hover');
			this.showDishImage(menuItem.getAttribute('image'));
		}
		this.menuItemMouseOut=function (menuItem){
			removeClass(menuItem.viewNode,'hover');
			this.showDishImage(null);
		}
		this.showDishImage=function (url){
			//alert(url);			
			if(this.getMenu().getAttribute('showImage')=='false' || isEmptyString(url)){
				url='img/transparent.gif';
			}
			
			this.getDishImageDisplay().src=url;
			
		}
		
		this.menuHeadScrollBegin=function (oDirect) {
			//alert(1);
			var oAnimationInfo = {
				attributeName: "top",
				fill: "freeze"
			}
			var iPxPerSec=100;
			var oContainer = this.getMenuHeadScrollPanel();
			
			if(!oContainer.style.top){
				oContainer.style.top='0px';
			}
			var deltaWidth = oContainer.offsetHeight - oContainer.parentNode.offsetHeight;
			if(deltaWidth<=0){
				this.menuHeadScrolling = null;
				return;
			}			
			var start = parseInt(oContainer.style.top);
			var distance;
			if(oDirect == "down") {
				distance = deltaWidth - Math.abs(start);
				stop = -deltaWidth;
			} else {
				distance = Math.abs(start);
				stop = 0;
			}
			if(distance != 0) {
				oAnimationInfo.dur = (Math.round(100*distance/iPxPerSec)/100) + "s";
				oAnimationInfo.values = start +"px;" + stop + "px";
				var callback = function() {
					this.menuHeadScrolling = null;
				}
				this.menuHeadScrolling = bb.smil.animate(oContainer, oAnimationInfo, callback);
			} else {
				this.menuHeadScrolling = null;
			}
		}
		
		this.menuHeadScrollEnd=function (){
			if(this.menuHeadScrolling != null) {
				bb.smil.stop(this.menuHeadScrolling);
				this.menuHeadScrolling = null;
			}
		}
		
		this.menuHeadScrollMouseOver=function (ele){
			this.menuHeadScrollHover(ele);
			this.menuHeadScrollBegin(ele.getAttribute('direction'));
		}
		this.menuHeadScrollMouseOut=function (ele){
			this.menuHeadScrollNormal(ele);
			this.menuHeadScrollEnd();
		}
		this.menuHeadScrollHover=function (ele){
			bb.command.setStyle(ele.viewNode,{'border-style':'inset','margin-left':'1px','margin-right':'-1px'});
		}
		this.menuHeadScrollNormal=function (ele){
			bb.command.setStyle(ele.viewNode,{'border-style':'solid','margin-left':'0px','margin-right':'0px'});
		}
		this.menuHeadNeedScroll=function (){
			var oContainer = this.getMenuHeadScrollPanel();
			return oContainer.offsetHeight > oContainer.parentNode.offsetHeight;
		}
		this.menuHeadScrollShowHide=function (){
			var container=this.getMenuHeadContainer();
			//alert(container);
			if(this.menuHeadNeedScroll()){
				// has to be done twice				
				removeClass(container,'show');
				addClass(container,'show');				
			}else{
				// has to be the following sequence
				addClass(container,'show');
				removeClass(container,'show');
				
			}
		}

	}// end of class def		
	var __MENUS__={};
	function findMyScrollingMenu(ele){
		var idSuffix=findMyMenuIdSuffix(ele);
		return __MENUS__[idSuffix];
		//return allMenus[idSuffix];			
		//return containerEle.modelNode.cycScrollingMenu;
	}
	function findMyMenu(ele){
		var xpath="ancestor-or-self::*[@idSuffix]";
		
		var containerEle=bb.evaluateSmart(xpath,ele);
		
		if(!containerEle){
			alert('ERROR: no result from xpah: '+xpath);
		}
		return containerEle;
	}
	function findMyMenuIdSuffix(ele){
		var menu=findMyMenu(ele);
		return menu.getAttribute('idSuffix');
	}
	function findScrollingMenu(idSuffix){
		return __MENUS__[idSuffix];
	}				
	
