// JavaScript Document
(function($) {

// publikus metodusok
$.extend($.fn, {
	pformValidate: function(validator, messages, options) {
		//console.time('init');
		pform = new $.pform(validator, messages, options, this);
		//console.timeEnd('init');
		return pform;
	}
});

// pform konstruktor
$.pform = function(validator, messages, options, form) {
	this.validator = validator;
	this.messages = $.extend( {}, $.pform.defaultMessages, messages );
	this.options = $.extend( {}, $.pform.defaultOptions, options );
	this.formats = $.extend( {}, $.pform.formats );
	this.$form = form;
	this.$form.data('pform', this);
	this.initialize();
};


// pform
$.extend($.pform, {
	defaultOptions: {
		requiredClassName : 'required',					// kotelezo mezok (illetve label-ek class-e)	
		warningClassName : 'warning',					// warning mezok (illetve label-ek class-e)
		disabledClassName: 'disabled',					// disabled elemekre kerul
		addClassesToSimpleLabels: true,					// a simpla elemekhez tartozo labelek is megkapjak az elem classeket?
		addClassesToComplexLabels: true,				// az elemhez tartozo label is szinezodjon? (complex tipusu elemek)
		addWarningTitles: true,							// titleben kiirodjon-e a hiba oka, help kurzorral?
		addWarningTitlesToLabels: true,					// az elemhez tartozo labelre is rakeruljon-e a title?
		addWarningElements: true,						// kulon warning elem letrehozasa a hibauzenetnek
		addWarningElementEffect: 'show()',				// a warning element mutatasa soran jelentkezo effekt: lehet pl show(), fadeIn(), slideDown()		
		warningElementsTagName: 'span',					// a warning element tag
		addRequiredMarks: true,							// hasznalja-e a kotelezoseget jelzo karaktereket
		requiredMark: '*',								// kotelezoseg jelzo karakter
		warningElementsClassName: 'warning',			// warning elem class
		setFocusAfterSubmit: true,						// focus keruljon-e az elso invalid elemre submit utan?
		addTypeClasses: true,							// az iType class rahuzasa az input elemekre? (css formazast segiti)
		simpleTypeClass: 'simple',
		complexTypeClass: 'complex',
		selectTypeClass: 'select',
		setMaxlength: true,								// ha hossz ellenorzes van egy mezon, akkor automatikusan rakeruljon-e a maxlength?
		addWarningsOnInit: true							// ha be van kapcsolva, akkor indulaskor is kiirja a hibauzeneteket

		
		
	},
	prototype: {
		/**
		 * inicializalas
		 * @return void
		 */
		initialize: function() {
			this.beforeInitialization();
			if (!$(this.$form).is('form')) {
				this.log('Az inicializacio nem form elemre tortent!', 3);	
				return false;
			}
			if (this.$form.length!=1) {
				this.log('Az inicalizacio egy form elemre tortenhet!', 3);
				return false;
			}
			if (typeof(this.validator)!= 'object') {
				this.log('Az inicializaciohoz ervenyes validator objektumot kell megadni!', 3);
				return false;
			}
			// ha nem adott meg blokkot a validatorban, akkor krealunk -> normalizalas, @TODO: kulon fv is lehetne lassan
			if (typeof(this.validator.blocks)!='object') {
				var tmp = $.extend({}, this.validator);
				this.validator.blocks = [tmp];
				for (var i in this.validator) {
					if (i=='blocks') continue;
					delete this.validator[i];
				}
			}
			
			// blokkonkent inicializalunk
			for (var i in this.validator.blocks) {
				this.validator.blocks[i] = new $.block(this.validator.blocks[i], this);
				//this.validator.blocks[i].initialize(this);
			}
			
			// formhoz tartozo esemenykezeles
			this.$form.bind('submit', {p:this}, function(e) {
				var isValid = e.data.p.checkAll('onSubmit', true);
				if (isValid == false) {
					alert(e.data.p.messages._invalidForm);
					e.preventDefault();
				}
			});
			// ellenorzes elso lefuttatasa inicializalas eseteben
			if (this.options.addWarningsOnInit==true) this.checkAll('onInit');
			this.afterInitialization();
		},
		/**
		 * ellenorzes a pform objektumhoz rendelt validator objektum valamennyi mezojen
		 * @param {Bool} - csak akkor kap true erteket, ha vegso ellenorzes (form submit), ilyenkor meghivja a setfocust
		 * @param {String} eventId - hivo esemeny tipusa: onInit, onSubmit, stb.
		 */
		checkAll: function(eventId, setFocus) {
			var allIsValid = true;
			var notValidFields = [];
			for (var k in this.validator.blocks) {
				for (var i in this.validator.blocks[k].fields) {
					var isValid = this.validator.blocks[k].fields[i].checkField(eventId);
					if (isValid == false) {
						allIsValid = false;
						// a nem valid fieldeket ossze kell gyujteni egy tombbe, a fokuszt mindig ezekbol az elsore kell rakni
						notValidFields.push(this.validator.blocks[k].fields[i]);
					}
				}
				// block processorok meghivasa elkuldeskor
				if (eventId=='onSubmit') this.validator.blocks[k].callProcessor('onSubmit');
			}
			if (setFocus == true && this.options.setFocusAfterSubmit==true) {
				this.setFocus(notValidFields);
			}
			return allIsValid;
		},
		/**
		 * ellenorzi a formot, kivulrol hivhato fv
		 */
		isValid: function() {
			result = this.checkAll('onSubmit');
			return result;
		},
		/**
		 * Opciok modositasa futasidoben, publikus
		 */
		setOptions: function(options) {
			for (var i in options) {
				this.options[i] = options[i];
			}
		},
		/**
		 * a nem valid fieldek tombjebol kivalasztja az elsot es rarakja a fokuszt a megfelelo elemre (csak simple vagy select mezokre van ertelme focusnak)
		 * @param {Array} notValidFields
		 */
		setFocus: function(notValidFields) {
			if (typeof(notValidFields[0])!='object') return;
			notValidFields[0].$elements.focus();	
		},
		afterInitialization: function() {
			//pform pluginok mukodesehez kell!	
		},
		beforeInitialization: function() {
			//pform pluginok mukodesehez kell!	
		}
	},
	defaultMessages: {
		_required : 'A mező kitöltése kötelező!',
		_requiredSelect : 'Legalább egy opciót ki kell választania!',
		_requiredComplex : 'Legalább egy opciót ki kell jelölnie!',
		_minLength : 'A mezőben minimum %d karakternek kell szerepelnie!',
		_minLengthSelect : 'A mezőből minimum %d opciót ki kell választania!',
		_minLengthComplex : 'Minimum %d opciót ki kell jelölnie!',
		_maxLength : 'A mezőben maximum %d karakter szerepelhet!',
		_maxLengthSelect : 'A mezőből maximum %d opciót választhat ki!',
		_maxLengthComplex : 'Maximum %d opciót jelölhet ki!',
		_exactLength : 'A mezőben pontosan %d karakter szerepelhet!',
		_exactLengthSelect : 'A mezőből pontosan %d opciót választhat ki!',
		_exactLengthComplex : 'Pontosan %d opciót jelölhet ki!',
		_equalTo: 'A két mező értéke nem egyezik meg!',
		_format: 'A mező nem megfelelő formátumú!',
		_customValidation: 'A mező nem megfelelő formátumú!',
		_remote: 'A mező nem felel meg a távoli ellenőrzés kritériumainak!',
		_greaterThan : 'A mező értékének nagyobbnak kell lennie, mint %d!',
		_lessThan : 'A mező értékének kisebbnek kell lennie, mint %d!',
		_invalidForm: 'Az űrlap nincs megfelelően kitöltve!',
		// formatumokhoz kapcsolodo hibauzenetek
		_email: 'A mezőben érvényes-email címet kell megadnia!',
		_postalCodeHu: 'A mezőben érvényes postai irányítószámot kell megadnia! (4 számjegy)!',
		_date: 'A mezőben érvényes dátumot kell megadnia, helyes formátum: éééé-hh-nn',
		_dateHu: 'A mezőben érvényes dátumot kell megadnia, helyes formátum: éééé.hh.nn',
		_alnum: 'A mező csak az angol abc kis és nagybetűit, valamint számjegyeket tartalmazhat!',
		_alnumw: 'A mező csak az angol abc kis és nagybetűit, valamint számjegyeket, szóközt tartalmazhat!',
		_alnumhun: 'A mező csak a magyar abc kis és nagybetűit, valamint számjegyeket tartalmazhat!',
		_alnumhunw: 'A mező csak a magyar abc kis és nagybetűit, valamint számjegyeket, szóközt tartalmazhat!',
		_alpha: 'A mező csak az angol abc kis és nagybetűit tartalmazhatja!',
		_alphaw: 'A mező csak az angol abc kis és nagybetűit, valamint szóközt tartalmazhat!',
		_alphahun: 'A mező csak a magyar abc kis és nagybetűit tartalmazhatja!',
		_alphahunw: 'A mező csak a magyar abc kis és nagybetűit, valamint szóközt tartalmazhat!',
		_digits: 'A mezőbe csak egész szám írható!',
		_float: 'A mezőbe csak szám írható!',
		_int: 'A mezőbe csak egész szám írható!',
		_natural: 'A mezőbe csak pozitív egész szám írható!',
		_ip: 'A mezőbe csak érvényes ip cím írható'	
	},
	formats: {
		'email': /^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_.-])+\.([a-zA-Z])+([a-zA-Z])+/,
		'postalCodeHu': /^\d{4}$/,
		'datetime' : /^\d{4}[\-]\d{2}[\-]\d{2}T\d{2}:\d{2}:\d{2}.\d{2}(Z|(\+|[\-])\d{2}:\d{2})$/,
		'datetimeHu' : /^[\ ]*(\d{2,4})([\.\\\/]|[\.\\\/] |[ -])(\d{1,2})([\.\\\/]|[\.\\\/] |[ -])(\d{1,2})[\.]? (\d{1,2})[:\-\. ](\d{1,2})([:\-\. ](\d{1,2}))?$/,
		'date' : /^[1-2]{1}\d{3}-[0-1]{1}[0-9]{1}-[0-3]{1}[0-9]{1}$/,
		'dateHu' : /^[1-2]{1}\d{3}([\.]|[\.])[0-1]{1}[0-9]{1}([\.]|[\.])[0-3]{1}[0-9]{1}[\.]?$/,
		'number' : /^(-)?[\d]+(\.[\d]+)?$/,
		'phone' : /^[0-9\ \-\+\/\#\*\(\)]{4,40}$/,
		'alnum' : /^([a-zA-Z0-9]+)$/,
		'alnumw' : /^([a-zA-Z0-9 ]+)$/,
		'alnumhun' : /^([a-zA-ZáéiíóöőúüűÁÉIÍÓÖŐÚÜŰ0-9]+)$/,
		'alnumhunw' : /^([a-zA-ZáéiíóöőúüűÁÉIÍÓÖŐÚÜŰ0-9 ]+)$/,
		'alpha' : /^([a-zA-Z]+)$/,
		'alphau' : /^([a-zA-Z-_]+)$/,
        'alphaw' : /^([a-zA-Z ]+)$/,
		'alphahun' : /^([a-zA-ZáéiíóöőúüűÁÉIÍÓÖŐÚÜŰ]+)$/,
		'alphahunw' : /^([a-zA-ZáéiíóöőúüűÁÉIÍÓÖŐÚÜŰ ]+)$/,
		'digits' : /^\d*$/,
		'formatted_digits' : /^([0-9- ]+)$/,
        'float' : /^(-)?[\d]+(\.[\d]+)?$/,
		'int' : /^(-)?[\d]+?$/,
		'natural' : /^[\d]+?$/,
		'ip' : /^([1-9][0-9]{0,2})+\.([1-9][0-9]{0,2})+\.([1-9][0-9]{0,2})+\.([1-9][0-9]{0,2})+$/
	}
});

// block konstruktor
$.block = function(block, pform) {
	$.extend(this, block);
	this.options = $.extend( {}, $.block.defaultOptions, block.options );
	this.initialize(pform);
	this.$parentForm = pform.$form;
}
// block
$.extend($.block, {
	defaultOptions: {},
	prototype: {
		initialize: function(pform) {
			for (var i in this.fields) {
				this.fields[i] = new $.field(this.fields[i], i, this, pform.options, pform.messages, pform.formats);
			};
			this.$fieldsetElement = this.getFieldsetElement(pform.$form);
			this.$fieldsetElement.data('block', this);
			this.callProcessor('onInit');
		},
		getFieldsetElement: function($form) {
			var $fieldsetElement;
			if(this.block_id) {
				$fieldsetElement = $('#'+this.block_id);
			}
			else {
				$fieldsetElement = $('fieldset', $form);
			}
			if ($fieldsetElement.length!=1) log('a block_id helytelenul van megadva!', 3);
			return $fieldsetElement;
		},
		/**
		 * blokkhoz tartozo processor fuggveny lefuttatasa 
		 * @param {String} eventId: a hivo esemeny tipusa
		 * @return void
		 */
		callProcessor: function(eventId, fireId) {
			if (typeof(this.processor)!='function') return;
			//@TODO: befejezni, tesztelni, stb. 
			
			var arguments = [this.fields, eventId, fireId];	
			this.processor.apply(this, arguments);
		}
	}
});

// field konstruktor
$.field = function(field, name, block, options, messages, formats) {
	$.extend(this, field);
	this.name = name;
	this.options = options;
	this.messages = messages;
	this.formats = formats;
	this.initialize(block);
};

// field
$.extend($.field, {
	prototype: {
		initialize: function(block) {
			this.$elements = $('#' + this.name);
			// ha id alapjan nem talajuk a validator mezohoz tartozo elemet, akkor name alapjan keressuk, checkboxok, radiok miatt
			if (this.$elements.length == 0) {
				this.$elements = $('input[name=' + this.name + ']');
			}
			// multi checkbox eseten
			if (this.$elements.length == 0) {
				this.$elements = $('input[name=' + this.name + '[]]');
			}
			// ha sem id, sem name alapjan nem talatunk a validator mezojehez tartozo elemet
			if (this.$elements.length == 0) {
				log('hiba: nincs elem a kovetkezo validator mezohoz: ' + this.name, 3);
			}
			this.setElements();
		},
		setElements: function() {
			// esemeny kotesek az input elemekre
			for (var i = 0; i < this.$elements.length; i++) {
				el = this.$elements[i];
				$(el).data('field', this);
				// szoveges input vagy textarea
				if ( $(el).is('input[type="text"]') || $(el).is('input[type="password"]') || $(el).is('textarea') ) { // egy "is"-ben nem mukodik a harom ie7 es ie8 alatt
					this.iType = 'simple';
					$(el).bind( "keyup blur", {f:this}, function(e) {
						// @TODO: alt, shift, ctrl kizarasa
						field = e.data.f;
						field.checkField('onCheckField');
						var block = field.$parentFieldset.data('block');
						if (field.equalTo) block.fields[field.equalTo].checkField('onCheckEqualTo');
					});
					// ha a configban a setMaxlenght be van kapcsolva, akkor az ilyen mezokre rapakoljuk
					if (this.options.setMaxlength==true && (this.maxLength || this.rangeLength)) {
						if (!$(el).is('textarea')) { // textareara nincs ertelme rarakni
							var maxlength = 0;
							if (this.maxLength) 
								maxlength = this.maxLength;
							if (this.rangeLength) 
								maxlength = this.rangeLength[1];
							$(el).attr('maxlength', maxlength);
						}
					}
				}
				// select
				else if ( $(el).is('select') ) {
					this.iType = 'select';
					$(el).bind( "change", {f:this}, function(e) {
						e.data.f.checkField('onCheckField');
					});
				}
				// radio vagy checkbox
				else if ( $(el).is('input[type="radio"]') || $(el).is('input[type="checkbox"]') ) { // egy is-ben nem mukodik ie alatt a ketto
					this.iType = 'complex';
					$(el).bind( "click", {f:this}, function(e) {
						e.data.f.checkField('onCheckField');
					});
				}
				// classnevek rapakolasa az elemekre, ha be van kapcsolva
				if (this.options.addTypeClasses == true) {
					$(el).addClass( this.options[this.iType+'TypeClass'] );
				}
				this.$parentFieldset = this.$elements.parents('fieldset');
		
			};	
		},
		/**
		 * egy field objektum ellenorzese
		 * @param {String} eventId: onInit, onSubmit, stb.
		 * @return {Bool}
		 */
		checkField: function(eventId) {
			//console.time('checkField');
			var res = {
				isValid:true, 
				className: '', 
				message: ''
			};
			var className, message, hasValue = this.hasValue();
			if ( this.required == true ) {
				res = this.checkRequired();
			}
			// hossz ellenorzese
			if ( res.isValid==true && hasValue==true && (this.minLength || this.maxLength || this.rangeLength || this.exactLength) ) {
				res = this.checkLength();
			}
			// ertek ellenorzese
			if ( res.isValid==true && hasValue==true && (this.greaterThan || this.lessThan || this.between ) ) {
				res = this.checkValueLength();
			}
			// formatum ellenorzese
			if ( res.isValid==true && hasValue==true && this.format ) {
				res = this.checkFormat();
			}
			// azonossag ellenorzese
			if ( res.isValid==true && hasValue==true && this.equalTo ) {
				res = this.checkEqualTo();
			}
			// sajat ellenorzesek
			if ( res.isValid==true && hasValue==true && this.customValidation ) {
				res = this.checkCustomValidation();
			}
			if (eventId=='onCheckField') {
				var block = this.$parentFieldset.data('block');
				block.callProcessor('onCheckField', this.name);
			}
			// ha ures a mezo akkor semmilyen warning nem kell ra
			if ( !hasValue && !this.required ) {
				res = {
					isValid: true,
					className: '',
					message: ''
				}
			}
			this.setWarnings(res);
			
			//console.timeEnd('checkField');
			return res.isValid;	
		},
		/**
		 * validator objektum egy adott mezojehez tartozo kotelezoseg teljesul-e vagy sem 
		 * segedfuggvenykent szukesges
		 * @return {Bool} 
		 */
		checkRequired: function() {
			var isValid = false;
			if (this.hasValue()) {
				isValid = true;
			}
			return {
				isValid: isValid,
				className: this.options.requiredClassName,
				message: this.getMessage('required')
			};	
		},
		/**
		 * Hosszellenorzesek
		 * @return {Object}
		 */
		checkLength: function() {
			var minLength = this.minLength;
			var maxLength = this.maxLength;
			var rangeLength = this.rangeLength;
			var exactLength = this.exactLength;
			var $el = this.$elements;
			var messageType, messageParam;
			if (typeof(rangeLength)=='object') {
				minLength = rangeLength[0];
				maxLength = rangeLength[1];
			}
			// az ertek hosszanak tipusfuggo ellenorzese
			if (this.iType=='simple') {
				l = $el[0].value.length;
			}
			else if (this.iType=='select') {
				l = $('option:selected', $el).length;	
			}
			else if (this.iType=='complex') {
				l = $("input:checked", $el.parent() ).length;
			}
			// konkret ellenorzes
			var isValid = true;
			if (typeof(exactLength) == 'number') {
				if (l!=exactLength) {
					isValid = false;
					messageType = 'exactLength';
					messageParam = exactLength;
				}
			}
			else if (minLength!='undefined' && l<minLength) {
				isValid = false;
				messageType = 'minLength';
				messageParam = minLength;
			}
			else if (maxLength!='undefined' && l>maxLength ) {
				isValid = false;
				messageType = 'maxLength';
				messageParam = maxLength;
			}
			return {
				isValid: isValid,
				className: this.options.warningClassName,
				message: this.getMessage(messageType, messageParam)
			};	
		},
		/**
		 * Ertekre vonatkozo ellenorzesek
		 * @return {Object}
		 */
		checkValueLength: function() {
			var greaterThan = this.greaterThan;
			var lessThan = this.lessThan;
			var between = this.between;
			var $el = this.$elements;
			var val = $el.val();
			var isValid = true;
			var messageType, messageParam;
			if (typeof(between)=='object') {
				greaterThan = between[0];
				lessThan = between[1];
			}
			if (greaterThan && val<=greaterThan) {
				isValid = false;
				messageType = 'greaterThan';
				messageParam = greaterThan;
			}
			if (lessThan && val>=lessThan) {
				isValid = false;
				messageType = 'lessThan';
				messageParam = lessThan;
			}
			return {
				isValid: isValid,
				className: this.options.warningClassName,
				message: this.getMessage(messageType, messageParam)
			};	
		},
		/**
		 * Ellenorzi a mezoben megadott ertek formatumat
		 * @return {Object}
		 */
		checkFormat: function() {
			var format = this.format;
			var $el = this.$elements;
			var isValid = false;
			var formatName = 'format'; 
			// formatumot csak text jellegu inputokra lehet huzni
			if (this.iType!='simple') {
				log('hiba: csak text jellegu mezokhoz (text, password,textarea) lehet formatumot rendelni!', 2);
				return false;
			}
			// ha beepitett formatumot hasznal
			if (typeof(format)=='string') {
				formatName = format;
				format = this.formats[format];
			
			}
			// ha sajat regexpet ad meg a hivaskor; typeof(format)=='function' Safari miatt
			else if (typeof(format)=='object' || typeof(format)=='function') {
				
			}
			else {
				log(this.name - ' ervenytelen formatum!', 2);
				return false;
			}
			isValid = format.test($el[0].value);
			// ha a messagesben nincs az adott formatumhoz megfelelo hibauzenet felveve, akkor hozzuk a default hibauzenetet
			if (typeof(this.messages['_'+formatName])!='string') {
				formatName = 'format';
			}
			return {
				isValid: isValid,
				className: this.options.warningClassName,
				message: this.getMessage(formatName)
			};	
		},
		/**
		 * Azonossag ellenorzese
		 * @return {Object}
		 */
		checkEqualTo: function() {
			var block = this.$parentFieldset.data('block');
			var equalTo = this.equalTo;
			var $el = this.$elements;
			var isValid = true;
			
			var equalToValue = block.fields[equalTo].$elements.val();
			if ($el.val() != equalToValue) 
			isValid = false;
			
			return {
				isValid: isValid,
				className: this.options.warningClassName,
				message: this.getMessage('equalTo', '')
			};	
		},
		/**
		 * Sajat validator fuggveny lefuttatasa
		 * @return {Object}
		 */
		checkCustomValidation: function() {
			var $el = this.$elements;
			var isValid = true;
			isValid = this.customValidation.apply(this);		
			return {
				isValid: isValid,
				className: this.options.warningClassName,
				message: this.getMessage('customValidation', '')
			};	
		},
		/**
		 * Hibauzenet osszeallitasa
		 * @param {string} messageId
		 * @param {string} messageParam
		 * @return {string}
		 */
		getMessage: function(messageType, messageParam) {
			// meghivodhat a fuggveny olyankor is, ha nem kell semmit sem visszaadnia @TODO: mikor?
			if (!messageType) return false;
			
			// ha van testreszabott uzenet az adott mezohoz es uzenettipushoz, akkor azt adjuk vissza
			if (typeof(this.messages[this.name]) == 'object') {
				var customMessage = this.messages[this.name][messageType];
				if (typeof(customMessage) == 'string') {
					return customMessage;
				}
			}
			// ha nincs sajat uzenet, akkor a messages tombbol adjuk vissza a default uzenetet
			switch (this.iType) {
				case 'simple' : messageIdSuffix = '';
				break;
				case 'select' : messageIdSuffix = 'Select';
				break;
				case 'complex' : messageIdSuffix = 'Complex';
				break;
			}
			message = this.messages['_'+ messageType+messageIdSuffix];
			// uzenet parameterenek behelyettesitese
			if (messageParam!=undefined) message = message.replace('%d', messageParam);
			return message;	
		},
		/**
		 * A megfelelo class hozzaadasa, levetele az elemhez es a vonatkozo labelhez valamint title megadas, error felirat elkeszitese
		 * @param {Object} res
		 * @return void
		 */
		setWarnings: function(res) {
			//console.time('setWarnings');
			var $el = this.$elements;
			// megfelelo classek hozzadasa vagy levetele input elemekre
			if (res.isValid == false) {
				if (res.className==this.options.requiredClassName) {
					$el.addClass(this.options.requiredClassName).removeClass(this.options.warningClassName);
				}
				else if (res.className == this.options.warningClassName) {
					$el.addClass(this.options.warningClassName).removeClass(this.options.requiredClassName);
				}
			} 
			else {
				$el.removeClass(this.options.requiredClassName+" "+this.options.warningClassName);
			}
			// classek hozzaadasa, levetele a vonatkozo label elemekre
			if ( ( this.options.addClassesToSimpleLabels && ( this.iType == 'simple' || this.iType == 'select' ) ) || ( this.options.addClassesToComplexLabels && ( this.iType == 'complex' ) ) ) {
				if (res.isValid == false) {
					for (var i = 0; i < $el.length; i++) {
						if (res.className==this.options.requiredClassName) {
							$('label[for=' + $el[i].id + ']').addClass(this.options.requiredClassName).removeClass(this.options.warningClassName);
						}
						else if (res.className == this.options.warningClassName) {
							$('label[for=' + $el[i].id + ']').addClass(this.options.warningClassName).removeClass(this.options.requiredClassName);
						}
					}
				}
				else {
					for (var i = 0; i < $el.length; i++) {
						$('label[for=' + $el[i].id + ']').removeClass(this.options.requiredClassName+" "+this.options.warningClassName);
					}
				}
			}
			// title beallitasa
			if (this.options.addWarningTitles==true) {
				if (res.isValid == false) {
					$el.attr('title', res.message).css('cursor', 'help');
				}
				else {
					$el.removeAttr('title').css('cursor', '');
				}
			}
			// title beallitasa a label elemekre
			if (this.options.addWarningTitlesToLabels==true) {
				if (res.isValid == false) {
					for (var i = 0; i < $el.length; i++) {
						var selector = $el[i].id;
						$('label[for=' + selector + ']').attr('title', res.message).css('cursor', 'help');
					}
				}
				else {
					for (var i = 0; i < $el.length; i++) {
						var selector = $el[i].id;
						selector = selector.replace(":", "\\:");
						$('label[for=' + selector + ']').removeAttr('title').css('cursor', '');
					}
				}
			}
			// warning elem
			if (this.options.addWarningElements==true) {
				// letezik-e mar a warning element
				$warningElements = $(this.options.warningElementsTagName+"."+this.options.warningElementsClassName, $el.parent() );
				if (res.isValid == false) {
					if ($warningElements.length==0) {
						var warningElement = document.createElement(this.options.warningElementsTagName);
						warningElement.innerHTML = res.message;
						$(warningElement).addClass(this.options.warningElementsClassName);
						var lastElement = $el[$el.length-1];
						$(lastElement).after(warningElement);
						if (this.options.addWarningElementEffect!='show()') {
							$(lastElement).hide();
							eval('$(warningElement).'+options.addWarningElementEffect);
						}
					}
					else {
						$warningElements.html(res.message);
					}
				}
				else {
					if ($warningElements.length > 0) {
						$(this.options.warningElementsTagName+"."+this.options.warningElementsClassName, $el.parent()).remove();
					}
				}
			}

			// kotelezoseget jelzo karakterek kezelese
			if (this.options.addRequiredMarks==true) {
				if (res.isValid == false) {
					
				}
				else {
					
				}	
			}
		},
		/**
		 * adott mezohoz tartozo elem(ek)rol megallapitja, h van-e mar ertekuk, ki van-e mar valasztva, stb, kotelezoseg ellenorzesere is ezt hasznaljuk
		 * @return {Bool}
		 */
		hasValue: function() {
			var $el = this.$elements;
			// tipusonkent eltero ellenorzes
			switch (this.iType)
			{
				case 'simple':
					if ($el[0].value) return true;
				break;
				case 'select':
				if ($('option:selected', $el).length > 0) { //@TODO: meg kell nezni at lehet-e ugy szervezni mint a complex ágat
					if ($('option:selected:first', $el).get(0).getAttribute('value')) return true;
				}
				break;
				case 'complex':
					if ( $el.is(":checked") ) return true;
				break;
			}
			return false;	
		},
		/**
		 * Adott mezo objektum aktualis erteket adja vissza (jelenleg csak kivulrol hasznaljuk, pl. processzorba)
		 * @return {Mixed} field objektumhoz tartozo elemek erteke, tomb megy vissza ha tobb ertek van
		 */
		getValue: function() {
			var $el = this.$elements;
			// tipusonkent eltero lekerdezes
			//console.log(this);
			switch (this.iType)
			{
				case 'simple':
					if ($el[0].value.length>0) return $el[0].value; else return false;
				break;
				case 'select':
					// @TODO: tesztelni!
					var $selected_elements = $( 'option:selected', $el );
					if ($selected_elements.length==1) {
						return $selected_elements[0].value;
					}
					else if ($selected_elements.length>1) {
						result = [];
						for (var i=0; i<$selected_elements.length; i++) result.push($selected_elements[i].value);
						return result; 
					}
				break;
				case 'complex':
					var $checked_elements = $( 'input:checked', $el.parent() );
					if ($checked_elements.length==1) {
						return $checked_elements[0].value;
					}
					else if ($checked_elements.length>1) {
						result = [];
						for (var i=0; i<$checked_elements.length; i++) result.push($checked_elements[i].value);
						return result; 
					}
				break;
			}
			return false;	
			
		},
		/**
		 * Adott mezo attributumanak allitasa
		 * @param {Object} attributes {required: true} 
		 * @param 
		 */
		setAttr: function(attributes) {
			for (var i in attributes) {
				this[i] = attributes[i];
			}
			this.checkField('onSetAttr');
		},
		/**
		 * Ervenyes-e adott mezo
		 */
		isValid: function() {
			var res = this.checkField('onIsValid');
			return res;
		},
		/**
		 * Adott mezo kotelezoseget lehet beallitani (kivulrol hivjuk)
		 */
		disable: function() {
			this.$elements.attr('disabled', 'disabled').addClass(this.options.disabledClassName);
		},
		/**
		 * Adott mezo kotelezoseget lehet beallitani (kivulrol hivjuk)
		 */
		enable: function() {
			this.$elements.removeAttr('disabled').removeClass(this.options.disabledClassName);
		}
	}
});
})(jQuery);

/**
 * hibauzenetek, figyelmeztetesek megjelenitese
 * @param {String} uzenet szovege
 * @return {Int} hiba szintje: 1-notice, 2-warning, 3-error
 */
function log(message, level) {
	message = 'pform: '+message;
	if (window.console) {
		switch (level) {
			case 2:
				console.warn(message);
				break;
			case 3:	
				console.error(message);
				break;
			default:
				console.log(message);
		}
	}
	else {
		alert(message)
	}
}



