﻿// CMS3: Module common

// docOnClick_taskList
// This array contains a task list of functions to perform on document click.
// Task list is built of trio of values: [0] = function reference, [1] = task priority, [2] = task name
var docOnClick_taskList = new Array();
var DocOnClick;

function Init() {
	if (document.getElementById("modloading") != null) {
		document.getElementById("modloading").style.display = "none";
	}
	DocOnClick = new DocumentOnClick();
	try {
		SetTextAreaLimiters();
	} catch(e) {}
	// Try to reset the session
	try {
		if (typeof top.__SessionHandler != "undefined") {
			top.__SessionHandler.Reset();
		}
	} catch(e) {
	}
}

function Wstatus(message) {
	try {
		if (typeof message == "string") {
			top.status = message;
		} else {
			if (typeof message.alt != "undefined") {
				top.status = message.alt;
			} else if (typeof message.title != "undefined") {
				top.status = message.title;
			}
		}
	} catch(e) {
	}
}

function TogglePageTools(who) {
	var tools = document.getElementById("pt_coll");
	if (tools.className == "PageTools_Collapsible_Open") {
		tools.className = "PageTools_Collapsible_Closed";
		who.src = who.src.replace("collapse.gif","restore.gif");
		who.alt = "Restore this block";
		who.title = "Restore this block";
	} else {
		tools.className = "PageTools_Collapsible_Open";
		who.src = who.src.replace("restore.gif","collapse.gif");
		who.alt = "Collapse this block";
		who.title = "Collapse this block";
	}
}

/* Document onClick queue handlers */

function _taskSort(a,b) {
	return (a[1] - b[1]);
}

function DocumentOnClick() {
	this.Add = function(taskid,functionref,optPriority) {
		// This method adds a function reference to the queue.
		// functionref can be either a reference to the function object or a string which will be EVALed.
		// If optMakeFirst is not defined, the reference is added at the bottom of the queue, getting the next available ID
		if ((typeof functionref != "function" && typeof functionref != "string") || typeof taskid != "string") {
			return false;
		}
		if (typeof optPriority == "undefined" || optPriority == null) {
			docOnClick_taskList.push(new Array(functionref,docOnClick_taskList.length,taskid));
		} else {
			// optPriority is defined. The task is added with the proper priority, while the existing tasks with the same priority and lower move down one level
			var newprior = optPriority;
			for (var i=0;i<docOnClick_taskList;i++) {
				if (docOnClick_taskList[i][1] >= newprior) {
					docOnClick_taskList[i][1]++;
				}
			}
			docOnClick_taskList.push(new Array(functionref,docOnClick_taskList.length,taskid));
		}
		// Sort the task array
		if (docOnClick_taskList.length > 1) docOnClick_taskList.sort(_taskSort);
	}
	this.Remove = function(taskid) {
		// Locate the task
		var remindex = null;
		for (var i=0;i<docOnClick_taskList.length;i++) {
			if (docOnClick_taskList[i][2].toUpperCase() == taskid.toUpperCase()) {
				remindex = i;
				break;
			}
		}
		if (remindex == null) return false;
		// Remove the task
		var oldprio = docOnClick_taskList[remindex][1];
		docOnClick_taskList.splice(remindex,1);
		// Move all subsequent task priorities one level up
		for (var i=0;i<docOnClick_taskList.length;i++) {
			if (docOnClick_taskList[i][1] <= oldprio) {
				docOnClick_taskList[i][1]--;
			}
		}
		// Sort the task array
		if (docOnClick_taskList.length > 1) docOnClick_taskList.sort(_taskSort);
	}
	this.RunTasks = function(ev) {
		for (var i=0;i<docOnClick_taskList.length;i++) {
			var ref = docOnClick_taskList[i][0];
			if (typeof ref == "function") try { ref(ev); } catch(e) {}
			if (typeof ref == "string") try { eval(ref); } catch(e) {}
		}
	}
	document.body.onclick = this.RunTasks;
}

/* Parent relations */

function hasParent(who,papa) {
	if (who == papa) return true;
	var current = who;
	while (1 == 1) {
		if (current == document.body) return false;
		if (current == papa) return true;
		current = current.parentNode;
	}
	return false;
}

/** Element retrieval **/

function getElementsByPartialID(partid,optParent) {
	// Returns all elements who's IDs either equal or contain the partid value
	// optParent is used internally, or can be used to find elements which are childnodes of the specified object
	var res = new Array();
	if (typeof optParent == "undefined" || optParent == null) {
		var p = document.body;
	} else {
		var p = optParent;
	}
	if (typeof p.id != "undefined" && p.id.indexOf(partid)>-1) res.push(p);
	if (typeof p.childNodes != "undefined" && p.childNodes != null) {
		for (var j=0;j<p.childNodes.length;j++) {
			var subs = getElementsByPartialID(partid,p.childNodes[j]);
			for (var i=0;i<subs.length;i++) res.push(subs[i]);
		}
	}
	return res;
}

function getElementsByClass(classname,optParent) {
	// Returns all elements who's class either equal or contain the partid value
	// optParent is used internally, or can be used to find elements which are childnodes of the specified object
	var res = new Array();
	if (typeof optParent == "undefined" || optParent == null) {
		var p = document.body;
	} else {
		var p = optParent;
	}
	if (typeof p.className != "undefined" && p.className.indexOf(classname)>-1) res.push(p);
	if (typeof p.childNodes != "undefined" && p.childNodes != null) {
		for (var j=0;j<p.childNodes.length;j++) {
			var subs = getElementsByClass(classname,p.childNodes[j]);
			for (var i=0;i<subs.length;i++) res.push(subs[i]);
		}
	}
	return res;
}

/* Item list rendering */

function RenderItemsByTemplate(targetContainer,tplId,dataSource,placeholderLayout,optEmptyTemplate,optHeader,optFooter) {
	// This function fills the contents of the targetContainer with instances of template (as specified by the tplId parameter).
	// The data filling is according to the data provided by the dataSource array parameter.
	// The list of placeholders to be replaced with data must be laid out in the placeholderLayout array, in the same order as the data appears in the dataSource.
	// targetContainer can accept either the ID of the container, or reference to it's DOM object.
	// tplId can accept an ID of the HTML container which holds the template as it's innerHTML or Value
	
	// There are 2 reserved placeholders: [__index_1_based] and [__index_0_based] which render as the item's position 1 or 0 based, accordingly.
	
	// optEmptyTemplate provides an optional fixed string with the content to be filled into the targetContainer if the dataSource has no items.
	// optHeader provides a string to be written before any items are rendered
	// optFooter privides a string to be written after all items have been rendered
	
	// Check inputs
	if (typeof targetContainer == "undefined" || typeof tplId  == "undefined" || typeof dataSource == "undefined") return false;
	
	// Fetch container
	if (typeof targetContainer == "string") {
		var cont = document.getElementById(targetContainer);
	} else {
		var cont = targetContainer;
	}
	if (Undefined(cont) == true) return false;
	
	// Fetch template
	var tryTemp = document.getElementById(tplId);
	if (typeof tryTemp == "undefined" || tryTemp == null) {
		// Not a valid ID
		var template = tplId;
	} else {
		if (typeof tryTemp.value == "undefined") {
			var template = tryTemp.innerHTML;
		} else {
			var template = tryTemp.value;
		}
	}

	if (typeof placeholderLayout == "undefined" || placeholderLayout == null) {
		// Try to fetch the placeholder template from the dataLayout attribute of the tplId container
		if (tryTemp.getAttribute("datalayout") != null) {
			var pll = tryTemp.getAttribute("datalayout").split(",");
		} else {
			return false;
		}
	} else {
		if (typeof placeholderLayout == "string") {
			pll = placeholderLayout.split(",");
		} else {
			pll = placeholderLayout;
		}
	}	

	// Create items.
	if (dataSource.length == 0) {
		if (typeof optEmptyTemplate == "undefined" || optEmptyTemplate == "" || optEmptyTemplate == null) {
			var newHTML = "";
		} else {
			var newHTML = optEmptyTemplate;
		}
	} else {
		var newHTML = "";
		for (var i=0;i<dataSource.length;i++) {
			try {
				var str = String(decodeURI(template));
			} catch(e) {
				var str = String(template);
			}
			for (var j=0;j<pll.length;j++) {
				try {
					str = str.Replace(pll[j],dataSource[i][j]);
				} catch(e) {
					str = str.Replace(pll[j],"#");
				}
			}
			str = str.Replace("[__index_1_based]",String(i+1));
			str = str.Replace("[__index_0_based]",i.toString());
			newHTML += str;
		}
	}
	// Add header / footer, if any or both present
	if (typeof optHeader != "undefined" && optHeader != null) newHTML = String(optHeader) + newHTML;
	if (typeof optFooter != "undefined" && optFooter != null) newHTML += String(optFooter);
	// Put the rendered HTML
	cont.innerHTML = newHTML;
}

function RenderItemsByTemplates(targetContainer,tplId,altTplId,altDataPoint,altDataValue,dataSource,placeholderLayout,optEmptyTemplate,optHeader,optFooter) {
	// This function fills the contents of the targetContainer with instances of template (as specified by the tplId parameter).
	// The data filling is according to the data provided by the dataSource array parameter.
	// The list of placeholders to be replaced with data must be laid out in the placeholderLayout array, in the same order as the data appears in the dataSource.
	// targetContainer can accept either the ID of the container, or reference to it's DOM object.
	// tplId can accept an ID of the HTML container which holds the template as it's innerHTML or Value
	
	// There are 2 reserved placeholders: [__index_1_based] and [__index_0_based] which render as the item's position 1 or 0 based, accordingly.
	
	// optEmptyTemplate provides an optional fixed string with the content to be filled into the targetContainer if the dataSource has no items.
	// optHeader provides a string to be written before any items are rendered
	// optFooter privides a string to be written after all items have been rendered
	
	// Check inputs
	if (typeof targetContainer == "undefined" || typeof tplId  == "undefined" || typeof dataSource == "undefined") return false;
	
	// Fetch container
	if (typeof targetContainer == "string") {
		var cont = document.getElementById(targetContainer);
	} else {
		var cont = targetContainer;
	}
	if (Undefined(cont) == true) return false;
	
	// Fetch template
	var tryTemp = document.getElementById(tplId);
	if (typeof tryTemp == "undefined" || tryTemp == null) {
		// Not a valid ID
		var template = tplId;
	} else {
		if (typeof tryTemp.value == "undefined") {
			var template = tryTemp.innerHTML;
		} else {
			var template = tryTemp.value;
		}
	}
	// Fetch template
	var tryTemp = document.getElementById(altTplId);
	if (typeof tryTemp == "undefined" || tryTemp == null) {
		// Not a valid ID
		var alttemplate = tplId;
	} else {
		if (typeof tryTemp.value == "undefined") {
			var alttemplate = tryTemp.innerHTML;
		} else {
			var alttemplate = tryTemp.value;
		}
	}

	if (typeof placeholderLayout == "undefined" || placeholderLayout == null) {
		// Try to fetch the placeholder template from the dataLayout attribute of the tplId container
		if (tryTemp.getAttribute("datalayout") != null) {
			var pll = tryTemp.getAttribute("datalayout").split(",");
		} else {
			return false;
		}
	} else {
		if (typeof placeholderLayout == "string") {
			pll = placeholderLayout.split(",");
		} else {
			pll = placeholderLayout;
		}
	}	

	// Create items.
	if (dataSource.length == 0) {
		if (typeof optEmptyTemplate == "undefined" || optEmptyTemplate == "" || optEmptyTemplate == null) {
			var newHTML = "";
		} else {
			var newHTML = optEmptyTemplate;
		}
	} else {
		var newHTML = "";
		for (var i=0;i<dataSource.length;i++) {
			var usealt = (dataSource[i][altDataPoint] == altDataValue);
			try {
				var str = (usealt == true)?String(decodeURI(alttemplate)):String(decodeURI(template));
			} catch(e) {
				var str = (usealt == true)?String(alttemplate):String(template);
			}
			for (var j=0;j<pll.length;j++) {
				try {
					str = str.Replace(pll[j],dataSource[i][j]);
				} catch(e) {
					str = str.Replace(pll[j],"#");
				}
			}
			str = str.Replace("[__index_1_based]",String(i+1));
			str = str.Replace("[__index_0_based]",i.toString());
			newHTML += str;
		}
	}
	// Add header / footer, if any or both present
	if (typeof optHeader != "undefined" && optHeader != null) newHTML = String(optHeader) + newHTML;
	if (typeof optFooter != "undefined" && optFooter != null) newHTML += String(optFooter);
	// Put the rendered HTML
	cont.innerHTML = newHTML;
}

/** ENTER Keypress checkup function **/

function CheckEvent13(ev,func) {
	var isIE = false;
	if (navigator.appName.indexOf("Microsoft") > -1 || navigator.appName.indexOf("IE") > -1) {
		isIE = true;
	}
	if ((isIE && event.keyCode == 13) || (!isIE && ev.which == 13)) {
		if (isIE) {
			event.cancelBubble = true;
		} else {
			ev.preventDefault();
			ev.stopPropagation();
		}
		return func();
	}
}

/** Global service functions **/

function Undefined(obj) {
	if (typeof obj == "undefined" || obj == null) return true;
	return false;
}

function Default(obj,defValue) {
	// Returns defValue in case obj is undefined or null
	if (Undefined(obj) == true) return defValue; else return obj;
}

/** Other service functions **/

function frmPageSearch() {
	var strSearchTextBox = document.getElementById("txtSearch");
	if (strSearchTextBox.value == "")
	{
		alert("יש להזין מילת חיפוש");
		strSearchTextBox.focus();
		return false;
	}
	var btn = document.getElementById("btnSearch");
	btn.click();
	return false;
}

function clearSearchResults() {
	var strSearchPhrase = document.getElementById("hdnFilterString");
	var strSearchTextBox = document.getElementById("txtSearch");
	strSearchTextBox.value = "";
	var btn = document.getElementById("btnSearch");
	btn.click();
}

/** Textarea limiter **/

function TextAreaLimiter(ev) {
	try {
		if (typeof ev == "undefined") {
			var s = event.srcElement; 
		} else {
			var s = ev.target;
		}
		var lim = s.getAttribute("YkMaxLength");
		if (lim == null) return;
		var nlim = Number(lim);
		if (s.value.length > nlim) {
			// Overflow, cut
			if (typeof ev == "undefined") {
				event.cancelBubble = true;
			} else {
				ev.stopPropagation();
				ev.preventDefault();
			}
			s.value = s.value.substr(0,nlim);
			return false;
		}
	} catch(e) {
	}
}

function SetTextAreaLimiters() {
	var all_ta = document.getElementsByTagName("textarea");
	for (var i=0;i<all_ta.length;i++) {
		if (all_ta[i].getAttribute("YkMaxLength") != null) {
			// Has limiter
			all_ta[i].onchange = TextAreaLimiter;
			all_ta[i].onkeyup = TextAreaLimiter;
			all_ta[i].onkeypress = TextAreaLimiter;
			all_ta[i].onkeydown = TextAreaLimiter;
		}
	}
}

/** Prototypes */

Array.prototype.AddItems = function(resultFormattedString,optItemDelimiter,optPropDelimiter,optDuplicateContainer) {
	// This method breaks the properly formatted result string and adds the data arrays into the __results array.
	// The string must be formed of "~#~"-separated items (or any other, defined by the optItemDelimiter parameter).
	// Each item contains values (properties) separated by "~!~" (or any other, defined by the optPropDelimiter).
	
	// optDuplicateContainer is an optional reference to another array, which contains items of the similar structure. When this
	// parameter is provided, only the items that are NOT present in the optDuplicateContainer array will be added.
	
	// In case of Result-Selection ASCX, the following layout must be kept:
	// First value of the block is always the ID of the item.
	// Second value is always the textual representation of the item.
	// Third value (when present) is always an URL of the relevant external resource.
	if (typeof resultFormattedString == "undefined" || resultFormattedString == null || resultFormattedString == "") return;
	
	var blkd = Default(optItemDelimiter,"~#~");
	var itmd = Default(optPropDelimiter,"~!~");
	
	var blocks = resultFormattedString.split(blkd);
	for (var i=0;i<blocks.length;i++) {
		var items = blocks[i].split(itmd);
		if (typeof optDuplicateContainer != "undefined" && optDuplicateContainer != null) {
			// Check if item is already present in the selection list
			if (optDuplicateContainer.ItemPresent(items) == false) {
				this.push(items);
			}
		} else {
			this.push(items);
		}
	}
}

Array.prototype.Clear = function() {
	// This method clears the entire array of data
	this.splice(0,this.length);
}

Array.prototype.ItemPresent = function(obj) {
	// This method scans the array. Returns TRUE if the specified object is found int eh array.
	for (var i=0;i<this.length;i++) {
		if (this[i].join(":") == obj.join(":")) return true;
	}
	return false;
}

Array.prototype.ItemIndex = function(obj) {
	for (var i=0;i<this.length;i++) {
		if (this[i].join(":") == obj.join(":")) return i;
	}
	return null;
}

Array.prototype.FindNestedArrayWithValue = function(seekArray) {
	// This function scans the array for values, which are themselves of the Array type.
	// In case there is such a value, with an inner value(s) corresponding to the one(s) provided, the parent index is returned.
	// If the item is not found, null is returned.
	// seekArray is an Array with the matching structure as the one being seeked, while the irrelevant values are set as NULL, and the relevant ones
	// are filled with the proper value. For example, if we need to find a nested array of 5 values, with the first value of 10, and third value of 15,
	// the seekArray will have to look like this: [10,null,15,null,null].
	for (var i=0;i<this.length;i++) {
		if (typeof this[i].length != "undefined" && typeof this[i].length != "string" && this[i] != null) {
			// Item is probably an array
			var res = true;
			for (var j=0;j<seekArray.length;j++) {
				if (seekArray[j] != null) {
					if (seekArray[j] != this[i][j]) {
						res = false; break;
					}
				}
			}
			if (res == true) return i;
		}
	}
	return null;
}

Array.prototype.MoveItemUp = function(obj) {
	var myindex = this.ItemIndex(obj);
	if (myindex == 0) return;
	var tempval = this[myindex - 1];
	this[myindex - 1] = this[myindex];
	this[myindex] = tempval;
}

Array.prototype.MoveItemDown = function(obj) {
	var myindex = this.ItemIndex(obj);
	if (myindex == (this.length-1)) return;
	var tempval = this[myindex + 1];
	this[myindex + 1] = this[myindex];
	this[myindex] = tempval;
}

String.prototype.Replace = function(seek,repl) {
	var temp = this.split(seek);
	var newstr = temp[0];
	for (var i=1;i<temp.length;i++) {
		newstr += (repl + temp[i]);
	}
	return newstr;
}

