﻿/*
	Tämä javascripti sisältää seuraavat luokat:

	tähdellä (*) merkityt ovat parametreja jotka syötetään olinoa:
	esim. var ib = new tsInputbox({name : "en", text : "Etunimi"})

	risuaidalla (#) merkityt ovat metoodeja.

	- tsLinkButton (ohjelmoitava linkki)
		* name - yksilöllinen nimi luokalle.
		* text - selite.
		* linkFunction - funktio		

	- tsInputbox (yksirivinen tekstikenttÃ¤)
		* name - yksilöllinen nimi luokalle.
		* text - selite.

	- tsTextarea (monirivi-tekstikenttÃ¤)
		* name - yksilöllinen nimi luokalle.
		* text - selite.

	- tsSelect (lista / dropdownlista)
		* name - yksilöllinen nimi luokalle.
		* text - selite.
		* type - voi olla "dropdown" tai "list"
		(* size - jos type="list" tämä on listan koko)

		# addOption(text, value)
		
	- tsGroup (ryhmä)
		* name - yksilöllinen nimi luokalle.
		* text - selite.

		# addChild(obj)
			obj voi olla joku seuraavista (Inputbox, Textarea, Select tai Group).
			
	- tsForm (lomke)
		* name - yksilöllinen nimi luokalle.
		* submitText - vaihtoehtoinen nimi submit-napille.
		* submitFunction - submit-napin funktio.
		* shadow - jos true lisää toisen DIV-elementin ennen varsinaista lomake-DIV:iä.

		# addChild(obj)
			obj voi olla joku seuraavista (Inputbox, Textarea, Select tai Group).
		# write(id)
			tulostaa lomakkeen; joko elementtiin Id tai sivun viimeiseksi elementiksi.
			Parametrit:
				- before : ennen elementtiä 
				- after : elementin jälkeen
*/

function name_exists(elArray, name) {
	for(var i=0; i < elArray.length; i++) { if (elArray[i].name == name) return name; }
	return null;
}

function global_tsValidate(expression, trueText, falseText) {
	var currentObject = this;
	var form = this;
	while(form.parent) form = form.parent;
	
	var re = typeof(expression) == 'string'? new RegExp(expression) : expression;
	
	if (currentObject instanceof tsInputbox || currentObject instanceof tsTextarea) {
		currentObject.validationEvent = 'blur';
	} else if (currentObject instanceof tsSelect) {
		currentObject.validationEvent = 'change';
	}
	
	currentObject.validationFunction = function() {
		var elementName = currentObject.getName? currentObject.getName() : null;
		var element = elementName? document.getElementById(elementName) : currentObject; 

		var parent = element.parentNode; 

		var value = typeof(element.value) != "undefined"? element.value : element.options[element.selectedIndex].value;

		var chk = (value.length > 0) && re.test(value);
		
		var classNames = element.className.split(' ');
		if (/(?:in)?valid/.test(classNames[classNames.length - 1])) {
			classNames[classNames.length - 1] = chk? 'valid' : 'invalid';
		} else {
			classNames.push(chk? 'valid' : 'invalid');
		}
		element.className = classNames.join(' ');

		var currentValidateObjectName = currentObject.getName() + "_validateStatus";

		eval('var ' + currentValidateObjectName + ' = null;');
	
		if (!document.getElementById(currentValidateObjectName)) {
			eval(currentValidateObjectName + ' = document.createElement("span");');
			eval(currentValidateObjectName + '.id = "' + currentValidateObjectName + '";');
			eval(currentValidateObjectName + '.className = "' + (currentValidateObjectName + " ") + (chk? 'valid' : 'invalid') + '";');
			eval('parent.appendChild(' + currentValidateObjectName + ');');
		} else {
			eval(currentValidateObjectName + ' = document.getElementById("' + currentValidateObjectName + '");');
			eval(currentValidateObjectName + '.className = "' + (currentValidateObjectName + " ") + (chk? 'valid' : 'invalid') + '";');
		}
		eval(currentValidateObjectName + '.innerHTML = chk? trueText : falseText;');
		
		currentObject.validated = chk;
		return chk;
	}

	form.setValidateOnSubmit(currentObject);
}

var tsLinkButton = function(oParams) {
	if (!oParams.name) throw ('LinkButton: must have a parameter "name"');
	if (!oParams.text) throw ('LinkButton: must have a parameter "text"');
	if (!oParams.linkFunction) throw ('LinkButton: must have a parameter "linkFunction"');
	if (typeof(oParams.linkFunction) != "function") throw ('LinkButton: parameter "linkFunction" must be a function!');
	
	this.parent = null;
	this.name = oParams.name.replace(/[åä]/g, 'a').replace(/ö/g, 'o').toLowerCase();
	
	this.getName = function() { return this.parent.getName() + "_" + this.name; }
	this.setParent = function(parent) { this.parent = parent; }
	
	this.render = function() {
		var container = document.createElement('div');
		container.id = this.getName() + "_container";

		var linkbutton = document.createElement('a');
		linkbutton.onclick = function() { oParams.linkFunction(); return false; }
		linkbutton.href = "#";
		
		linkbutton.innerHTML = oParams.text;

	    container.appendChild(linkbutton);
	
		container.className = "container";
		return container;	  
	}
}

var tsInputbox = function(oParams) {
	if (!oParams.name) throw ('Input: must have a parameter "name"');
	if (!oParams.text) throw ('Input: must have a parameter "text"');
	
	this.parent = null;
	this.name = oParams.name.replace(/[åä]/g, 'a').replace(/ö/g, 'o').toLowerCase();
	this.element = null;
	
	this.getName = function() { return this.parent.getName() + "_" + this.name; }
	this.setParent = function(parent) { this.parent = parent; }
	
	this.setValidate = global_tsValidate;
	
	this.getValue = function() { return this.element.value; }
	
	this.render = function() {
	  var input = document.createElement('input');
	  input.id = this.getName();
	  if (this.validationFunction && this.validationEvent) {
			input.attachEvent?  input.attachEvent('on' + this.validationEvent, this.validationFunction) :
                                input.addEventListener(this.validationEvent, this.validationFunction, true);
		}
	  input.type = oParams.password? 'password' : 'text';
	  var label = document.createElement('label');
	  label.innerHTML = oParams.text + ":";
		label.htmlFor = this.getName();
	  
	  var container = document.createElement('div');
		container.id = this.getName() + "_container";
	  
		container.appendChild(label);	  
		container.appendChild(input);

		this.element = input;

		input.className = "inputbox";
		label.className = "label";
		container.className = "container";
	
		return container;	  
	}
}

var tsTextarea = function(oParams) {
	if (!oParams.name) throw ('Textarea: must have a parameter "name"');
	if (!oParams.text) throw ('Textarea: must have a parameter "text"');

	this.parent = null;
	this.name = oParams.name.replace(/[åä]/g, 'a').replace(/ö/g, 'o').toLowerCase();
	this.element = null;
	
	this.getName = function() { return this.parent.getName() + "_" + this.name; }
	this.setParent = function(parent) { this.parent = parent; }

	this.setValidate = global_tsValidate;

	this.getValue = function() { return this.element.value; }
		
	this.render = function() {
	  var textarea = document.createElement('textarea');
	  textarea.id = this.getName();
	  if (this.validationFunction && this.validationEvent) {
			textarea.attachEvent?   textarea.attachEvent('on' + this.validationEvent, this.validationFunction) :
                                    textarea.addEventListener(this.validationEvent, this.validationFunction, true);
		}

	  var label = document.createElement('label');
	  label.innerHTML = oParams.text + ":";
		label.htmlFor = this.getName();
	  
	  var container = document.createElement('div');
		container.id = this.getName() + "_container";
	  
		container.appendChild(label);	  
		container.appendChild(textarea);
		
		textarea.className = "textarea";
		this.element = textarea; 
		label.className = "label";
		container.className = "container";
		
		return container;	  
	}
}

var tsSelect = function(oParams) {
	if (!oParams.name) throw ('Select: must have a parameter "name"');
	if (!oParams.text) throw ('Select: must have a parameter "text"');
	if (oParams.type && oParams.type.toLowerCase() == 'list' && !oParams.size) throw ('Select: parameter "type=list" need also parameter "size"');

	this.parent = null;
	this.name = oParams.name.replace(/[åä]/g, 'a').replace(/ö/g, 'o').toLowerCase();
	this._elements = new Array();
	this.element = null;

	this.setValidate = global_tsValidate;

	this.getValue = function() { return this.element.options[this.element.selectedIndex].value; }
		
	this.addOption = function(text, value) {
    var option = document.createElement('option');
    option.appendChild(document.createTextNode(text));
    option.value = value;
		this._elements.push(option);
	}

	this.getName = function() { return this.parent.getName() + "_" + this.name; }
	this.setParent = function(parent) { this.parent = parent; }

  this.render = function() {
		var container = document.createElement('div');
		var select = document.createElement('select');
		select.size = !oParams.type? 1 : (oParams.type == 'list')? oParams.size : 1;  
		select.id = this.getName();		 
	  if (this.validationFunction && this.validationEvent) {
			select.attachEvent? select.attachEvent('on' + this.validationEvent, this.validationFunction) :
                                select.addEventListener(this.validationEvent, this.validationFunction, true);
		}
				
		for(var i=0; i < this._elements.length; i++) select.appendChild(this._elements[i]);

		var label = document.createElement('label');
		label.appendChild(document.createTextNode(oParams.text + ": "));
		label.htmlFor = this.getName();		 

		container.id = this.getName() + "_container";

		container.appendChild(label);
		container.appendChild(select);

		select.className = "selectbox";
		this.element = select; 
		label.className = "label";
		container.className = "container";

		return container;
	}
}

var tsGroup = function(oParams) {
	if (!oParams.name) throw ('Group: must have a parameter "name"');
	if (!oParams.text) throw ('Group: must have a parameter "text"');

	this.parent = null;
	this.name = oParams.name.replace(/[åä]/g, 'a').replace(/ö/g, 'o').toLowerCase();
	this._elements = new Array();

	this.addChild = function(obj) {
	  if (name_exists(this._elements, obj)) throw('Group: Element("' + obj.name + '") already exists in group!');
		if (typeof(obj.render) == "function") {
			 obj.setParent(this);
			 this._elements.push(obj);
		}
	}

	this.setParent = function(parent) { this.parent = parent; }
	this.getName = function() { return this.parent.getName() + "_" + this.name; }

  this.render = function() {
	  var fieldset = document.createElement('fieldset');
	  var legend = document.createElement('legend');
	  legend.appendChild(document.createTextNode(oParams.text));
	  
	  fieldset.appendChild(legend);
	  fieldset.id  = this.getName();
	  legend.id = this.getName() + "_title";

		for(var i=0; i < this._elements.length; i++) {
			if (this._elements[i].render) fieldset.appendChild(this._elements[i].render());
		}

		fieldset.className = "group";
		legend.className = "title";
			  
	  return fieldset;
	}
}

var tsForm = function(oParams) {
	if (!oParams.name) throw ('Form: must have a parameter "name"');
	if (!oParams.submitText) throw ('Form: must have a parameter "submitText"');
	if (!oParams.submitFunction) throw ('Form: must have a parameter "submitFunction"');
	if (typeof(oParams.submitFunction) != "function") throw ('Form: parameter "submitFunction" must be a function!');

	this.name = oParams.name.replace(/[åä]/g, 'a').replace(/ö/g, 'o').toLowerCase();
	this._elements = new Array();

	var formElement = this;

	this.addChild = function(obj) {
	  if (name_exists(this._elements, obj.name)) throw('Form: Element("' + obj.name + '") already exists in form!');
		if (typeof(obj.render) == "function") {
			 obj.setParent(this);
	  	 this._elements.push(obj);
		}
	}

	this.setValidateOnSubmit = function(obj) {
		var f = obj.validationFunction;
		var copy = this.validationFunction;
		formElement.validated = false;
		if (!copy) this.validationFunction = function() { 
		   formElement.validated = f.call(obj);
        }; else this.validationFunction = function() {
           copy();
		   if (f.call(obj) == false) formElement.validated = false;
        };
	}

	this.getName = function() { return this.name; }
	
	this.write = function(elID, pos) {
	  // Ei sallita tupplia
	  if (document.getElementById(this.getName())) return false;
	  
	  var rootEl = elID? document.getElementById(elID) : document.body;
	  if (!rootEl) throw('Form: element (id: "' + elID + '") could not be found!');

		var rootEl_clone = rootEl.cloneNode(true); 

		var doc_fragment = document.createDocumentFragment();

		var form = document.createElement('div');
		var shadow = document.createElement('div');

	  var submit_container = document.createElement('div');
		var submit = document.createElement('input');
		submit.value = oParams.submitText; 
		submit.type = 'button';
		
		submit_container.appendChild(submit);

		for(var i=0; i < this._elements.length; i++) {
			if (this._elements[i].render) form.appendChild(this._elements[i].render());
		}

	  form.appendChild(submit_container);

		if (pos && pos.toLowerCase() == "after") doc_fragment.appendChild(rootEl_clone);
		if (oParams.shadow) {
			shadow.appendChild(form);
			doc_fragment.appendChild(shadow);
	 	} else {
			doc_fragment.appendChild(form);
	  }
		if (pos && pos.toLowerCase() == "before") doc_fragment.appendChild(rootEl_clone);

		if (!pos) rootEl.appendChild(doc_fragment);
		else rootEl.parentNode.replaceChild(doc_fragment, rootEl);

		submit.onclick = function() {
			if (formElement.validationFunction) formElement.validationFunction();
			oParams.submitFunction.getElements = function() { return formElement._elements; }
			oParams.submitFunction.getStatus = function() { return formElement.validated; }
			oParams.submitFunction();
		} 
	  
		form.id = this.getName();
		shadow.className = this.getName() + "_shadow";
		submit.className = this.getName() + "_submit button";
	  submit_container.className = this.getName() + "_submit_container submitcontainer";
	}
}