/** 
 * DScripted Toolkit for JavaScript
 * Copyright (c) 2010 Keith Daulton (dscripted.com)
 * Licensed under the GNU General Public License.
 * @author	Keith Daulton
 * @version	1.2
*/


/** Core library - DScripted Toolkit for JavaScript 
 * @author kdaulton
 */
var log = function(item){
	if (window.console) {
		if(window.console.firebug != '') { console.info(item); }
	}
};
function Tester(){
	this.endTime = 0;
	this.startTime = 0;
};
Tester.prototype.start = function(){ this.startTime = new Date(); };
Tester.prototype.end = function () { this.endTime = new Date(); };
Tester.prototype.getResult = function () { 
	var result = Number(this.endTime - this.startTime);
	this.endTime=0;
	this.startTime=0;
	return result;
};

function undef (obj) { return (typeof(obj) == "undefined"); };
function $id (strId) { return document.getElementById(strId); };

function getClass(object) {  return Object.prototype.toString.call(object).slice(8, -1); }; // Solution by Kangax.
function addClass (obj, cssClass) { if (obj.className.indexOf(cssClass) < 0) { if (obj.className != "") { obj.className += " " + cssClass; } else { obj.className = cssClass; } } };
function addClassById (strId, cssClass) { var obj = $id(strId); addClass(obj,cssClass); };
function removeClass (obj, cssClass) { if (obj.className.indexOf(cssClass) > -1) { obj.className = (obj.className.replace(cssClass,"")).trim(); } };
function removeClassById (strId, cssClass) { var obj = $id(strId); removeClass(obj,cssClass); };
function hasClass (obj, cssClass) { 
	var pattern = new RegExp("\\b"+cssClass+"\\b");
	return (obj.className.search(pattern,"g") > -1); 
};
function setEvent (obj, evnt, funct) { 
	if(obj) {
		if (obj.addEventListener){ obj.addEventListener(evnt, funct, false); return true; }
		else if (obj.attachEvent){ var r = obj.attachEvent("on"+evnt, funct); return r; }
		else { return false; } 
	} else { return false; } 
};

function getElementsByClassName (obj, strClassName) { 
	var resultSet = [];
	var elements = obj.getElementsByTagName('*');
	var pattern = new RegExp("\\b"+strClassName+"\\b");
	for (var i=0, j=elements.length; i<j; i++) {
		var childElement = elements[i];
		if (childElement.nodeType == 1) {
			if (childElement.className.search(pattern,"g") > -1) { resultSet.push(childElement); }
		}
	}
	return resultSet;
};

function DomObject (objRef) { 
	this.obj = (typeof(objRef) == 'string') ? document.getElementById(objRef) : objRef; 
};
DomObject.prototype.getElementsByClassName = function (strClassName) { return getElementsByClassName(this.obj, strClassName); };
DomObject.prototype.addClass = function (cssClass) { addClass(this.obj, cssClass); };
DomObject.prototype.removeClass = function (cssClass) { removeClass(this.obj, cssClass); };
DomObject.prototype.setEvent = function (evnt, funct) { setEvent(this.obj, evnt, funct); };
DomObject.prototype.setEventByClass = function (cssClass,evnt, funct) { 
	var objs = getElementsByClassName(this.obj,cssClass);
	for (var i=objs.length; i--;) { setEvent(objs[i], evnt, funct); }
};
function $extend (objRef) { return new DomObject(objRef); };

function newElement (ele, objid, cssClass) {
	var element = document.createElement(ele);
	if (objId != null) { element.id = objId; }
	if (cssClass != null) { addClass(element, cssClass); }
	return element;
};

function newXHRequest () {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		try {
			return new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				return new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) { return null; }
		}
	} else { return null; }
};

function randomNumber (length) {
	var number;
	for (var i=0; i<length;i++){ number += Math.floor(Math.random()*9); }
	return Number(number);
};

function setInputText (obj) { 
	if (obj.msg == null) { obj.msg = obj.value; }
	if (obj.value == "" && obj.msg != null) { obj.value = obj.msg; }
	else if (obj.value == obj.msg) { obj.value = ""; }
};

/* String Methods. */
String.prototype.trim = function () { return this.replace(/^\s+|\s+$/g, ""); };
String.prototype.ltrim = function () { return this.replace(/^\s+/, ""); };
String.prototype.rtrim = function () { return this.replace(/\s+$/, ""); };
String.prototype.onlyDigits = function () { return this.replace(/([\D\W])/gi, ""); };
String.prototype.equalsIgnoreCase = function (arg) { return (this.toLowerCase() == String(arg).toLowerCase()); };
String.prototype.equals = function (arg) { return (this.toString() == arg.toString()); };
String.prototype.startsWith = function (arg) { return (this.match("^"+arg)==arg); };
String.prototype.endsWith = function (arg) { return (this.match(arg+"$")==arg); };

/* Date Methods. */
Date.prototype.isLeapYear = function () {
    var year = this.getFullYear();
    return !(year % 4) && (year % 100) || !(year % 400) ? true : false;
};

var windowUtil = {
	getLiveHeight: function () {
		var result = 0;
		if (self.innerWidth) { result = self.innerHeight; }
		else if (document.documentElement && document.documentElement.clientWidth) { result = document.documentElement.clientHeight; }
		else if (document.body) { result = document.body.clientHeight; }
		return result;
	},
	getLiveWidth:  function () {
		var result = 0;
		if (self.innerWidth) { result = self.innerWidth; }
		else if (document.documentElement && document.documentElement.clientWidth) { result = document.documentElement.clientWidth; }
		else if (document.body) { result = document.body.clientWidth; }
		return result;
	},
	getFullHeight: function () {
		var result = 0;
		if (window.innerHeight && window.scrollMaxY) { result = window.innerHeight + window.scrollMaxY; } 
		else if (document.body.scrollHeight > document.body.offsetHeight){ result = document.body.scrollHeight; } 
		else { result = document.body.offsetHeight; }
		return result;
	},
	getFullWidth: function () {
		var result = 0;
		if (window.innerHeight && window.scrollMaxY) { result = window.innerWidth + window.scrollMaxX; } 
		else if (document.body.scrollHeight > document.body.offsetHeight){ result = document.body.scrollWidth; } 
		else { result = document.body.offsetWidth; }
		return result;
	}
};
var MouseUtil = { xPos:"", yPos:"", targetObj:null, xDiff:0, yDiff:0,
	getPositionEvent : function (e) {
		if (!e) var e = window.event;
		MouseUtil.getPosition(e);
	},
	getPosition : function (eObj) {
		if(eObj.pageX || eObj.pageY){ 
			this.xPos=eObj.pageX;
			this.yPos=eObj.pageY; 
		} else { 
			try {
            	this.xPos=eObj.clientX + document.body.scrollLeft - document.body.clientLeft;
                this.yPos=eObj.clientY + document.body.scrollTop  - document.body.clientTop; 
             } catch (err) {//DO nothing
			 }
		}
	},
	setDragObj : function (obj) {
		document.onmousedown = this.falsefunc;
		if (this.targetObj != obj) {
			this.targetObj = obj;
			this.xDiff =  obj.offsetLeft - this.xPos;
			this.yDiff =  obj.offsetTop - this.yPos;
		}
		document.onmousemove = MouseUtil.dragObjEvent;
		document.onmouseup = MouseUtil.releaseDrag;
	},
	dragObjEvent : function (e) {
		var targetObj;
		if (!e) var e = window.event;
		MouseUtil.getPositionEvent(e);
		if (e.target) targetObj = e.target;
		else if (e.srcElement) targetObj = e.srcElement;
		MouseUtil.dragObj(targetObj);
	},
	dragObj : function (eObj) {
		if(this.targetObj) {
			var target = this.targetObj;
			var xNew = this.xPos + this.xDiff;
			var yNew = this.yPos + this.yDiff;
			target.style.left = String(xNew) + 'px';
			target.style.top  = String(yNew) + 'px';
		}
	},
	releaseDrag : function () {
		if(MouseUtil.targetObj) { MouseUtil.targetObj=null; MouseUtil.xDiff=0; MouseUtil.yDiff=0; }
		document.onmousemove = MouseUtil.getPositionEvent;
		document.onmouseup = null;
		document.onmousedown = null;
	},
	falsefunc : function() { return false; }
};
var DateUtil = {
	isNewerDate : function (year,month,day) {
		var result = true;
		if (this.isRealDate(year,month,day)) {
			var compDate = new Date();
			compDate.setFullYear(year,month,day);
			var today = new Date();
			result = (compDate>today);
		} else { result=false; }
		return result;
	},
	isRealDate : function (year,month,day) {
		var result = true;
		var compDay = new Date();
		compDay.setFullYear(year,month);
		var lastDay = this.lastDayOfMonth(compDay);
		if (day<1 || day>lastDay) { result=false; }
		return result;
	},
	lastDayOfMonth : function (dateObj) {
		var days = 31;
		var mon = (dateObj.getMonth() +1);
		if (mon==4 || mon==6 || mon==9 || mon==11) {days = 30;}
		if (mon==2) {days = dateObj.isLeapYear() ? 29 : 28;}
		return days;
	}
};
var AJAX = {
	xhrQueue:{},
	getReqObj: function (key) {
		if(this.xhrQueue[key] == null) {
			this.xhrQueue[key] = this.newReq();
		}
		if (this.xhrQueue[key] != null) {
			return this.xhrQueue[key];
		} else {
			return null;
		}
	},
	newReq: function () {
		return newXHRequest();
	}
};
/* Core library - END */

/** DFormed library  - DScripted Toolkit for JavaScript 
 * @author kdaulton
 */
var DFormed = { // Object Literal
	// LIBRARY CONFIG VARS
	enabled: false,
	errorMessaging: true,
	errorMessageLimit:-1,
	errorMarking: false,
	errorClass: "",
	searchByDef: false,
	// LIBRARY COLLECTIONS
	definitionList: [],
	postProcessQueue : [],
	preProcessQueue :  [],
	
	// DEFINITION FUNCTIONS
	setDefinition: function (strFieldName, arrValidations, strDependency, msgLimit) {
		var def = new Object();
		def.field = String(strFieldName);
		if (arrValidations != null && arrValidations != "" && arrValidations.length > 0)
			def.validations = arrValidations;
		if (strDependency != null && strDependency != "")
			def.dependency = strDependency;
		if (msgLimit != null && msgLimit != "")
			def.msgLimit = Number(msgLimit);
		this.definitionList.push(def);
	},
	getDefinition: function (key) {
		var result = null;
		for (var i=0, j=this.definitionList.length; i<j;i++) {
			var definition=this.definitionList[i];
			if (definition.field == key) { 
				result = definition;
				break;
			}
		}
		return result;
	},
	deleteDefinition: function (key) {
		for (var i=0, j=this.definitionList.length; i<j;i++) { 
			if (this.definitionList[i].field == key) { this.definitionList.splice(i,1); } 
		}
	},
	checkDependency: function (obj, frmName) {
		var result = true;
		if (obj.dependency != null) { 
			result = (frmName[obj.dependency]) ? true : false;
		}
		return result; 
	},
	
	// VALIDATION FUNCTIONS
	addValidation: function (key,obj) { this.getDefinition(key).validations.push(obj); },
	getValidations: function (obj) { return (obj.validations != null ? obj.validations : []); },
	getValidationMsgLimit: function (obj) { return (obj.msgLimit != null ? Number(obj.msgLimit) : -1); },
	deleteValidation: function (obj,strFunction) {
		var list = obj.validations;
		for (var j=0, m=list.length; j<m;j++) { 
			if (list[j].fn == strFunction) { list.splice(j,1); } 
		}
	},
	deleteValidationByKey: function (key,strFunction) { this.deleteValidation(this.getDefinition(key), strFunction); },
	checkCondition : function (conditionStr) { return eval(conditionStr); },
	
	// PRE & POST PROCESS FUNCTIONS
	processQueue : function (arrQueue) {
		var queue = arrQueue;
		for (var i=queue.length; i--;) {
			eval(queue[i]);
		}
	},
	setPostProcess : function (callBackFn) {
		this.postProcessQueue.push(callBackFn);
	},
	postProcess : function () { this.processQueue(this.postProcessQueue);},
	setPreProcess : function (callBackFn) {
		this.preProcessQueue.push(callBackFn);
	},
	preProcess : function () { this.processQueue(this.preProcessQueue) },
	
	// INITIALIZING FUNCTIONS
	init: function () { this.enabled = true; setEvent(window,"load",DFormed.attach); },
	attach: function () {
		var formElements = document.getElementsByTagName("form");
		for(var i=formElements.length; i--;) formElements[i].onsubmit = DFormed.executeEvent;
	},
	disable: function () { DFormed.enabled = false; },
	enable: function () { DFormed.enabled = true; },
	enableErrorHighlights: function (strClassName) { this.errorMarking=true; this.errorClass=strClassName; },
	isValidationEnabled: function () { return this.enabled; },
	setErrorLimit: function (numLimit) { this.errorMessageLimit=Number(numLimit); },
	
	// EXECUTION FUNCTIONS
	executeEvent: function () { return DFormed.execute(this); },
	execute: function (obj) {
		
		DMasked.clearInputMasks();
		this.preProcess();
		
		var result = true;
		if (this.isValidationEnabled() && this.definitionList.length > 0) {
			if (!this.searchForm(obj)) { result = false; DMasked.attach(); }
		}
		if (this.errorMessaging &&  result == false) { DMessaged.pushMsg(); }
		
		if (result) { this.postProcess(); }
		
		return result;
	},
	getFormFields: function (obj) {
		var fieldList = [];
		for(var i=0, j=obj.elements.length; i<j; i++){
			var childElement = obj.elements[i];
			if (childElement.name != undefined && childElement.name != "" && childElement.disabled != true && childElement.type != "hidden") {
				fieldList.push(childElement);
			}
		}
		return fieldList;
	},
	resetFormFields: function (obj) {
		var undef;
		var formObj = obj;
		var fieldList = this.getFormFields(formObj);
		if (fieldList != undef && fieldList.length != undef) {
			DMessaged.clearMsgTargets();
			DMessaged.clearMsgQueue();
			for(var i=0, j=fieldList.length; i<j; i++){
				removeClass(fieldList[i], this.errorClass);
			}
		}
		
	},
	searchFormByDef: function (obj) {
		var result = true;
		var formObj = obj;
		var defList = this.definitionList;
		for(var i=0, j=defList.length; i<j; i++){
			var childElement = formObj[defList[i].name];
			var childResult = this.runDefinitions(formObj,childElement,defList[i].arrValidations);
			if (result) result = childResult;
		}
		return result;
	},
	searchFormByInput: function (obj) { 
		var result = true;
		var formObj = obj;
		var fieldList = this.getFormFields(formObj);
		for(var i=0, j=fieldList.length; i<j; i++){
			var childResult = this.runDefinitions(formObj,fieldList[i]);
			if (result) result = childResult;
		}
		return result;
		
	},
	searchForm: function (obj) {
		if (this.searchByDef) {
			return this.searchByDef(obj);
		} else {
			return this.searchFormByInput(obj);	
		}
	},
	runDefinitions: function(formObj,inputObj,definition) {
		var result = true;
		var inputName = String(inputObj.getAttribute("name"));
		var defObj = (definition != null) ? definition : this.getDefinition(inputName);
		if (defObj != null) {
			result = this.checkDependency(defObj, formObj);
			if (result) {
				var list =  defObj.validations != null ? defObj.validations : [];
				var msgCount = 0;
				var limit = (this.getValidationMsgLimit(defObj) != -1) ? this.getValidationMsgLimit(defObj) : this.errorMessageLimit;
				for (var i=0, j=list.length; i<j; i++) {
					var validation = list[i];
					var checkCondition = true;
					if (list[i].condition != null && list[i].condition != "") { checkCondition = this.checkCondition(list[i].condition);}
					if (result && checkCondition) {
						var fnStr;
						if (list[i].param != null && list[i].param != "") { fnStr = list[i].fn+"(inputObj,\""+list[i].param+"\")"; }
						else { fnStr = list[i].fn+"(inputObj)"; }
						result = eval(fnStr);
					}
					if (this.errorMessaging && !result) {
						if (limit == -1 || (limit > 0 && msgCount < limit)) {
							msgCount++;
							if (list[i].callback != null && list[i].callback != "") 
								eval(String(list[i].callback)+"('"+String(list[i].msg)+"')");
							else
								DMessaged.queueMsg(String(list[i].msg), list[i].target);
						}
					}
					if(this.errorMarking) {
						if(result) { removeClass(inputObj, this.errorClass); }
						else { addClass(inputObj, this.errorClass); }
					}
				}
			}
		}
		return result;
	},
	
	// UTILITY FUNCTIONS
	isFormField: function (obj) { return ((obj.nodeName == "INPUT" || obj.nodeName == "SELECT" || obj.nodeName == "TEXTAREA") && obj.type != "hidden"); },
	getParentFormId: function (obj) {
		return String(this.getParentFormObj(obj).getAttribute("id"));
	},
	getParentFormObj: function (obj) {
		var objParent = obj;
		while (objParent.nodeName != "FORM") objParent = objParent.parentNode;
		return objParent;
	}
};
/* DFormed library - END */

/** DMessaged library  - DScripted Toolkit for JavaScript 
 * @author kdaulton
 */
var DMessaged = { 
	msgQueue: [], targetId: "", msgElement: "", msgHistory: [],
	isPreLoaded: false,
	clearMsgQueue: function () { this.msgQueue = []; },
	init: function (objId, elementType) { this.targetId = objId; this.msgElement = elementType; },
	queueMsg: function (msgTxt,objId) { this.msgQueue.push({"msg":msgTxt, "id":objId }); },
	loadEvent: function () { 
		if(!this.isPreLoaded) {
			setEvent(window,"load", DMessaged.preload);
			this.isPreLoaded = true;
		} 
	},
	preload: function () { DMessaged.pushMsg(); },
	pushMsg: function () {
		this.clearMsgTargets();
		var messages = this.msgQueue;
		for (var i=0, j=messages.length; i<j;i++) {
			if (messages[i].msg != "") {
				var actualTarget;
				if(messages[i].id) { 
					actualTarget= document.getElementById(messages[i].id);
				} else { 
					actualTarget= document.getElementById(this.targetId);
				}
				var text = document.createElement(this.msgElement);
				text.innerHTML = messages[i].msg;
				actualTarget.appendChild(text);
				actualTarget.style.display = "block";
				this.msgHistory.push(actualTarget);
			}
		}
		if(messages.length > 0)	{ window.scrollTo(0,0); }
		this.clearMsgQueue();
	},
	clearMsgTargets: function () {
		for (var i=0, j=this.msgHistory.length; i<j;i++) {
			var target = this.msgHistory[i];
			target.innerHTML = "";
			target.style.display = "none";
		}
		this.msgHistory = [];
	}
};
/* DMessaged library - END */

/** DMasked library  - DScripted Toolkit for JavaScript 
 * @author kdaulton
 */
var DMasked = { 
	enabled: false,
	maskList: [],
	addMask: function (strClassName,mask,callbackFn) { 
		if (strClassName.trim() != "" && mask.trim() != "" ) this.maskList.push({"name":strClassName,"mask":mask,"callbackFn":callbackFn});
	},
	getMask: function (key) {
		if(key.indexOf(" ") > -1) { return this.getMaskByKeyList(key); }
		else { return this.getMaskByKey(key); }
	},
	getMaskByKey: function (key) {
		var result = null;
		for (var i=0, j=this.maskList.length; i<j; i++) {
			if (this.maskList[i].name == key) result = this.maskList[i].mask;
		}
		return result;
	},
	getMaskByKeyList: function (key) {
		var keyList = key.split(" ");
		var result = null;
		for (var i=0, j=keyList.length; i<j; i++) {
			var maskResult = this.getMaskByKey(keyList[i]);
			if (maskResult != null && maskResult != "") result = maskResult;
		}
		return result;
	},
	init: function () { this.enabled = true; setEvent(window,"load",DMasked.attach); },
	attach: function () { 
		if(DMasked.maskList.length > 0) {
			var root = document.getElementsByTagName('body')[0];
			for (var i=DMasked.maskList.length; i--;) {
				var maskDef = DMasked.maskList[i];
				var elementList = $extend(root).getElementsByClassName(maskDef.name);
				for (var j=elementList.length; j--;) {
					var targetObj = elementList[j];
					if (targetObj.nodeName == "INPUT") { 
						targetObj.format = maskDef.mask;
						targetObj.callback = (maskDef.callbackFn) ? maskDef.callbackFn : "";
						//targetObj.onkeyup = DMasked.maskField;
						var oldEvent = targetObj.onkeyup ? targetObj.onkeyup : null;
						targetObj.onkeyup = function(){};
						setEvent(targetObj,"keyup",DMasked.maskField);
						if (oldEvent) {
							setEvent(targetObj,"keyup",oldEvent);
						}
						DMasked.executeMask(targetObj);
					} 
					else { DMasked.maskText(targetObj, maskDef.mask); }
				}
			}
		}
	},
	maskField: function (e) {
		var targetObj;
		if (!e) var e = window.event;
		if (e.target) targetObj = e.target;
		else if (e.srcElement) targetObj = e.srcElement;
		var mask = DMasked.getMask(targetObj.className);
		if (mask != null) {
			DMasked.executeMask(targetObj);
		}
	},
	executeMask: function (inputObj) {
		var inputFormat = inputObj.format;
		var inputValue = inputObj.value.replace(/\D/g,'');
		if (inputObj.callback) { inputValue = eval(inputObj.callback+"(inputValue)"); }
		var inputValueCount=0,finalNumber='';
		if (inputObj.value.length>0){
			for (var count=0, j=inputFormat.length; count<j;count++){
				var nextChar ="";
				if (inputFormat.charAt(count)=='~') {
					nextChar = inputValue.charAt(inputValueCount++);
				} else {
					if (inputValueCount<inputValue.length) {
						nextChar = inputFormat.charAt(count);
					}
				}
				finalNumber+=nextChar;
				if (inputValueCount>inputValue.length) { break; }
			}
		}
		
		inputObj.value=finalNumber;
	},
	maskText: function (targetObj, formatType) {
		var targetText = targetObj.innerHTML.replace(/\D/g,'');
		if (targetText != "") {
			var inputFormat=formatType;
			var targetTextCount=0,finalNumber='';
			if (targetText.length>0){
				for (var count=0, j=inputFormat.length; count<j;count++){
					finalNumber+=(inputFormat.charAt(count)=='~')?targetText.charAt(targetTextCount++):inputFormat.charAt(count);
					if (targetTextCount>targetText.length) break;
				}
			}
			targetObj.innerHTML = finalNumber;
		}
	},
	clearInputMasks: function () {
		if(DMasked.maskList.length > 0) {
			var root = document.getElementsByTagName('body')[0];
			for (var i=DMasked.maskList.length; i--;) {
				var elementList = $extend(root).getElementsByClassName(DMasked.maskList[i].name);
				for (var j=elementList.length; j--;) { 
					if (elementList[j].nodeName == "INPUT" && elementList[j].value != "") { 
						elementList[j].value = elementList[j].value.replace(/\D/g,'');
					}
				}
			}
		}
	}
};
/* DMasked library - END */
