/**
*  @file common.js
*  @author Abhay Garg
*  @version 1.0
*  @desc To implement functions for most common client side task.
**/

/**
   @desc Strip whitespace from the beginning and end of a string
   @param string inputString
   @return string
*/

function trim(inputString)
{
	if (typeof inputString != "string")
	{
		return inputString;
	}
	var retValue = inputString;
	var ch = retValue.substring(0, 1);
	while (ch == " ")
	{
		retValue = retValue.substring(1, retValue.length);
		ch = retValue.substring(0, 1);
	}
	ch = retValue.substring(retValue.length-1, retValue.length);
	while (ch == " ")
	{
		retValue = retValue.substring(0, retValue.length-1);
		ch = retValue.substring(retValue.length-1, retValue.length);
	}
	while (retValue.indexOf("  ") != -1)
	{
		retValue = retValue.substring(0, retValue.indexOf("  ")) + retValue.substring(retValue.indexOf("  ")+1, retValue.length); // Again, there are two spaces in each of the strings
	}
	return retValue;
}

/**
   @desc check empty string.
   @param string
   @return true|false
*/

function isEmpty (elementValue)
{
   var str = trim(elementValue);
   if(str == "" || str.length == 0)
   {
	  return true;
	}
	else
	{
	  return false;
	}
}

/**
   @desc check if number is real number (have decimal).
   @param string|integer|float
   @return true|false true is number is real oherwise false
*/

function isReal(elementValue)
{
	var str = trim(elementValue);
	var oneDecimal = false;
	var oneChar = 0;
	// make sure value hasn't cast to a number data type
	str = str.toString( );
	for (var i = 0; i < str.length; i++)
	{
		oneChar = str.charAt(i).charCodeAt(0);

		// OK for one decimal point
		if (oneChar == 46)
		{
			if (!oneDecimal)
			{
				oneDecimal = true;
				continue;
			}
			else
			{
			   return false;
			}
		}
		// characters outside of 0 through 9 not OK
		if (oneChar < 48 || oneChar > 57)
		{
		   return false;
		}
	}
	return true;
}

/**
   @desc check if number is negtive
   @return: true|false
*/

function isNegtive (elementValue)
{
  var str = trim(elementValue);
  if(str.charCodeAt(0)== 45)
  {
	return true; // if negtive
  }
  else
  {
	 return false;
  }
}

/**
   @desc check string of allowed length.
   @param string elementValue
   @param integer len allowed length
   @return: true|false false if string length exceeds.
*/

function isMaxLength(elementValue, len)
{
	var str = trim(elementValue);
	if (str.length != len)
	{
		return false;
	}
	else
	{
		return true;
	}
}

/**
   @desc check valid email
   @param string
   @return true|false
*/

function checkEmail(elementValue)
{
	var str = trim(elementValue);
	var re = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
	if (!str.match(re))
	{
	  return false;  // invalid email address
	}
	else
	{
		return true;
	}
}

/**
   @desc check and uncheck all checkboxes in given form.
   @param object formx <form> object
   @param object parentChk parent <checkbox> object
*/

function checkAllBoxes(formx,parentChk)
{
	if(formx.parentChk.checked)
	{
		for(var i=1;i<formx.length;i++)
		{
			if(formx.elements[i].type=="checkbox")
			{
				formx.elements[i].checked=true;
			}
		}
	}
	else
	{
		for(var i=1;i<formx.length;i++)
		{
			if(formx.elements[i].type=="checkbox")
			{
				formx.elements[i].checked=false;

			}
		}
	}
}

/**
@desc count number of character left in textarea and do not let user to enter more characters in textbox if maxlimit get exceeded.
@para object <textarea> object
@param object countfield <text> object that shows the characters left
@param integer maxlimit number of characters allowed in <textarea>
@example
<tr>
<td nowrap class="input_form_caption_td" valign = "top">Meta Keyword:<span> * </span> </td>
<td><textarea name="txtComments1" rows="6" cols="72" class="inputbox" onkeydown="textAreaLimit(this.form.txtComments1,this.form.totalChars1,255);" onkeyup="textAreaLimit(this.form.txtComments1,this.form.totalChars1,255);"><?=$txtComments1?></textarea>
<br>
<input class="inputbox" readOnly type="text" maxLength="4" size="4" value="255" name="totalChars1">
<small>Characters left</small>
</td>
</tr>
*/

function textAreaLimit(fieldname, countfield, maxlimit)
{
	if (fieldname.value.length > maxlimit)
		fieldname.value = fieldname.value.substring(0, maxlimit);
	else
		countfield.value = maxlimit - fieldname.value.length;
}

/**
	@desc random string of specified length.
	@param integer strlength length of random string.
	@return string.
*/

function randString(strLength)
{
	var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
	var randomString = '';
	for (var i=0; i<strLength; i++)
	{
	  var rnum = Math.floor(Math.random() * chars.length);
	  randomString += chars.substring(rnum,rnum+1);
	}
	return randomString;
}

/**
	@desc check file extension.
	@param string  ext comma seperated string of allowed file extensions
	@param filename
	@return true|false|-1 true for correct file extension otherwise false. If filename is without extension and allowed file extension is empty string.
*/

function checkFileExt(ext, filename)
{
   ext = trim(ext);
   var extArr = ext.split(",");
   var pos  = filename.lastIndexOf(".");
   if(pos==-1 || ext=="")
   {
	 return -1;
   }
   else
   {
	 var fileExt = filename.substr(pos+1);
	 fileExt = trim(fileExt.toLowerCase());
	 for(var i=0; i<extArr.length;i++)
	 {
		if (fileExt == trim(extArr[i].toLowerCase()))
			return true;
	 }
	 return false;
   }
}

/**
	@desc check valid date.
	@param string date string as INTERNATIONAL DATE FORMAT(ISO 8601) YYYY-MM-DD and most commaon date format DD-MM-YYYY.
	@return array|false 1st element day, 2nd element month and 3rd element year if date is valid date string otherwise false.
	@note Handles '-' or '/' as date seperator character.
*/

function checkDate(dateString)
{
	var dateString = trim(dateString);
	var datePattern = /^(\d{4})(\/|-)(\d{1,2})\2(\d{1,2})$/;  // yyyy-mm-dd and yyyy/mm/dd
	var datePattern1 = /^(\d{1,2})(\/|-)(\d{1,2})\2(\d{4})$/; // dd-mm-yyyy and dd/mm/yyyy

	if((matchArray = dateString.match(datePattern))!=null)    // check yyyy-mm-dd and yyyy/mm/dd
	{
	  month = matchArray[3];
	  day = matchArray[4];
	  year = matchArray[1];

	  if (month < 1 || month > 12)
	  {
	   return false;
	  }
	  if (day < 1 || day > 30)
	  {
		return false;
	  }
	  if ((month==4 || month==6 || month==9 || month==11) && day==31)
	  {
		return false;
	  }
	  if (month == 2) // check For leap year
	  {
		var isLeap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day>29 || (day==29 && !isLeap))
		{
		  return false;
		}
	  }
	  return (new Array(day,month,year));
	}
	else if((matchArray = dateString.match(datePattern1))!=null)  // check dd-mm-yyyy and dd/mm/yyyy
	{
	  month = matchArray[3];
	  day = matchArray[1];
	  year = matchArray[4];

	  if (month < 1 || month > 12)
	  {
	   return false;
	  }
	  if (day < 1 || day > 31)
	  {
		return false;
	  }
	  if ((month==4 || month==6 || month==9 || month==11) && day==31)
	  {
		return false;
	  }
	  if (month == 2) // check For leap year
	  {
		var isLeap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
		if (day>29 || (day==29 && !isLeap))
		{
		  return false;
		}
	  }
	   return (new Array(day,month,year));
	}
	else
	{
	  return false;   // if none of the date format match
	}
}

/**
  @desc get age.
  @param string DOB in format yyyy-mm-dd, yyyy/mm/dd, dd-mm-yyyy, dd/mm/yyyy.
  @return integer|false age of person or false if date is invalid.
*/

function getAge(dob)
{
	var dob = trim(dob);
	var now = new Date();

	dobArr = checkDate(dob);
	if(dobArr == false)
	{
	   return false;
	}
	else
	{
	  var dy = dobArr[0];
	  var mnth = dobArr[1] - 1; // 0 is janaury, 1 Feb and so on.
	  var yr = dobArr[2];

	  var dobDays = ((new Date(yr,mnth,dy)).getTime())/(60*60*24*1000);
	}
	 var current  = (now.getTime())/(60*60*24*1000);
	 var diffInDays = Math.abs((current-dobDays)); // contain difference in days
	 diffInDays = Math.floor(diffInDays);
	 if(diffInDays >= 365)
	 {
	   var years = diffInDays/365;
	   years = parseInt(years);
	   return years;
	 }
	 else
	 {
	   return diffInDays;
	 }
}

/**
  @desc date difference.
  @param string date strings in format yyyy-mm-dd, yyyy/mm/dd, dd-mm-yyyy, dd/mm/yyyy.
  @return array|integer|false 1st element years 2nd element days, number of days if difference is less than 365 or false any of the date is invalid.
*/

function dateDiff (dateFirst, dateSecond)
{
	dateFirst = trim(dateFirst);
	dateString1 = trim(dateSecond);

	dateFirstArr = checkDate(dateFirst);
	dateSecondArr = checkDate(dateSecond);

	if(dateFirstArr == false)
	{
	   return false;
	}
	else
	{
	  var dy = dateFirstArr[0];
	  var mnth = dateFirstArr[1] - 1; // 0 is janaury, 1 Feb and so on.
	  var yr = dateFirstArr[2];
	  firstDays = ((new Date(yr,mnth,dy)).getTime())/(60*60*24*1000);
	}

	if(dateSecondArr == false)
	{
	   return false;
	}
	else
	{
	  var dy = dateSecondArr[0];
	  var mnth = dateSecondArr[1] - 1; // 0 is janaury, 1 Feb and so on.
	  var yr = dateSecondArr[2];
	  secondDays = ((new Date(yr,mnth,dy)).getTime())/(60*60*24*1000);
	}

	diffInDays = Math.abs((firstDays-secondDays)); // contain difference in days
	diffInDays = Math.floor(diffInDays);

	if(diffInDays >= 365)
	{
	   var daysLeft = diffInDays%365; // days left
	   var years = diffInDays/365;
	   years = parseInt(years);
	   return (new Array(years,daysLeft));
	}
	else
	{
	   return diffInDays;
	}

}

/**
	@desc compare dates
	@param string date strings in format yyyy-mm-dd, yyyy/mm/dd, dd-mm-yyyy, dd/mm/yyyy.
	@return 0|1|2|false 0 if two dates are equal, 1 if first date is greater than second date, 2 if second date is greater than first date, false if dates are invalid.
*/
function compareDate(dateString1, dateString2)
{
   var dateString1 = trim(dateString1);
   var dateString2 = trim(dateString2);

   var dateStringArr1 = checkDate(dateString1);
   var dateStringArr2 = checkDate(dateString2);
   if(dateStringArr1 == false || dateStringArr2 == false)
   {
	 return false;
   }

   var dateMillSec1 = (new Date(dateStringArr1[2],dateStringArr1[1]-1,dateStringArr1[0])).getTime();
   var dateMillSec2 = (new Date(dateStringArr2[2],dateStringArr2[1]-1,dateStringArr2[0])).getTime();

   if(dateMillSec1 == dateMillSec2)
	 return 0;

   if(dateMillSec1 > dateMillSec2)
	  return 1;

  if(dateMillSec1 < dateMillSec2)
	  return 2;
}

/**
	@desc show date in format MONTH, DAY YEAR.
	@param string date string in format yyyy-mm-dd, yyyy/mm/dd, dd-mm-yyyy, dd/mm/yyyy.
	@return string|false
*/

function showDate(dateString)
{
   var dateString = trim(dateString);

   var dateStringArr = checkDate(dateString);

   if(dateStringArr == false)
   {
	 return false;  // invalid date
   }

   var date = new Date(dateStringArr[2],dateStringArr[1]-1,dateStringArr[0]);
   return ((date.toLocaleDateString()).substr(((date.toLocaleDateString()).indexOf(","))+1));
}

/**
	@desc round real number to certain decimal point.
	@param integer num
	@param integer placces number of digits after decimal
	@return integer|false
*/

function roundNumber(num, places)
{
   if(isReal(num) == false)
   {
	  return false;
   }
   if (places > 0)
   {
	  if ((num.toString().length - num.toString().lastIndexOf('.')) > (places + 1))
	  {
		 var rounder = Math.pow(10, places);
		 return Math.round(num * rounder) / rounder;
	  }
	  else return num;
   }
   else return Math.round(num);
}


/**
* ======================================
*  Setting, reading and deleting cookie
* ======================================
*/

/**
	@desc set cookie.
*/

function setCookie(sName, sValue, oExpires, sPath, sDomain, bSecure)
{
  sName    = trim(sName);
  sValue   = trim(sValue);
  oExpires = trim(oExpires);
  sPath    = trim(sPath);
  sDomain  = trim(sDomain);

  var sCookie = sName + "=" + encodeURIComponent(sValue);
  if (oExpires)
  {
   sCookie += "; expires=" + oExpires.toGMTString();
  }
  if (sPath)
  {
   sCookie += "; path=" + sPath;
  }
  if (sDomain)
  {
	sCookie += "; domain=" + sDomain;
  }
  if (bSecure)
  {
	sCookie += "; secure";
  }
  document.cookie = sCookie;
}

/*
	@desc get cookie.
	@param sName cookie name
	@return string|null cookie value or null if value is not set.
*/

function getCookie(sName)
{
  var sRE = "(?:; )?" + sName + "=([^;]*);?";
  var oRE = new RegExp(sRE);
  if (oRE.test(document.cookie))
  {
	return decodeURIComponent(RegExp["$1"]);
  }
  else
  {
	return null;
  }
}

/**
	@desc delete cookie.
*/

function DeleteCookie(sName, sPath, sDomain) // deleteCookie(), it makes sense just to use it and pass in an expiration date that already occurred (in this case, January 1, 1970).
{
   setCookie(sName, "", new Date(0), sPath, sDomain);
}

/**
* ==============
* AJAX Functions
* ==============
*/

/**
  @desc Create XMLHTTP object
  @return object xmlhttp object.
*/

function createXMLHTTP()
{
  var xmlhttp = false;
  if (window.XMLHttpRequest)
  {
	xmlhttp = new XMLHttpRequest();
  }
  else if (window.ActiveXObject)
  {
	xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
  return xmlhttp;
}

/**
  @desc Send post and get request to server(URL)
  @param string url
  @param function callback handles the data recieved from server
  @param function process to display gif image or animation or  null if you do not want to show user that data is on progress.
  @param string postData data send to server by POST method if not supplied then the request will be GET.
  @note to remove animation, write code in handleResponse function.
  @example
  sendRequest('url?id=2',handleResponse,process); // GET
  sendRequest('url',handleResponse,process,postData); // POST
					 OR
  sendRequest('url?id=2',handleResponse,null); // GET
  sendRequest('url',handleResponse,null,postData); // POST

<html>
<head>
<title>Menu</title>
<script type="text/javascript" src="lib/jscript/basicfunctions.js"></script>
<script type="text/javascript">
var url = "http://localhost/site_folder/test.php";
function HandleReq(req)
{
   var div = document.getElementById('x');
   div.innerHTML = "";
   div.innerHTML = req.responseText;
}
function createAnimation()
{
   var div = document.getElementById('x');
   div.innerHTML = "";
   div.innerHTML = "<img src='http://localhost/site_folder/lib/images/orange.gif'";
}
</script>

</head>
<body>
<div style="height:100px; width:200px; border:1px solid #FF8080; text-align:center; padding-top:20px" id="x">
This is AJAX DIV.
</div>
<input type="button" name="ajax" id="ajax" value="Send Request" onclick="sendRequest(url,HandleReq,createAnimation);">
									 OR - without animation - pass null without quote.
<input type="button" name="go" id="go" value="Get" onclick="sendRequest(url,HandleReq,null,'id=12');">
</body>
</html>
*/

function sendRequest(url,callback,process,postData)
{
	var req = createXMLHTTP();
	if (!req) return;
	var method = (postData) ? "POST" : "GET";
	req.open(method,url,true);
	req.setRequestHeader('User-Agent','XMLHTTP');
	if (postData)   // handle default argument
		   req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
	req.onreadystatechange = function ()
	{
	   if (req.readyState != 4) return;
		   if (req.status != 200 && req.status != 304)
		   {
				   alert('ERROR: ' + req.status+' '+req.statusText);
				   return;
		   }

		  callback(req);	// call when document has been loaded
	}
	if (req.readyState == 4) return; // the document is already in the browser's cache, and the request does not need to be sent.
	req.send(postData);
	if(process != null)
	   process(); // call when document has not been loaded as yet.

}

/**
  @desc set post data in foramt id=12&name=xyz from FORM FIELDS
  @param object oForm <form>
  @return string data passed to sendRequest() method
*/

function setPostData(oForm)
{
	var aParams = new Array();
	for (var i=0 ; i < oForm.elements.length; i++)
	{
		var sParam = encodeURIComponent(oForm.elements[i].name);
		sParam += "=";
		sParam += encodeURIComponent(oForm.elements[i].value);
		aParams.push(sParam);
	}
	return aParams.join("&");
}

/*
* =====================
* End of AJAX Functions
* =====================
*/
