/*	DataNavigator HeuvelTop Webapplication development framework
 *	(c) 2002-2010 HeuvelTop; Frank van den Heuvel
 *
 *	version: 2.0.1
 *
 *	Designed, tailor made set of javascript tools for client side support of DataNavigator.
 *
 *	makew3cid: to strip not for id or name allowed chars from a string
 *	onSubmitPost2: for building the Ajax.updater to post form results and get new content
 *	registerOnCompleteEvent: child registers with parent to recieve dn:oncomplete events
 *	setProgressIcon: add a Ajax updater in progress Icon to an element
 *	dn_open_form: create a new div block or iframe to contain a form, show any prexisting form with the same id
 *	dn_open_childform: for including childforms
 *	dn_open_div: limited edition of dn_open_form only creates div's used to store previous retrieved results
 *	stripMyValue: sanitize a string according to a regex
 *	switchFocus: switch focus to another element on an array of keycodes
 *	resize_to_fit: fit window around its contents.
 *	dn_form_Popup: open a pop up window from control or button
 *	dn_closePopUps: close lists of pop up windows
 *	dn_checkboxToggle: helper function for dn_checkbox
 */
/**
 *	W3C: ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by 
 *	any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), 
 *	and periods (".").
 *	Strips any non applicable char from the string. 
 *	You yourself should make shure to start with [A-Za-z] and be careful that there are no resulting conflicting id's
 */
function makew3cid(noid) {
	return noid.gsub(/[^A-Za-z0-9\-_:\.]/, '');
}

/**
 *	Gather form data and post it to the form.action
 *	Delayed posting when the form is not visible.
 *	Close all modal pop up's
 *	Confirm before delete of record
 *	prevent queing of events on the same form (multiple or double clicking)
 */
function onSubmitPost2(formid, submitid, setvalue) {
	if ( $(submitid) ) {
		$(submitid).value = setvalue;
		if ( submitid.startsWith('dn_tb_submit') && (setvalue == 'erase' || setvalue == 'delete') ) {
			if ( confirm('Record verwijderen?') == false) return false;
		}
	}
	var aform = $(formid);
	// update form
	if ( $($(aform.ancestors()).first()).visible() ) {
		// prevent event queues on the same form
		if ( aform.retrieve('activeRequestCount', 0) > 0 ) {
			alert('Wacht u even tot de lopende opdracht is afgehandeld?');
			return false;
		}
		// add progress icon
		var icon = setProgressIcon();
		if ( $(aform.select('tr.dn_toolbar > td > div')).size() > 0 ) {
			$(aform.select('tr.dn_toolbar > td > div')).first().appendChild(icon);
		} else if ( $(aform.select('div.dn_toolbar')).size() > 0 ) {
			$($(aform.select('div.dn_toolbar')).first()).appendChild(icon);
		}
		aform.store('activeRequestCount', aform.retrieve('activeRequestCount', 0) + 1);
		dn_closePopUps(modalItems);
		endTinyMCE(aform); // cleanup tinyMCE editors
		new Ajax.Updater(formid, aform.readAttribute('action'), {
			evalScripts: true,
			parameters: aform.serialize(true),
			onCreate: function(t) {
				aform.disable();
			},
			onSuccess: function(t) {
				aform.store('activeRequestCount', aform.retrieve('activeRequestCount', 0) - 1);
				aform.enable();
				aform.fire('dn:oncomplete');
				focusForm(aform);
			},
			onFailure: function(t) {
				aform.store('activeRequestCount', aform.retrieve('activeRequestCount', 0) - 1);
				aform.enable();
				if (confirm('Foutmelding: ' + t.status + ' Opnieuw proberen?') == true) {
					onSubmitPost2(formid, submitid, setvalue);
				}
			}
		});
	} else {
		// delayed execution
		aform.store('isDirty', 'delayed');
	}
	return aform;
}

/*
 *	register defaultaction for a form
 */
function setDefaultAction(formid, submitid, action) {
	if ( $(formid) ) {
		$(formid).store('defaultAction', action);
		$(formid).store('submitid', submitid);
	} else {
		alert('formid: '+ formid + ' not found for setDefaultAction!');
	}
}

/**
 *	Register this as event handler for calling the default action of a form
 *	it will find the form and what to submit. The form will need the attributes
 *	defaultAction and submitid to be set.
 *	Only executed on ENTER when the originating control is not an textarea or select
 *	The handled event is cancelled (to stop bubbling and allow for multiple registration of this handler).
 */
function defaultSubmit4(event) {
	if ( (event.which || event.keyCode) == Event.KEY_RETURN ) {
		var origin = event.element();
		if ( origin.tagName.toLowerCase() == 'select' || origin.tagName.toLowerCase() == 'textarea') return ;
		var aform = event.findElement('form');
		if ( aform ) {
			var action = aform.retrieve('defaultAction', false);
			var submitid = aform.retrieve('submitid', false);
			if ( action && submitid ) {
				event.stop();
				if ( action == 'save' && confirm('Wilt u de gegevens opslaan?') == false ) return ;
				onSubmitPost2(aform.identify(), submitid, action);
			}
		}
	}
}

/**
 *	bring focus to the right control
 */
function focusForm(formid) {
	var aform = $(formid);
	if ( aform ) if ( aform.findFirstElement() ) aform.focusFirstElement();
}

/**
 *	dn:oncomplete events are used to cascade the changes of a parent down to child forms
 */
function registerOnCompleteEvent(parent, child) {
	var parentform = $($(parent).select('form')).first();
	if ( $(parentform) ) {
		var childform = $($(child).select('form')).first();
		if ( $(childform) ) {
			$(parentform).observe('dn:oncomplete', function(event) {
				onSubmitPost2(childform, '', '');
			});
		}
	}
}

/**
*	create an img element with a progress icon and contain it in a div with text-align: xenter;
 *	into (optional) is the element that will contain de icon.
 *	return the img component (without the div). 
 */
function setProgressIcon(into) {
	var image = new Element('img', { 'src' : '/dn/images/icons/progress.gif' });
	if ( $(into) ) {
		var progress = new Element('div', { 'style' : 'text-align: center; margin: auto;'});
		progress.appendChild(image);
		$(into).appendChild(progress);
	}
	return image;
}

/**
 *	hide the current form (container)
 *	at first call append a container to the body and update the contents with the results of the link
 *	at following calls show the container
 *	When link is not based on dn_form.php create an IFRAME and open the link within the IFRAM.
 *	The IFRAME is dimensioned on the viewport.
 *	@PARAM link is both the id of the container and the first URL to create the contents with
 */
function dn_open_form(link) {
	// reserved words
	if ( link.startsWith('redirect:') ){
		url = link.sub('redirect:', '', 1);
		window.location = url;
		return false;
	}
	$$('div.dn_container').invoke('hide');
	linkid = makew3cid(link);
	if ( $(linkid) ) {
		$(linkid).show();
	} else {
		var dn = new Element('div', { 'class' : 'dn_container', 'id' : linkid });
		if ( $('dn_content') ) 
			$('dn_content').appendChild(dn);
		else 
			$(document.body).appendChild(dn);
		if ( link.startsWith('dn_form.php?') ){
			setProgressIcon(dn);
			new Ajax.Updater(dn, link, {
				evalScripts: true,
				onSuccess: function(t) {
					focusForm(dn.select('form').first());
				},
				onFailure: function(t) {
					dn.remove();
				}
			});
		} else { 
			// open external link in iframe
			var frame = new Element('iframe',
				{ 'frameborder' : '0',  'vspace' : '0', 'hspace' : '0', 'marginwidth' : '0',
				'marginheight' : '0', 'width' : '850', 'scrolling' : 'auto', 'height' : '600', 'src' : link });
			dn.appendChild(frame);
			frame.observe('load', function(event) {
				var dims = document.viewport.getDimensions();
				dims.height -= dn.positionedOffset().top;
				dims.height -= 35;
				dims.width -= 35;
				dims.height += 'px';
				dims.width += 'px';
				frame.setStyle(dims);
			});
		}
	}
	return linkid;
}

/**
 *	Similar to dn_open_form but for child forms includes updating of tab bar.
 *	When clicking an already active tab just hide.
 *	Otherwise hide all childs and make all tabs passive.
 *	Activate the new current tab
 *	If non existent childform create container and call Ajax.Updater
 *	else show the previously created childform
 */
function dn_open_childform(tab, parentid, childurl) {
	var childid = makew3cid(childurl);
	parentid = makew3cid(parentid);
	if ( $(tab).hasClassName('tabActive') ) {
		// child form must have preexisted: hide it now
		$(tab).className = 'tabPassive';
		$(childid).hide();
	} else {
		// hide open childforms
		$(tab).adjacent('td.tabActive').each(function(s) { $(s).className = 'tabPassive'});;
		$(tab).className = 'tabActive';
		//hide only first level children: fix hidden subchild bug
		$(parentid).childElements('div.dn_childcontainer').each(function (el) {
			if ( $(el).hasClassName('dn_childcontainer') ) $(el).hide();
		});
		// find childform and show or create a new one
		if ( $(childid) ) {
			$(childid).show();
			var childform = $(childid).select('form').first();
			if ( $(childform).retrieve('isDirty', false) ) {
				childform.store('isDirty', false);
				onSubmitPost2(childform, '', '');
			}
			// fix hidden child bug
			if ( $(childid).childElements('div.dn_childcontainer').size() == 1 ) {
				$(childid).childElements('div.dn_childcontainer').first().show();
			}
		} else {
			// the first time to open this childurl
			var dn = new Element('div', { 'class' : 'dn_childcontainer', 'id' : childid });
			$(parentid).appendChild(dn);
			setProgressIcon(dn);
			new Ajax.Updater(dn, childurl, {
				evalScripts: true, 
				onComplete: function(t) {
					registerOnCompleteEvent(parentid, childid);
					focusForm(dn.select('form').first());
				},
				onFailure: function(t) {
					dn.remove();
				}
			});
		}
	}
	return $(childid);
}

/**
 *	Limited edition of dn_open_form
 *	Hides all div with class = dn_div 
 *	Show an existing one for link
 *	When not exists create new one and fill with link by calling ajaxupdater for link.
 */
function dn_open_div(link) {
	$$('div.dn_div').invoke('hide');
	linkid = makew3cid(link);
	if ( $(linkid) ) {
		$(linkid).show();
	} else {
		var dn = new Element('div', { 'class' : 'dn_div', 'id' : linkid });
		document.body.appendChild(dn);
		new Ajax.Updater(dn, link, {
			evalScripts: true
		});
	}
	return $(link);
}

/**
 *	Find the source element of the event and strip its value of anything that matches the regex
 */
function stripMyValue(event, regex) {
	source = event.element();
	if ( source.value.match(regex) ) {
		source.value = source.value.gsub(regex, '');
	}
	return true;
}

/**
 *	switch focus to another element for keyCodes stored in array forkeys
 */
function switchFocus(event, to, forkeys) {
	//alert('Got: ' + event.keyCode + ' Character was ' + String.fromCharCode(event.keyCode));
	// this test shows fromCharCode(keyCode) is complete bogus
	if ( $A(forkeys).indexOf(event.which || event.keyCode) != -1 ) {
		event.stop();
		$(to).activate();
	}
}

/**
 *	resize the current window to fit the contents
 */
function resize_to_fit(el) {
	if ( $(el) ) window.resizeTo($(el).getWidth(), $(el).getHeight());
}

/**	
 *	Opens or refreshes a pop up window
 *	link: URL of the document to load into the (new) window
 *	WindowName: name to assign to the new window, or to find the window already open
 *	FormType:
		modal: has a onBlur event to keep focus
		dialog: returns value, floats on top and is resizable
		console: resizable with scrollbars (=application window)
		full: browser window
 *	WindowHeight, WindowWidth:
 *	ConfirmMsg: text to ask user to confirm before opening the popup
 */
var popupItems = new Array;
var modalItems = new Array;
function dn_form_Popup(link, WindowName, FormType, WindowHeight, WindowWidth, ConfirmMsg) {
	var Options;	// String
	var I;		// Object
	var el;		// element pointer

	Options="alwaysraised,height=" + WindowHeight + ",width=" + WindowWidth;
	switch(FormType) {
		case "modal":
			Options+= ",dependent";
			break;
		case "dialog":
			Options+= ",dependent,resizable";
			break;
		case "console":
			Options+= ",resizable,scrollbars";
			break;
		case "full":
			Options+= ",toolbar,menubar,scrollbars,resizable,location";
			break;
	}
	if ( ConfirmMsg.length == 0 || confirm(ConfirmMsg) == true ) {
		I = window.open(link, WindowName, Options);
		I.focus();
		switch(FormType) {
			case "modal":
			case "dialog":
				modalItems.push(I);
				break;
			default:
				popupItems.push(I);
				break;
		}
		return I;
	}
	return false;
}

function dn_closePopUps(wList) {
	var w;
	if ( $A(wList) ) {
		$A(wList).each(function(w) {
			if ( $(w) ) $(w).close();
		});
		$A(wList).clear();
	}
}

/**
 *	Opens or refreshes an iframe within a div
 *	title: a captionstring
 *	parentform: the element or the id of the form that will contain the created popup
 *	link: URL of the document to load into the (new) window
 *	iframeid: name to assign to the iframe
 *	WindowHeight, WindowWidth:
 *	ConfirmMsg: text to ask user to confirm before opening the popup
 */
function dn_control_Popup(title, parentform, link, frameid, WindowHeight, WindowWidth, ConfirmMsg) {
	var newframe;
	var top;
	var left;
	var framestyle;
	var popWin;
	var popCap;
	var closeButton;
	
	if ( $(frameid) ) {
		$(frameid).show();
		$(frameid).focus();
	} else
	if ( ConfirmMsg.length == 0 || confirm(ConfirmMsg) == true ) {
		if ( $(parentform) ) {
			var lo = $(parentform).getLayout();
			top = (lo.get('height') - WindowHeight) / 3 + lo.get('top');
			left = (lo.get('width') - WindowWidth) / 2;
		} else {
			top = (document.viewport.getHeight() - WindowHeight) / 3;
			left = (document.viewport.getWidth() - WindowWidth) / 2;
		}
		framestyle = '';
		framestyle += 'top:' + top + 'px;';
		framestyle += 'left:' + left + 'px;';
		framestyle += 'width:'+WindowWidth+'px;';
		framestyle += 'height:'+WindowHeight+'px;';
		popWin = new Element('div', {'class':'popupWindow', 'id': frameid,	'name': frameid, 'style': framestyle});
		popCap = new Element('div', {'class':'popupWindowCaption'});
		popCap.update('<strong>' + title + '</strong>');
		closeButton = new Element('span');
		closeButton.update('X');
		closeButton.on('click', 'div.popupWindow', function(event, element) {
			element.remove();
		});
		framestyle = 'padding: 0px; ';
		framestyle += 'width:'+WindowWidth+'px;';
		WindowHeight -= 24;
		framestyle += 'height:'+WindowHeight+'px;';
		newframe = new Element('iframe', {'src': link, 'frameborder': '0', 'scrolling': 'auto', 'style': framestyle});

		// put everything together
		popCap.appendChild(closeButton);
		popWin.update(popCap);
		popWin.appendChild(newframe);
		if ( $(parentform) ) $(parentform).appendChild(popWin); 
                else document.body.appendChild(popWin);
	}
	return $(frameid);
}
/**
 *	Toggle the dn_checkbox control
 *	If keypress event only for space
 *	if even handled stop
 */
function dn_checkboxToggle(event, valContainer) {
	var imgControl;
	var key;
	switch(event.type) {
		case "keypress":
			key = event.which || event.keyCode;
			if ( key == Event.KEY_TAB) return;
			if ( key == Event.KEY_RETURN) return;
			if ( key == Event.KEY_BACKSPACE) return;
			if ( key == Event.KEY_DELETE) return;
			if ( key == Event.KEY_ESC) return;
			if ( key == Event.KEY_LEFT) return;
			if ( key == Event.KEY_UP) return;
			if ( key == Event.KEY_RIGHT) return;
			if ( key == Event.KEY_DOWN) return;
			if ( key == Event.KEY_HOME) return;
			if ( key == Event.KEY_PAGEUP) return;
			if ( key == Event.KEY_PAGEDOWN) return;
			break;
		case "click":
			break
		default:
			return;
	}
	imgControl = event.element();
	if ( $(valContainer).value == 0 ) {
		imgControl.src='/dn/images/checkbox1.gif';
		$(valContainer).value = 1;
	} else {
		imgControl.src='/dn/images/checkbox0.gif';
		$(valContainer).value = 0;
	}
	event.stop();
	return false;
}

/**
 *	Multipurpose Close window:
 *		- to close current window from parent (for dn_form_popup)
 *		- to close Div-Iframe (for dn_control_Popup)
 *		- to redirect to login.php when session has expired
 *		- to redirect parent to login.php when session has expired and close current window or iframe
 *	curf: the id or object of the current iframe or window
 *	mode: 'close' or 'login'
 */
function closeWindow(curf, mode) {
	if (mode == null) mode='close';
	var wpar = null;
	
	if (window.opener) {
		wpar = window.opener;
		if (wpar.$(curf)) {
			wpar.$(curf).hide();
			if (mode=="login") wpar.location.href='login.php';
			wpar.$(curf).close();
		}
	} else if (window.parent) {
		wpar = window.parent;
		if (wpar.$(curf)) {
			wpar.$(curf).hide();
			if (mode=="login") wpar.location.href='login.php';
			wpar.$(curf).remove();
		}
	}
}


