//____________________________________________________________________
function Property(name_str,label_str,parentObj,superAuthority){
	
	var self				= this;
	var value_str			= '';
	var isAttribute_bool	= false;
	var definedValue_str	= '';
	var valueDerivation_func;
	var defaultValue_str	= '';
	
	var broadcaster			= new Broadcaster(this);
	broadcaster.createEventType('valueChange');

	// create authorisation object
	var editAuth			= new Authorisation();
	superAuthority? editAuth.defineSuperAuthority(superAuthority) : null;
	
	// add parentObj listeners
	parentObj.addEventListener('reset',handleEventReset);
	parentObj.addEventListener('pollChange',handlePollChange);
	parentObj.addEventListener('save',handleSave);
	
	parentObj.addEventListener('dataLoad',handleDataLoad);
	parentObj.addEventListener('beforeDataSave',handleBeforeSave);
	
	this.__defineGetter__('editable',function(){return editAuth.valid;});
	this.__defineGetter__('name',function(){return name_str;});
	this.__defineGetter__('label',function(){return label_str;});
	this.__defineGetter__('value',function(){return value_str? value_str : defaultValue_str;});
	this.__defineSetter__('value',editValue);
	
	refreshDerivation();
	
	//----------------------------------------------------------------
	function handleSave(){
		
		definedValue_str 	= value_str;
	};
	//----------------------------------------------------------------
	function handlePollChange(changes_obj){
		
		if(definedValue_str != value_str){
			changes_obj.changes	= true;
		}
	};
	//----------------------------------------------------------------
	function editValue(newValue_str){
		
		if(editAuth.valid){
			setValue(newValue_str);
		}else{
			throw new Error('Unauthorised edit attempt on property: '+self.name);
		}
	};
	//----------------------------------------------------------------
	function handleBeforeSave(saveParams_obj){
		
		saveParams_obj[name_str]	= self.value;
	};
	//----------------------------------------------------------------
	function handleDataLoad(data_xdoc){
		
		if(isAttribute_bool){
			var value_str	= data_xdoc.firstChild.getAttribute(self.name);
		}else{
			value_str		= data_xdoc.firstChild.xPathQuery(self.name,'string');
		}
		value_str			= value_str? value_str : '';
		definedValue_str	= value_str;
		setValue(value_str);
	};
	//----------------------------------------------------------------
	function setValue(newValue_str){

		if(value_str != newValue_str){
			value_str		= newValue_str;
			broadcaster.triggerEvent('valueChange');
		}
	};
	//----------------------------------------------------------------
	function handleEventReset(){
		
		setValue('');
	};
	//----------------------------------------------------------------
	function refreshDerivation(){
		
		if(valueDerivation_func){
			setValue(valueDerivation_func());
		}
	};
	//________________________________________________________________
	this.setDefaultValue = function(newValue_str){
		
		defaultValue_str	= newValue_str;
		value_str? null : setValue(defaultValue_str);
	};
	//________________________________________________________________
	this.defineAsNodeAttribute = function(){
		
		isAttribute_bool	= true;
	};
	//________________________________________________________________
	this.defineValue = function(newValue_str){
		
		definedValue_str	= newValue_str;
		setValue(newValue_str);
	};
	//________________________________________________________________
	this.bindConnectionStateToAttribute = function(element_h,attribute_str){
		
		parentObj.addEventListener('connect',function(){element_h.setAttribute(attribute_str,true);});
		parentObj.addEventListener('disconnect',function(){element_h.setAttribute(attribute_str,false);})
	};
	//________________________________________________________________
	this.bindValueToAttribute = function(element_h,attribute_str){
		
		var refreshAttribute = function(){element_h.setAttribute(attribute_str,self.value);};
		refreshAttribute();
		this.addEventListener('valueChange',refreshAttribute);
	};
	//________________________________________________________________
	this.bindValueToInnerHTML = function(element_h){
		
		// define a function to update element_h upon change in Property.value
		// replace line breaks with <br /> tags
		var refreshElement	= function(){element_h.innerHTML = self.getValueAsHTML();};//'
		refreshElement();
		
		// execute function on value change
		this.addEventListener('valueChange',refreshElement);
	};
	//________________________________________________________________
	this.getValueAsHTML = function(){
		
		return self.value.replace(/\n/g,'<br />');//'
	};
	//________________________________________________________________
	this.refreshDerivation = refreshDerivation;
	//________________________________________________________________
	this.bindValueToInput = function(input_h){
		
		// define functions to bind values between input_h and Property
		//------------------------------------------------------------
		function refreshInputValue(){
			
			if(input_h.value != self.value){
				input_h.value	= self.value;
			}
		};
		//------------------------------------------------------------
		function refreshInputAttributes(){
			
			input_h.disabled= !editAuth.valid;
		};
		//------------------------------------------------------------
		function takeInputValue(){
			
			self.value 		= input_h.value;
		};
		//------------------------------------------------------------
		refreshInputAttributes();
		refreshInputValue();
		
		// add parentObj listeners that will trigger value syncing
		this.addEventListener('valueChange',refreshInputValue);
		editAuth.addEventListener('validate',refreshInputAttributes);
		editAuth.addEventListener('invalidate',refreshInputAttributes);
		input_h.addEventListener('valueChange',takeInputValue,false);
		input_h.addEventListener('keyup',takeInputValue,false);
	};
};	//________________________________________________________________
//____________________________________________________________________