/*  project:   		  cat software applications
	client:    		  chigoze 'cat' nduanya
	author:    		  chigozie 'cat' nduanya
	date:      		  may 05, 2009
	file-name: 		  catscript-v2.js
	file-type: 		  javascript library
	supporting-files: prototype-1.6.0.3.js, jquery-1.3.2.min.js, jquery-ui-1.7.1.custom.min.js
    */

/* declarations:
   */
$cat=jQuery.noConflict();

/*
	class: 		CatScript
	parameters: -
	contract:   must provide methods for accessing the various rich classes preapred for the CatScript language.
				tested and passed.
    */
var CatScript=Class.create({											   
	initialize:function(){
		this.strPad=2;
		this.strFontSize=12;
		this.bodyCss={'font-family':'Tahoma','font-size':this.strFontSize+'px'};
		this.errorCss={'padding':'10px','text-align':'center'};
		this.fadeTime=5000;
		this.widthLeft=20;
		this.clearBoth='<div class="clear-both" style="clear:both;"></div>';
		/*
			property: 	 CatScript.menuItemsCss()
			parameters:  imageDir, strPad, strColor
			description: defines the style for menu items.
						 tested and passed.
			useage:      this.menuItemsCss=cat.menuItemsCss(this.imageDir,(this.strPad*3),strColor='white');*/
		this.menuItemsCss=function(imageDir,strPad,strColor){
			return {
				'background':'url('+imageDir+'template-6.png)','color':strColor,
				'padding':strPad,'font-weight':'bold','text-decoration':'none'
			};
		};//CatScript.menuItemsCss() ends here...
		
		this.menuItemOn={'text-decoration':'underline'};
	},//constructor ends here...
	
	/*
		method:		 CatScript.border()
		parameters:  properties (object)
		description: generates a border and returns it as a css object based on the type of border required.
					 if no mode property is specified, the default border is an all-round border css object.
					 if no color is specified, the default color is gray. if no properties at all, 
					 then the default settings are applied.
					 modes are: bottom, bottom-right, bottom-right-top, left, left-bottom-right, left-right, right, 
					 top, border (also the default mode)
					 tested and passed.										 
		useage:      var cssBorder=cat.border({color:signature.color,mode:'top'}); or ... cat.border({mode:'top'});
					 var cssBorder=cat.border();//returns default settings...
					 $cat('.container-page-menu a').css(cat.border({mode:'left',color:linkBorderColor,weight:2}));
					 //that's for using weight for thickness of border...
	*/
	border:function(properties){
		if(properties)
			var strMode=(properties.mode)?properties.mode:'border', strColor=(properties.color)?properties.color:'gray',
				weight=(properties.weight)?properties.weight:1;
		else 
			var strMode='border', strColor='gray';
		var cssBorder={};
		
		switch(strMode){
			case 'bottom': cssBorder={'border-bottom':weight+'px solid '+strColor}; break;
			case 'bottom-right': 
				cssBorder={
					'border-bottom':weight+'px solid '+strColor,
					'border-right':weight+'px solid '+strColor
				}; 
			break;
			case 'bottom-right-top': 
				cssBorder={
					'border-bottom':weight+'px solid '+strColor,
					'border-right':weight+'px solid '+strColor,
					'border-top':weight+'px solid '+strColor
				}; 
			break;
			case 'left':   cssBorder={'border-left':weight+'px solid '+strColor}; break;
			case 'left-bottom-right': 
				cssBorder={
					'border-left':weight+'px solid '+strColor,
					'border-bottom':weight+'px solid '+strColor,
					'border-right':weight+'px solid '+strColor
				}; 
			break;
			case 'left-right': 
				cssBorder={
					'border-left':weight+'px solid '+strColor,
					'border-right':weight+'px solid '+strColor
				}; 
			break;
			case 'right': cssBorder={'border-right':weight+'px solid '+strColor}; break;
			case 'top':   cssBorder={'border-top':weight+'px solid '+strColor};   break;
			default:      cssBorder={'border':weight+'px solid '+strColor};       break;
		}
		
		return cssBorder;
	},//CatScript.border() ends here...
	
	/*  method:      CatScript.clock()
		parameters:  container
		description: facilitates the action necessary to generate a clock-display into the parametized container.
					 //tested and passed.
		useage:		 cat.clock(applicationTitle.find('.date-and-time'));
	*/
	clock:function(container){
		if(container){
			$cat('.clock-display').remove();
			container=$cat(container).append('<div class="clock-display" style="width:30%;"></div>')
				.find('.clock-display').css({'padding':'2px'});
			container.css(this.border());
			tick();
		}
		else this.error({caller:'CatScript.clock()',message:'container expected!!!'});
	},//CatScript.clock() ends here...
	
	/*
		method: 	 CatScript.date()
		parameters:  strMode
		description: generates a date-display and returns it as a string. if no mode is specifed, month, day and year are returned.
					 tested and passed.
		useage:		 var strDate=this.date(mode='signature'); or ...
					 var strDate=this.date();//default setting is full date with day included...
	*/
	date:function(strMode){
		var mode=(strMode)?strMode:'full-date', output='';
		var currentTime=new Date(),month=currentTime.getMonth()+1, 
		day=(currentTime.getDate()<10)?'0'+currentTime.getDate():currentTime.getDate(), 
			year=currentTime.getFullYear();
		var months=['','January','February','March','April','May','June','July','August','September',
					'October','November','December'];
		
		switch(mode){
			case 'signature': output=months[month]+ ' '+year; 		   break;
			default: 		  output=months[month]+ ' '+day+', '+year; break;
		}
		
		return output;
	},//CatScript.date() ends here...
	
	/*  
		method:      CatScript.divide()
		parameters:  properties (object)
		description: coverts a container into a dual-panelled structure.
					 a dual panel consists of a left and right div, each classed accordingly, as well as a clear-float div.
					 tested and passed.
		useage:		 cat.divide({container:containerToSplit,widthLeft:40}); or cat.divide({container:containerToSplit});
	*/
	divide:function(properties){
		if(properties && properties.container){
			var widthLeft=(properties.widthLeft && properties.widthLeft>10 && properties.widthLeft<91)?
				properties.widthLeft:this.widthLeft, widthRight=100-widthLeft-1;
			var leftPanel='<div class="left-panel" style="float:left;width:'+widthLeft+'%;">width:'+widthLeft+'%</div>';
			var rightPanel='<div class="right-panel" style="float:right;width:'+widthRight+'%;">width:'+widthRight+'%</div>';
			$cat(properties.container).html(leftPanel+rightPanel+this.clearBoth);
		}
		else this.error({caller:'CatScript.divide()',message:'properties.container expected!!!'});
	},//CatScript.divide() ends here...
											 
	/*
		method:      CatScript.error()
		parameters:  properties
		description: this method outputs error messages to the current document. 
					 all execution is stopped until the error is addressed.
					 tested and passed.
		useage: 	 cat.error({caller:'CatScript.divide()',message:'properties expected!!!'});
					 //both required. no error-checking here.
	*/
	error:function(properties){
		properties.caller='<div style="color:blue;padding:5px;">caller: '+properties.caller+'</div>';
		$cat(document.body).html('<div class="error"><b>catscript error</b>'+properties.caller+properties.message+'</div>')
			.find('.error').hide().css(this.errorCss).fadeIn(this.fadeTime).find('b').css({'color':'red'});
	},//CatScript.error() ends here...
	
	/*
		method: 	 CatScript.form()
		parameters:  properties
		description: 
					 //tested and passed.
	*/
	form:function(properties){
	},//CatScript.form() ends here...
	
	/*
		method: 	 CatScript.highlight()
		parameters:  properties (mode, [menuItems, menuItem, menuItemOff, menuItemOn] - if mode is 'menu-item')
		description: if the specifed mode is 'menu-item', this method highlights a menu item on click. 
					 the parameters are all required.
					 tested and passed.
		useage:		 $cat('.container-page-menu a').click(function(){
						 var menuItems=$cat('.container-page-menu a'), menuItem=$cat(this), 
						 strBackground=menuItem.css('background'), menuItemOff={'background':strBackground};						 						  
						 cat.highlight({
							 mode:'menu-item',menuItems:menuItems,menuItem:menuItem,
							 menuItemOn:menuItemOn,menuItemOff:menuItemOff,
							 currentItemClassName:'menu-item current'
						 });
					 });
	*/
	highlight:function(properties){
		if(properties && properties.mode){
			switch(properties.mode){
				case 'menu-item':
					var menuItems=properties.menuItems, menuItem=properties.menuItem,
						menuItemOn=properties.menuItemOn, menuItemOff=properties.menuItemOff, currentItemClassName=properties.currentItemClassName;
					
					if(currentItemClassName && menuItem.attr('class')!=currentItemClassName){
						var strClassName=currentItemClassName.substr(currentItemClassName.lastIndexOf(' '),currentItemClassName.length);
						menuItems.removeClass(strClassName);
						menuItem.addClass(strClassName);
						menuItems.css(menuItemOff);
						menuItem.css(menuItemOn);
					}
				break;
			}
		}
		else this.error({caller:'CatScript.highlight()',message:'properties.mode expected!!!'});
	},//CatScript.highlight() ends here...
	
	/*  
		method:      CatScript.icon()
		parameters:  properties (object)
		description: must generate an icon-string and return to caller. an icon string comprises of 
					 an image (small-sized), and a hyperlink. 
					 this method assumes that the image is located in the standard image directory.
					 tested and passed.
		useage:		 var icon=cat.icon({directory:imageDirectory,imageSrc:'register.jpg'});//returns an xhtml string.
	*/
	icon:function(properties){
		if(properties && properties.directory){
			if(properties.imageSrc){
				var imageSrc=properties.imageSrc, directory=properties.directory, 
					imageCss='border:1px solid gray;margin-right:2px;';
				var iconText=imageSrc.substring(0,imageSrc.lastIndexOf('.'));
				var image='<img src="'+directory+imageSrc+'" width="14" height="14" alt="" style="'+imageCss+'" />';
				
				return '<a href="javascript:" class="icon" title="'+iconText+'">'+image+iconText+'</a>';
			}
			else this.error({caller:'CatScript.icon()',message:'properties.imageSrc expected!!!'});
		}
		else this.error({caller:'CatScript.icon()',message:'properties.directory expected!!!'});
	},//CatScript.icon() ends here...
	
	/*
		method: 	 CatScript.menu()
		parameters:  properties (container, imageDirectory, strPadding, strBorderColor,
			                     objMenuItemsCss,strLinkBorderColor;)
		description: generates and executes a style for menu-items.
					 tested and passed.
		useage:      cat.menu({
						 container:'.container-page-menu', strBackground:linkBorderColor, strPadding:strPad,
						 strBorderColor:borderColor, strLinkBorderColor:linkBorderColor, imageDir:imageDir, color:'white'
				     });
	*/
	menu:function(properties){
		var container=properties.container, background=properties.strBackground, strPad=properties.strPadding,
			borderColor=properties.strBorderColor, imageDir=properties.imageDir, color=properties.color, 
			menuItemsCss=this.menuItemsCss(imageDir,(strPad*3),color), linkBorderColor=properties.strLinkBorderColor,
			menuItemOn=this.menuItemOn, menuItemOff={'text-decoration':'none'};
		
		with($cat(container)){
			css({'background':background,'text-align':'center','margin':0+' '+strPad+'px'});
			css(this.border({mode:'left-right',color:borderColor}));
		}				
		with($cat(container+' a')){
			css(menuItemsCss);
			css(this.border({mode:'bottom-right-top',color:linkBorderColor}));
			hover(function(){$cat(this).css(menuItemOn);},
				  function(){$cat(this).css(menuItemOff);});
		}
		$cat(container+' a:first').css(this.border({mode:'left',color:linkBorderColor}));
	},//CatScript.menu() ends here...
	
	/*
		method: 	 CatScript.newContainer()
		parameters:  properties (parent, class)
		description: generates a new container into the specified parent-container (erasing all else within the parent-container), 
					 classes it and returns it to the caller.
					 tested and passed.
		useage:      var container=cat.newContainer({container:$cat(document.body),className:'page-header'});
	*/
	newContainer:function(properties){
		if(properties && properties.container){
			if(properties.className){
				return properties.container.html('<div class="'+properties.className+'"></div>').find('.'+properties.className);
			}
			else this.error({caller:'CatScript.newContainer()',message:'properties.className expected!!!'});
		}
		else this.error({caller:'CatScript.newContainer()',message:'properties.container expected!!!'});
	},//CatScript.newContainer() ends here...
	
	/*
		method: 	 CatScript.newWorkspace()
		parameters:  -
		description: clears the current document-body of all content, hence... new workspace.
					 tested and passed.
		useage:      cat.newWorkspace();
	*/
	newWorkspace:function(){
		if(confirm('really generate new workspace?'))$cat(document.body).html('');
	},//CatScript.newWorkspace() ends here...
		   
	/*
		 method: 	  CatScript.signature()
		 parameters:  strColor
		 description: generates author's signature into the current document.
		 			  if a color is specified, the signature is generated in that color. default color is gray.
					  tested and passed.
	*/
	signature:function(strColor){
		var strDate=this.date(mode='signature');
		var author={
				name:  	      "chigozie 'cat' nduanya",
				qualification:'computer-programmer analyst',
				date:  	      strDate
			};//author ends here...
		 
		var signature={
				container:		 '<table cellpadding="0" cellspacing="0" class="signature"></table>',
				authorRow:		 '<tr><td>author: '+author.name+'</td></tr>',
				qualificationRow:'<tr><td>'+author.qualification+'</td></tr>',
				dateRow:		 '<tr><td>'+author.date+'</td></tr>',
				color:		     (strColor)?strColor:'gray'
			};//signature ends here...
	  
		processor(this);//calling the 'this' object within a method signifies that objects can be passed around easily.
	  	function processor(cat){
			$cat('.signature').remove();
			$cat(document.body).append(signature.container)
				.find('table:last').append(signature.authorRow+signature.qualificationRow+signature.dateRow)
					.hide().fadeIn(cat.fadeTime)
					.css({'color':signature.color,'font-size':(cat.strFontSize-3)+'px','margin':'10px auto','text-align':'center'})
					.find('td:not(":first,:last")').css(cat.border({color:signature.color,mode:'top'}));
			$cat('table:last td').animate({'padding':'3px'},'slow');
		}//processor() ends here...
	},//CatScript.signature() ends here...
   
	/*
		method:		 CatScript.start()
		parameters:  properties (object)
		description: generates a new container into the current document, returns it, and as well, sets the default css styles 
					 for the current application. these can be over-ridden at any time within the application.
					 tested and passed.
		useage:		 var container=cat.start(); or 
					 cat.start('none');//this simply executes the body css and does not return a new container.
	*/
	start:function(insert){
		$cat(document.body).css(this.bodyCss);
		var insertContainer=(insert && insert=='none')?false:true;
		if(insertContainer)return this.newContainer({container:$cat(document.body),className:'container'});
	},//CatScript.start() ends here...
											 
	/*
	    method:      arrayStringToMultiArray()
	    parameters:  properties (object)
	    description: this function specializes in converting an array string to an array of arrays (multi-dimensional array).			
					 tested and passed.											 
		useage:      var controlIds=cat.stringToMultiArray({
						 arrayString:'row0cell0@row0cell1@rows0cell2~row1cell0@row1cell1@row1cell2',
						 mainArraySplit:'~', subArraySplit:'@'
					 });
								   
	*/
	stringToMultiArray:function(properties){
		if(properties&& properties.arrayString){
			if(properties.mainArraySplit){
				if(properties.subArraySplit){
					var output=[], internalArray, arrayString=properties.arrayString, 
						mainArraySplit=properties.mainArraySplit, subArraySplit=properties.subArraySplit;
					
					arrayString=arrayString.split(mainArraySplit);
					$cat(arrayString).each(function(){
						internalArray=this.split(subArraySplit);
						output.push(internalArray);
					});
					
					return output;
				}
				else this.error({caller:'CatScript.stringToMultiArray()',message:'properties.subArraySplit expected!!!'});
			}
			else this.error({caller:'CatScript.stringToMultiArray()',message:'properties.mainArraySplit expected!!!'});
		}
		else this.error({caller:'CatScript.stringToMultiArray()',message:'properties.arrayString property expected!!!'});
	},//stringToMultiArray() ends here...
	
	/*
		method: 	 CatScript.transform()
		parameters:  properties (mode, arrayToTransform are both required. other properties are: type - for input mode, 
								 imgDir - for images)
		description: takes an array of values, and, using the specified element-type, transforms the array into a string of
					 xhtml output representing each index of the array.
					 tested and passed.
		useage:		var output=cat.transform({mode:'div',arrayToTransform:Descon.general.menuItems});
					var container=cat.start();
					container.html(output);
					var menuItems=cat.transform({
						 mode:'a',arrayToTransform:['customers and projects','electrical','layout','mechanical','admin']
					});
					possible modes: all open-and-close-tag elements (except textarea); input (requires type), 
					and finally, img (requires src)
	*/
	transform:function(properties){
		if(properties && properties.mode){
			if(properties.arrayToTransform){
				properties.mode+=(properties.mode=='a')?' href="javascript:"':'';
				var output='', tagOpen='<'+properties.mode+'>', tagClose='</'+properties.mode+'>';
				
				function setForInput(){
					if(properties.mode=='input'){
						tagOpen='<input type="'+properties.type+'" value="';
						tagClose='" />';
					}
				}
				
				function setForImages(){
					if(properties.mode=='img'){
						tagOpen='<img src="'+properties.imgDir;
						tagClose='" alt="" />';
					}
				}
				
				setForInput();
				setForImages();
				$cat(properties.arrayToTransform).each(function(){output+=tagOpen+this+tagClose;});
				return output;
			}
			else this.error({caller:'CatScript.transform()',message:'properties.arrayToTransform expected!!!'});
		}
		else this.error({
				  caller:'CatScript.transform()',
				  message:'properties.mode expected!!!<br />possible values: a, div, input, span, table, tr, td, textarea'
			 });
	},//CatScript.transform() ends here...
	
	/*
		method: 	 CatScript.validate()
		parameters:  properties (object)
		description: validates all input fields that have a value attribute (only) whose ids match the ids in the properties' 
					 array of ids. if validation is successful, this method returns true else it returns false.
					 tested and passed.
		useage:		 if(cat.validate({ids:['txt_test_1','txt_test_2'],captions:['test 1','test 2']}))
					 	alert('all input fields validated!');
	*/
	validate:function(properties){
		if(properties){
			var validated=false, field=null;
			if(properties.ids && properties.captions && properties.ids.length==properties.captions.length){
				validated=true;
				for(var x=0;x<properties.ids.length;x++){
					if($(properties.ids[x])){
						field=$(properties.ids[x]);
						if(field.value==''){
							alert('sorry... '+properties.captions[x]+' required!!!');
							validated=false;
							field.focus();
							break;
						}
					}
				}
				return validated;
			}
			else 
				this.error({
					caller:'CatScript.validate()',
					message:'array of ids to be validated must be equal in length the array of captions!!!'
				});
		}
		else this.error({caller:'CatScript.validate()',message:'properties expected!!!'});
	},//CatScript.validate() ends here...
	
	/*
		method: ClsMuskokaSpaForPets.website()
	    parameters: -
	    description: contains all the logic for directing and organizing operations for a website.
	   				 tested and passed.
	 	useage:		 cat.website(key='home',Lib,Content,Styles,Functionality);//pls refer to the muskoka-spa-for-pets processor
					 for details on the properties required of the parametized objects.
	 */
	website:function(key,Lib,Content,Styles,Functionality){
		this.start('none');	
		function processor(){
			with(Content){
				pageHeader();
				pageBody(key);
			}			
			with(Styles){
				capping();
				pageHeader();
				pageMenu();
				pageBody();
				container();
				documentBody();
			}			
			Functionality.pageMenu();
		}//ClsMuskokaSpaForPets.processor()->processor() ends here...
		
		processor();
		this.signature();
	}//ClsMuskokaSpaForPets.website() ends here...
});//CatScript ends here...

/* functions:
   */								
/*tick(): displays the current time in 24-hr format. please ensure that a container of class clock-display 
		  is already created before calling this function.
		  tested and passed.*/
function tick(){
	var date=new Date(), hour=date.getHours(), minute=date.getMinutes(), second=date.getSeconds();    
	minute=(minute<10)?'0'+minute:minute; 
	second=(second<10)?'0'+second:second; 
	$cat('.clock-display').text(hour+':'+minute+':'+second+'hrs');
	timerObject=setTimeout('tick()',500);
}//tick() ends here...

/* declarations:
   */
var cat=new CatScript();