/*========================== PRIAM Javascript Livrary ============================
*
* Created
*=========== 
* 01 July 2009 ; PO
*
* Description
*==================
* This is a library of utility functions that are general in nature 
* mainly for manipulation/creating  DOM objects
* If adding any function to this file, it must be well documented.
* It must show
*** 1. What the function does
*** 2. What the arguments are, data type etc
*** 3. The return value and data type
*** 4. Possible example of how to use the function.
*
* Prerequisite
*==============
* prototype.js is required and must be include before this file
*
====================================================================================*/
function isset(item){
	return ((typeof item == 'undefined') || item == null) ? false : true;
}

function isArray(obj){
	return Object.isArray(obj);	
}

function poison(){
	var mt  = new Date();
	return mt.getTime() ;
}

function isEmpty(ob){
   for(var i in ob){ return false;}
  return true;
}
		
Number.prototype.fraction = fraction;	
function fraction(dec){

	if(!dec){
		return '1/1' ;
	}
	var decimal     = Math.round(dec*100)/100 ;
	decimal     = parseFloat("."+String(decimal).split('.')[1]);	
	var whole   = String(decimal).split('.')[0];	
	var num     = "1";

	for(z=0; z<String(decimal).length-2; z++){
		num += "0";
	}
		
	decimal = parseInt(decimal*num);
	num     = parseInt(num);

	for(z=2; z<decimal+1; z++){
		if(decimal%z==0 && num%z==0){
			decimal = decimal/z;
			num = num/z;
			z=2;
		}
	}
		
	return ((whole == 0) ? "" : whole + " ") + decimal + "/"+num;
}
		
var priamObject = {	
	/* this is the path is calling ajax functions using prototype*/
	'url'      : '/cmsPath.php',
	'errordiv' : 'cmsErrorArea',
	'passdiv'  : 'CMSsuccess',
	'data'     : '',
	'wait'     : 'ajaxWait',
	'animgif'  : '<img src="'+root+'images/cms/loader2.gif" border="0" align="right" vspace="5px"/>',
	'plusImg'  : '/images/cms/plus.png',
	'minusImg' : '/images/cms/minus.png',
	'pre'      : 'page_', 
	'cluster'  : 10,
	
	init: function(){		
		return this;
	},

/*
* This function creates a select object
* arr  = array of key/value pairs to populate select options
* name = name of the select
* code = additional item to append to the name. This would be the id of the select object
* cap  = Boolean value. If true or 1, it would capitalise the option text
* cur  = If set, would be selected as the current option
* returns an object
* to create a number list use the makeNumberList() function
*/

	createSel: function(arr,name,code,cap,cur,blank){
		var cnt  = 1;
		var done = false;
		var sel  = document.createElement('Select');
		code     = isset(code) ? code : '';
		blank    = isset(blank) ? blank : true;
		sel.id   = name + code;
		sel.name = name;
		
		if(blank){
			sel.options[0] = new Option('select',"",true,true);	
		}else{
			cnt = 0;
		}
		for(var i in arr){
			var desc = arr[i];
			if(isset(cap) && cap) {
				desc = desc.capitalize();
			}
			sel.options[cnt] = new Option(desc,i,false,false);
			if(isset(cur) && i == cur){
				sel.options[cnt].selected = true;
				done = true;
			}
			
			cnt++;
		}
		if(cnt == 2 && !done){
			var x = blank ? 0 : 1;
			sel.options[x].selected = true;
		}
	
		return sel;
	},


	createList: function(arr,name,code,type,clss,img){
		type     	= isset(type) ? type : 'ul';
		code     	= isset(code) ? code : '';
		clss     	= isset(clss) ? clss : '';
		var imgTag 	= '';
		var lst  	= document.createElement(type);
		lst.id   	= name + code;
				
		for(var i in arr){
			if(!Object.isString(arr[i])){
				var listCode = '';
				var li       = document.createElement('li');				
				li.id        = i;
				li.className = 'itemParent';
				li.innerHTML = i;	
				lst.appendChild(li);
				var subName  = '';//'sub_';	
				if(code){
					listCode = ['',i,code];
				}else{
					listCode = ['',i];
				}
				var subid    = listCode.join('_') ;
				var subList  = this.createList(arr[i],name,subid,type,clss,img);
				li.appendChild(subList);
			}else{
				var desc     = arr[i];
				var li       = document.createElement('li');
				if(isset(img)){
					imgTag = '<a href="#" onclick="$(\''+i+'\').remove(); return false;" title="Delete item">'+img+'</a>';
				}
				var html     = imgTag + desc;
				li.id        = i;								
				li.innerHTML = html;
				li.className = clss;
				lst.appendChild(li);
			}
		}
		
		return lst;
	},
	
/*
* This function creates a select object of numbers (number list)
* st    = start, the first item on the number list
* stp   = stop, the last item on the list
* cur   = current, the selected item
* selid = the id of the select object
* To create a non-number list select object, use createSel() instead
* returns and object
*/	
	makeNumberList: function(st,stp,cur,selid,name){
		var psn      = document.createElement('Select');
		psn.id       = selid;			
		psn.name     = isset(name) ? name : '';;
		var cnt      = 0;	
		for(var i=st; i<stp; i++){
			var sel = (cur == i) ? true : false;
			psn.options[cnt]  = new Option(i,i,false,sel);
			psn.options[cnt].selected = sel;
			cnt++;
		}
		
		return psn;
	},
	makeNumberListByArray: function(arr,cur,selid,name){
		var psn      = document.createElement('Select');
		psn.id       = isset(selid) ? selid : '';
		psn.name     = isset(name) ? name : '';;
		 
		if(isArray(arr)){
			for(var i=0; i<arr.length; i++){
				var sel = (cur == arr[i]) ? true : false;
				psn.options[i]  = new Option(arr[i],arr[i],false,sel);
				psn.options[i].selected = sel;
			}
		}
		
		return psn;
	},
/* 
* This function clears the error/success message displayed and hides the div
* errdiv  = the DIV id where the error message was displayed
* passdiv = id of the pass message div
* if not set, the default values would be used
*/
	clearError: function (errdiv,passdiv){
		errdiv   = (isset(errdiv) && errdiv != '')   ?  errdiv  : this.errordiv;
		passdiv  = (isset(passdiv) && passdiv != '') ?  passdiv : this.passdiv;
		var err  = $(errdiv);
		var pas  = $(passdiv);
		if(err){
			err.innerHTML = '';
			err.hide();
		}
		if(pas){
			pas.innerHTML = '&nbsp;';
			pas.hide();
		}
	},

	/**
	* This functions returns the associated error message for the error code passed
	*
	*/
	
	getErrorMessageByCode: function(code){
		var message = '' ;
		if(isset(code)){
			var req  = new Ajax.Request(this.url,{
				method:'Post',
				parameters:{'action':'PRM00114~','todo':'getError','errorCode':code},
				onSuccess: function(response){
					message = response.responseText; 
				}
			});			
		}
		
		return message;
	},
	
/*
* This function sets an error in the backend using the error code and displays the error
* error   = The error code
* divid   = ID of the DIV to display the error message
*/
	showError: function(error,divid,msg,notice,showHeader){
		this.clearError();
		showHeader = isset(showHeader) ? showHeader : 1;
		divid    = (isset(divid) && divid != '') ?  divid : this.errordiv;
		msg      = (isset(msg)  && msg != '')    ?  msg   : '';
		notice   = isset(notice)  ?  notice   : 0;
		isArray  = this.isArray(msg);
		var out  = '';
		//$(divid).innerHTML = '';
		if(msg != ''){
			if(isArray){
				var len = msg.length;
				if(showHeader){
					var str = len > 1 ? ' errors ' : ' error ' ;
					out    += notice ? '<h2>Warning: </h2><ol>' : '<h2>The following '+str+' occurred: </h2>';
				}
				out    += '<ol>';
				for(var k=0; k<len; k++){
					out += '<li>'+msg[k]+'</li>';
				}
				out += '</ol>';
			}else{
				out = msg;
			}
			$(divid).innerHTML = out;
			$(divid).show();
		}else{
			var req  = new Ajax.Updater(divid,this.url,{
				method:'Post',
				parameters:{'action':'PRM00114~','todo':'getError','errorCode':error,'showHeader':showHeader},
				onComplete: function(){
					$(divid).show();
				}
			}); 
		}	
	},
	
	isArray : function (obj) {
   		if (obj.constructor.toString().indexOf("Array") == -1)
      		return false;
   		else
      	return true;
	},
	
	process: function(obj,admin,func){
		admin     = isset(admin) ? admin : 0;	
		obj.admin = admin;	
		obj.ajax  = 1; 
		//param  = 'admin='+admin+'&'+param;		 
		//var data = '';
		var req = new Ajax.Request(this.url,{
			parameters : obj,
			onComplete  : func  
		});		 
	},
/*
* Finds the index of a select object with  value = val
* obj = form select object
* val = value to find index, if it is an option of the select object
*/
	findIndex: function(obj,val){
		obj     = $(obj);
		var len = obj.length;
 		var ind = 0;
 		
 		for(var i=0; i<len; i++){
 			var txt = obj.options[i].value;
 			if(txt == val){
 				ind = i;
 				break;
 			}
 		} 
 		return ind;		
	},
	
/*	Shows and animated gif when an ajax call is i progress
* 	divid = Id of the div where the gif should be displayed
*/
	showWait: function(divid){
		divid    = (isset(divid) && divid != '' ) ?  divid : this.wait;
		var obj  = $(divid);
		if(obj){
			obj.innerHTML = this.animgif;
			obj.show();
		}
	},

/* Hides the animated gif when an ajax call is complete
*  divid = Id of the div where the gif was displayed
*/
	hideWait: function(divid){
		divid    = isset(divid) ?  divid : this.wait;
		var obj  = $(divid);
		if(obj){
			obj.innerHTML = '&nbsp;';
			obj.hide();
		}
	},
	// This function selected an option by value
	
	selectOption: function(obj,val){
		obj     = $(obj);
		var len = obj.length; 
		
 		for(var i=0; i<len; i++){
 			var txt = obj.options[i].value;
 			if(txt == val){
 				obj.options[i].selected = true;
 				break;
 			}
 		} 
	},
	
/* this function displays an element that was previously hidden i.e. display=none.
* it changes the images indicating that it is either open or closed
* posid = The id of the element to be displayed
* imgid = the id of the image object who  src would be change
* more  = if set to 1, opens or 0 = closes the position
**** plus  = the image to indicate that the element is closed
**** minus - the image to indicate that the element is opened
**** If no image is specified, the default values would be used instead.
**** Images would be switched if the element exists
*/

	showMore: function(posid,imgid,more,plus,minus){
		plus     = isset(plus ) ?  plus  : this.plusImg ;
		minus    = isset(minus) ?  divid : this.minusImg;
		var img  = $(imgid);
		more     = isset(more) ? more : !$(posid).visible();
		if(more){
			//Effect.SlideDown(posid);			
			$(posid).show();
			if(img){
				img.src  = minus;
			}
		}else{
			$(posid).hide();
			//Effect.SlideUp(posid);
			if(img){
				img.src  = plus;
			}
		}
	},
	
/* hides posHide and dislays posShow
* usefull for showing animated gifs while hiding the main div
* posHide and posShow are the ids of the divs/elements
*/
	switchDisplay: function(posHide,posShow,frm,imgid){
		Form.reset(frm);
		var h = $(posHide);
		var s = $(posShow);
		
		if(isset(frm) && $(frm)){
			$(frm).getInputs('text').each(function(e){e.value='';});
			$$('textarea').each(function(e){e.innerHTML = '';});
		} 
		//Form.reset(frm);
		if(h){
			h.hide();
		}
		if(s){
			s.show();
		}
		if(isset(imgid)){
			var cc  = $$('img[id]');
			//var cols = $$('img [id ^='+imgid+']');
			cc.each(function(em){if(em.id.startsWith(imgid)){em.src='';}});		   
		}
		//$(posHide).hide();
		//$(posShow).show();
		this.clearError();
	},

/* Page Navigation
*  page = page to go to (pages must be enclosed int tbody tags	)	
*  each tboyd must have ids e.g. part_page, where page is the page number
*  the page numbers must be list items with each page enclosed in <a></a>
*  each list item must have an id inthe form li_page, where page is the page number.
*/
	 nextPage: function(page,prefix,obj){
		pre      = prefix;		
		prefix   = prefix ? prefix : 'part_';
		
		var nbody = $$('tbody[id ^= '+prefix+']');
		var refs = $$('li[class=active]');
		var rows = $$('tr');
		var ths  = $$('th');
		var hid  = $('curPage');
		
		redo     = true;
		curBody  = parseInt(page) - 1;

		if(hid){
			hid.value = page;
		}
		
		nbody.invoke('hide');
		/*
		nbody.each(function(e){			
			e.hide();
		});
		*/
		var bdyname = prefix+page;
		var cp      = $(bdyname);
		cp.show();
		
		refs.each(function(e){
			if(e.id.startsWith('li_')){
				e.removeClassName('active');
			}
		});

		if(isset(obj)){
			var li = $(obj).ancestors()[0];
			li.className = 'active';
		}else{
			$('li_'+page).className = 'active'; 
		}
		 
		//if(isset(redo)){
			//redo    = true;
		//}
		
		var cur = $$('span[id=currentPage]','input[id=curPage]');		 
		var b = $A(cur);
		if(cur.length){
			for(var k=0; k<cur.length; k++){
				if(cur[k].tagName == 'INPUT'){
					cur[k].value = page;
				}else{
					cur[k].innerHTML = page;
				}
			}
		}
		
		var topAnchor = $('top-anchor');
		if(topAnchor){
			Effect.ScrollTo('top-anchor') ;
		}
		
		return false ;
		//sorttable.init();
	},
/* This functions loops through a multiple select element and returns the selected options in an array	*/
	getMultiValues : function(selid){
	  	var obj = $(selid);
	  	var arr = new Array();
	  	var count = 0;
	  	for (var i=0; i<obj.options.length; i++) {
	    	if(obj.options[i].selected) {
	    		var val    = obj.options[i].value;
	    		//var txt    = obj.options[i].text;
		      	arr[count] = val;
	      		count++;
	    	}
	  	}  
	  	return arr;  
	},
	
	addInput2Form : function(formid,type,name,value,id){
		var minput= document.createElement("INPUT");
		minput.setAttribute('type',type);
		minput.setAttribute('name',name);
		minput.setAttribute('value',value);
		if(isset(id)){
			minput.setAttribute('id',id);
		}
		$(formid).appendChild(minput);	
	},
/* Returns the selected element  in a  radio group*/	
	getSelRadio : function(radid){
		var val  = '';
		var grp = $$('input[id ^='+radid+']');
		for(var a=0; a<grp.length; a++){
			var rr = grp[a];
			if(rr.type == 'radio' && rr.checked){
				val = rr;
				break
			}
		}
		return val;
	},

/** toggles visibility of elem and changes the sign from + to - and vice versa 
* img   = ID of the image object. the src would be switched to reflect on/off
* elem  = element to show or hide
* minus = image to indicate that elem is shown
* plus  = image to indicate that elem is hidden
*
*/

	toggleView : function(img,elem,minus,plus){
		var obj = $(elem);
		img     = $(img);
		obj.toggle();
		var file = img.src;
		plus  = isset(plus)  ? plus  : 'plus.png';
		minus = isset(minus) ? minus : 'minus.png';
		
		if(obj.visible()){
			img.src = file.replace(plus,minus);
		}else{
			img.src = file.replace(minus,plus);
		}
	},
	showPass: function (msg,divid){
		divid    = (isset(divid) && divid != '') ?  divid : this.passdiv;
		var pass = $(divid);
		pass.innerHTML = msg;
		pass.show();
	},
	/** function deletes all child elements of parentID */
	removeKids : function(parentID){
		var par = $(parentID);
		if(par){
			var kids = $A(par.childElements());
			kids.each(function(e){
							   e.remove();
			});
		}
	},
	
	selectAll: function(obj,prefix){
		obj       = $(obj);
		var boxes = $$('input[id ^= '+prefix+']');
		boxes.each(function(elm){elm.checked = obj.checked;});
	},
		
/* hides all elements of type 'typ' that have IDs starting with prefix.
** displays the element with ID=prefix+toOpen
*/
	showMe: function(prefix,toOpen,typ){
		typ      = isset(typ) ? typ : 'div';
		var cur  = $(prefix+toOpen);
		if(cur){
			var divs = $$(typ+'[id^='+prefix+']');
			divs.invoke('hide');
			cur.show();
		}		 
	},
	
/* Inserts an object/text
* content = what to insert
* where   = id of object or the object to insert into
* how     = should be either 'before', 'after', 'top' or 'bottom' default is top

*/

	insertMe: function(content,where,how){
		where = $(where);
		if(where){
			how   = isset(how) ? how.toLowerCase() : 'top';
			var param = {};
			param.how = content;
			switch(how){
				case 'top':{
					where.innerHTML = '';
					new Insertion.Top(where.id,content);
					break;
				}
				case 'bottom':{
					new Insertion.bottom(where.id,content);
					break;
				}				
				
				case 'before':{
					new Insertion.Before(where.id,content);
					break;
				}
				case 'after':{
					new Insertion.After(where.id,content);
					break;
				}
			}
			
		}else{
			var msg = 'Element with ID = ' + where + ' does not exist';
			this.showError('','',msg);
		}
	},
	
	//generates a random between num1 and num2
	genRandomNumber: function(num1, num2, base){
		base = isset(base) ? base : 0;
		num1 = parseInt(num1);
		num2 = parseInt(num2);
		if(num1 >= num2){		
			var num3 = num2;
			num2 = num1;
			num1 = num3
		}
		 
		var generator = Math.random()*(num2-num1);
		generator     = Math.floor(num1+generator);
		
		switch(base){
			case 16:{
				generator = this.getHexCode(generator);
				break;
			}
		}
		return generator;
	},
	
	buildPaginator: function(total,perpage,cur,id,cls){
		var cluster  = priam.cluster;
		var numPage  = Math.ceil(total/perpage);		
		var marg     = Math.floor(cluster/2);
		var template = '<ul id="'+id+'" class="'+cls+'">';
		
		var start    = cur - marg ;
		var end      = cur + marg ;
		
		if(start < 1){
			start = 1
			end   = cluster;
		}
		
		for(var k=1; k<=numPage; k++){ 
			var act  = (k == cur) ? ' class="active"' : '';
			var disp = (k<start || k>end) ? ' style="display:none" ' : '';
			
			template 	+= "<li id='li_"+k+"' "+ disp + act +"><a href='#' id='page_"+k+"'>"+k+"</a></li>";
		}
		template 	+= '</ul>';
		
		return template;
	},
	
	
	getHex: function(dec){ 
		var hexArray = new Array( "0", "1", "2", "3", 
								  "4", "5", "6", "7",
								  "8", "9", "A", "B", 
								  "C", "D", "E", "F" ); 
		var code1    = Math.floor(dec / 16);
		var code2    = dec - code1 * 16;
		var decToHex = hexArray[code2];
		
		return (decToHex);
	},
	
	getHexCode: function(dec){				
		var hexCode= new Array();
		var i=0;
		while(dec > 15)	{
			hexCode[i]  = priam.getHex(dec);
			dec 		= Math.floor(dec / 16); 
			 i+=1;
		} 
		hexCode[i] = priam.getHex(dec); 
		var decToHex = ""; 
		for(i=hexCode.length-1; i>=0; i--){
			decToHex += hexCode[i];
		}		
		return decToHex; 		
	},
	/*============ adds spinner ui to appear next to an input field ===============*
	* requires jquery 
	* TODO : rewrite to use prototype if jquery is not available	
	*/
	makeSpinner: function(selector,step){ 
		if(isset($j)){
			var btn ='<div class="spinner-div"><button class="spinner-up">&#9650;</button>';
			btn    +='<button class="spinner-down">&#9660;</button></div>';		
			$j(selector).after(btn).each(function(i,o){	
				var inp = $j(o);								  
				var par = $j(inp).parent();
				
				$j('button[class^="spinner-"]',par).bind('click',function(){
					var btn = $j(this); 
					var val = inp.val()*1;
					var stp = 0.25;
					var inc = isset(step) ? $j(step) : [];
					var mn  = inp.attr('alt');
					
					if(mn){
						mn = mn*1;
						stp = 1;
					}else if(inc.length && inp.hasClass('increment') == false){
						var stp = inc.val()*1;	
						mn = 0;
					}else{
						 mn =  0.25;
					}
					
					if(btn.hasClass('spinner-up')){				
						inp.val(val+stp);
					}else{
						var ls = val-stp;
						if(ls<mn){
							ls = mn;
						}					
						inp.val(ls);
					} 
					return false;
				});
			});
		}
	},
	/*
	*	creates a flyout with title = heading
	*  content = html
	*  div id = id
	*  div class = class.
	* appends the div to the document's body and makes it draggable
	*/
	getFlyout: function(heading, html, id, cls){
		id 		= isset(id) ? id  : 'winFloat';
		id      = $(id) ? id+'_1' : id;
		cls     = isset(cls) ? cls : 'winFloat';
		
		var temp  = '<div id="#{divId}" class="#{className}">';
		temp   += '<div id="handle" class="handleBar">';
		temp   += '<label>#{title}</label>';
		temp   += '<div class="handleImage">'; 
		temp   += '<span><img src="images/cms/delete_icon.png" alt="Close" onclick="$(\'#{divId}\').remove();" title="Close Library"/></span>'; 
		temp   += '<span><img src="images/cms/minimise_icon.png" alt="Minimise" onclick="priamObject.toggleView(this,\'itemPos\',\'minimise_icon.png\',\'add_icon.png\');" title="Minimise / Maximise"/></span>'; 
		temp   += '</div></div><div id="itemPos" style="padding:10px">#{content}</div></div>';		  
		
		
		var data   = {'title' : heading, 'content' : html, 'divId': id, 'className': cls};
		var myTemp = new Template(temp);		
		return myTemp.evaluate(data); 
	},
	
	showFlyout: function(heading, html, id, cls){
		var stagger = false;
		id 		    = isset(id)    ? id    : 'winFloat';
		if($(id)){
			id      = id+'_1';
			stagger = true;
		} 
		cls   = isset(cls) ? cls : 'winFloat';
		 
		var string = this.getFlyout(heading, html, id, cls);
		var arr    = document.getElementsByTagName('body');
		var pos    = $(arr[0]);
		pos.insert({'top':string}); 
		
	
		new Draggable(id);
		
		
		if(stagger){
			this.staggerPosition(id);
		}
	}, 
	/*
	* Staggers flyout position if multiple flyouts are on the page
	*/
	staggerPosition: function(obj){
		obj     = $(obj);
		var tp  = obj.getStyle('top').replace('px','') - 15;
		var lft = obj.getStyle('left').replace('px','') - 15;		
		obj.setStyle({left: lft+'px', top: tp+'px'});
	},
	
	getLCM: function(num){
		num = parseInt(num);
		var cnt    = -1;
		var i      = 2;
		var lcm    = [];
		var store  = {};
		store[1]   = 1;
		
		if(num > 1){
			while(i < num){ 		
				if(num%i ==0 ){ 
					store[i]    = 1;   
				}
				i++; 
			}
			store[i] = num;
		 
			
			var cnt = 0;
			for(var k in store){
				lcm[cnt] = k;
				cnt++;
			}
		}
	 
		return lcm.sort(function(a,b){return a - b});
	},
	
	/*
	* convert decimal floats to fractions
	*
	*/
	
	dec2frac: function (d) {	
	    var df = 1;
	    var top = 1;
	    var bot = 1;
	
	    while (df != d) {
	        if (df < d) {
	            top += 1;
	        }
	        else {
	            bot += 1;
	            top = parseInt(d * bot);
	        }
	        df = top / bot;
	    }
	    return top + '/' + bot;
	},


	 getUrlParam: function(url, paramName){
		  var reParam = new RegExp('(?:[\?&]|&amp;)' + paramName + '=([^&]+)', 'i') ;
		  var match   = url.match(reParam) ; 
		  return (match && match.length > 1) ? match[1] : '' ;
	},
	
	decodeHtmlEntities: function(str){
		var tarea = document.createElement('textarea'); // the "content" part is needed in buttons
		tarea.innerHTML = str;
		return tarea.value;			
	}
	/*
	countWords: function(textid,maxCount,displayid){ 
		var cmt   		= $(textid).innerHTML;
		var fullStr     = cmt + ' ';
		var cleanedStr  = cmt.strip();
        var splitString = cleanedStr.split(' ');
        var wordCount   = splitString.length -1;
 		var pos         = $(displayid);
		
        if (fullStr.length <2) {
    	      wordCount = 0;
        }
 		
		if(wordCount > maxCount){
			alert('Maximum word count reached');
		}else{
			if(pos){
				pos.innerHTML = wordCount;
			}
		}	
		
		return wordCount;
	}*/
};
//initialise
priam = priamObject.init();
 
 
