function formular( formId ){
	// definicje propoerties
	this.form = document.getElementById( formId );
	this.clearSelects = false;
	var structure = null;
	this.initialValues = null;

	// definicje metod
	
	this.setOnSubmit = function( fn ){
		this.form.onsubmit = fn;	
	}
	
	this.disableElements = function( names ){
		for (var n=0; n<names.length; n++){
			if (this.form[names[n]]) this.form[names[n]].disabled = true;
		}
	}
	
	this.setStructure = function( structure ){
		this.structure = structure;
	}
	this.setInitialValues = function( initialValues ){
		this.initialValues = initialValues;
	}

	this.setForceClearSelects = function( val ){
		this.clearSelects = val;
	}

	this.fillFormular = function(){

		for(var n in this.structure){
			// przechodzimy w pętli po wszystkich elementach zawartych w tabeli trzymającej strukturę elementów formularza
			// dla każdego elementu tablicy wyszukujemy odpowiadający mu nazwą element formularza i sprawdzamy jego typ
			// - dla selectów wywołujemy funkcję generującą select
			// - dla radiobuttona analogicznie
			// - dla innych typów takich jak hidden lub text nie wykonujemy żadnych czynności (narazie)

			var el = this.getElementByName( n );
			if (!el) continue; // jeżeli element nie istnieje przejdź do kolejnego

			if ( el.nodeName && el.nodeName=="SELECT" ){ // znaleziony element to select

				this.fillSelect( el, this.structure[n]	);

			} else if ( el.tagName && el.tagName=="INPUT" ) { // znaleziony element to input -> sprawdzamy jego typ

				switch ( el.type ){
			
					case "radio" :	this.fillRadioButton( el, this.structure[n] );
									break;
			
					case "input" :	break;	// na razie nic nie robimy
					case "hidden" :	break;
				}
			} else {
				// być może będzie trzeba dorobić obsługę textarea
				alert('#1 dziwny element o tagu '+ el.tagName );
			}
		}

		this.setInitValues();
	}


	this.fillSelect = function fillSelect( element, elementStructure ){
		if (this.clearSelects) {
			if (element.options[0].value=="{removeme}") element.options.length = 0;
		}
		for (var field in elementStructure){
			var option=document.createElement('option');
			option.value=field;
			option.innerHTML=elementStructure[field];
			element.appendChild(option);
		}
	}

	this.fillRadioButton = function fillRadioButton( element, elementStructure ){
		var label = element.parentNode;
		var afterFirst = false;
		for (var q in elementStructure){
			if (afterFirst) label.parentNode.insertBefore(label.cloneNode(true),label);
			label.getElementsByTagName('input')[0].value = q;
			label.getElementsByTagName('span')[0].innerHTML = elementStructure[q];
			var afterFirst = true;
		}
	}


	this.setInitValues = function setInitValues(){

		for(var n in this.initialValues){
			// przechodzimy w pętli po wszystkich elementach tablicy initial values, szukając pasujących elementów w formularzu
			// w przypadku, gdy element istnieje ustawiamy mu odpowiednią wybraną wartość
			// gdy nie znajduje się jako element formularza tworzymy go jako hidden
			this.setElementValue( n );
		}
		this.setMultiSelectsValue();
	}
	
	
	this.setElementValue = function ( list, value ){
		
		if (typeof list=='object') {
			for(var n in list ){
				this.setElementsValues( n, list[n] );
			}			
		} else {
			this.setElementsValues( list, value );
		}
	}
	
	
	this.setElementsValues = function ( n, v ){
		
		if (typeof v=='undefined') v = this.initialValues[n];
		var el = this.getElementByName( n );

		if (el) { // element istnieje w formularzu -> sprawdzamy jego typ
		
			if (el.tagName=="SELECT" ){

				this.setSelectValue( n, v ); // ustawiamy wybraną wartość selecta

			} else if(el.tagName=="INPUT"){

				switch ( el.type ){					

					case "radio" :	this.setRadioValue( n, v ); // ustawiamy wybrany radiobutton
									break;
			
					case "text" :	this.setInputValue( n, v ); // ustawiamy wartość Inputa
									break;

					case "hidden" :	this.setHiddenValue( n, v ); // ustawiamy wartość hiddena
									break;
								
					case "checkbox" : this.setCheckboxValue( n, v ); // to samo dla checkboxa
				}

			} else {
				alert('#2 dziwny element o tagu '+ el.tagName )
			}

		} else { // element nie istnieje trzeba stworzyć hiddenfielda i przypisać mu wartość

			this.addHiddenField( n, v );  
		}
	}

	this.setCheckboxValue = function( n, v ){
		
		//alert( n + ' -> ' + v );
		
		var el = this.getElementByName( n );
		
		if (el.value == v ) el.checked = true;
		
	}

	this.setMultiSelectsValue = function(){
		
		var els = this.form.getElementsByTagName('select');
		for (var n=0; n<els.length; n++){
			if (els[n].multiple){
				var sel=els[n];
				for (var i=0; i<sel.options.length; i++){
					var tmp=sel.options[i].value.split('|');
					if (tmp && this.initialValues[tmp[0]]==tmp[1]) sel.options[i].selected=true;
				}
			}
		}
	}


	this.addHiddenField = function addHiddenField( elementName, value ){
		var hf = document.createElement( 'input' );
		hf.type = 'hidden';
		hf.name = elementName;
		hf.value = value;
		this.form.appendChild( hf );
	}

	this.setSelectValue = function setSelectValue( elementName, value ) {
		var el = this.getElementByName( elementName );
		// poniżej specjalnie dla IE, bo potrafi on ustawić w <select> wartość niezdefiniowaną w <options>
		el.value = value;
		if (el.selectedIndex==-1) el.selectedIndex=0;
	}

	this.setRadioValue = function setRadioValue( elementName, value ) { 
		// tu będzie trochę bardziej skomplikowanie, bo trzeba znaleźć w formularzu wszystkie elementy o nazwie elementName
		// a wśród nich jednemu o wartości równej value nadać atrybut checked
	}

	this.setInputValue = function setInputValue( elementName, value ) { 
		this.getElementByName( elementName ).value = value;
	}

	this.setHiddenValue = function setHiddenValue( elementName, value ) {
		this.getElementByName( elementName ).value = value;
	}

	this.getElementByName = function getElementByName( name ){
		var x = this;
		var elements = this.form.getElementsByTagName('*');
		
		for (var i=0; i< elements.length; i++ ) {
			if (elements[i].name==name) return elements[i];
		}
		return null;
	}
	
	this.dump = function(o){
		ret=[];
		for (var n in o) ret.push( n + ' -> ' + o[n] );
		ret.sort();
		alert( ret.join('\n'));
	}
	
}
