function TemplateBase()
{

  var _control = null;
	
	var _input = null;
	
	
	// the first event below is used as a reference / descriptor and will not be included when saved
	var _events = ["Select an Event", "blur", "change", "click", "dblclick", "focus", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup"];
	
	this.BaseLoad = function(ControlElement, InputElement)
	{
	  try{

	    _control = $(ControlElement);
			
			if(InputElement != null)
			{
  			_input = $(InputElement);
				
  			_input.unbind("focus.clearerror").bind("focus.clearerror", function(){
    		  var ctrl = Helper.GetEditorComponent($(this).parent());
  				if(ctrl.ErrorStatus)
    	  	  ctrl.ErrorStatus(false);
  			});
			}
				
			_control.unbind("click.clearerror").bind("click.clearerror", function(){
  		  var ctrl = Helper.GetEditorComponent(this);
				if(ctrl.ErrorStatus)
  	  	  ctrl.ErrorStatus(false);
			});
			
			attachValuelessAttrs();
						
		}catch(err){Log.Add("TemplateBase.BaseLoad", err, LogType.Error)}
	}
	
	this.AttachFunctions = function()
	{
	  try{
		
 			if(_control.attr("function")!= null)
			{
			 
    		var functions = _control.attr("function").split("|");
    		
				var definitions = _control.attr("definition").split("|");
				
			  for(var i = 0; i<functions.length; i++)
				{
				
				  if(!definitions[i].beginsWith("#S"))
					{
  				 	var name = functions[i].toLowerCase() + ".templatebase";
			
    			  var fn = new Function(definitions[i]);

		  			_input.unbind(name).bind(name, fn);
						
					}
				}
			}
		}catch(err){Log.Add("TemplateBase.AttachFunctions", err, LogType.Error)}
	}
	
	this.DetachFunctions = function()
	{
	  try{
		
		  // hack: this should be called in its own
		  detachValuelessAttrs();
		
 			if(_control.attr("function"))
			{
			 
    		var functions = _control.attr("function").split("|");
    		
			  for(var i = 0; i<functions.length; i++)
				{
 				 	var name = functions[i].toLowerCase() + ".templatebase";

				  _input.unbind(name);
				} 
			}
		  
		}catch(err){Log.Add("TemplateBase.DetachFunctions", err, LogType.Error)}	  
	}
	
	
	this.AddFunction = function()
	{
	  try{
		
			if((_control.attr("function")==null) || (_control.attr("function").length == 0)){
		    _control.attr("function", "");
	  		_control.attr("definition",  "");
			} else {
  		  _control.attr("function", _control.attr("function") + "|");
	  		_control.attr("definition", _control.attr("definition") + "|");
			}	  
			
			Editor.ShowProperties(_control);
			
		}catch(err){Log.Add("Templatebase.AddFunction", err, LogType.Error)}					  
	}
	
	this.DeleteFunction = function(FunctionIndex)
	{
	  try{
		
  		var functions = _control.attr("function").split("|");
  		var definitions = _control.attr("definition").split("|");
  		
			functions.splice(FunctionIndex, 1);
			definitions.splice(FunctionIndex, 1);
  		
			_control.attr("function", functions.toPipeString());
  		_control.attr("definition", definitions.toPipeString());
			
			if(_control.attr("function").length == 0)
			{
			  _control.removeAttr("function");
			  _control.removeAttr("definition");
			}		  

			Editor.ShowProperties(_control);

		}catch(err){Log.Add("Templatebase.DeleteFunction", err, LogType.Error)}			
	}	
	
	this.GetBaseProperties = function()
	{
	  try{
		
		  var pref = Helper.GetParentRef(_control);
		
      var properties = new Array();
			
			if(pref == "StaticContainer")
			{
        properties[properties.length] = new PropertiesEditor.Property(PropertyFields.GetProperty("Left"), this.GetLeft, this.SetLeft);

        properties[properties.length] = new PropertiesEditor.Property(PropertyFields.GetProperty("Top"), this.GetTop, this.SetTop);
			}			
			
      properties[properties.length] = new PropertiesEditor.Property(PropertyFields.GetProperty("Condition"), this.GetCondition, this.SetCondition);
			
			if(_input != null)
			{
			  properties[properties.length] = new PropertiesEditor.Property(PropertyFields.GetProperty("TabIndex"), this.GetTabIndex, this.SetTabIndex);
				
			  properties[properties.length] = new PropertiesEditor.Property(PropertyFields.GetProperty("Tooltip"), this.GetTooltip, this.SetTooltip);				
				
			  properties[properties.length] = new PropertiesEditor.Property(PropertyFields.GetProperty("ValueLessAttrs"), this.GetValueLessAttrs, this.SetValueLessAttrs);				
			
			}


      var args = new RulesMaker.ComplexArgs(this.GetBaseProperties, this.AddFunction, this.DeleteFunction);
      properties[properties.length] = new PropertiesEditor.Property(PropertyFields.GetProperty("ScriptFunctions"), this.GetFunctions, this.SetFunctions, args);
			
			return properties;
			
		}catch(err){Log.Add("TemplateBase.GetBaseProperties", err, LogType.Error)}
	}

	
  this.GetCondition = function(){try{  return _control.attr("condition"); } catch(err){ Log.Add( "TemplateBase.GetCondition", err, LogType.Error); }};
	
  this.SetCondition = function(Condition){try{ _control.attr("condition", Condition); } catch(err){ Log.Add("TemplateBase.SetCondition", err, LogType.Error); }};

	this.GetEventList = function()
	{
	  return _events;
	}
	

	this.GetFunctions = function()
	{
	  try{

		  var functions, definitions;
		  
			functions = _control.attr("function");
			definitions = _control.attr("definition");
			
			if((functions == null) || (definitions==null))
			{
			  return new Array();
			}

      var ret = new Array();
						
			if(functions.indexOf("|") > -1)
			{	// multiple functions
			  functions = _control.attr("function").split("|");
				definitions = _control.attr("definition").split("|");
    		 
    		for(var i = 0; i<functions.length; i++)
    		{
    		  var f = new UserFunction(functions[i], definitions[i]);
    			ret[ret.length] = f;
    		}
			} 
			else 
			{ // only one function
			  ret[0] = new UserFunction(functions, definitions);
			}
			
			return ret;
		
		
		
    }catch(err){Log.Add("TemplateBase.GetFunctions", err, LogType.Error)}
	}	
	
	
	this.SetFunctions = function(arr)
	{
	  try{
		
  		var functions = "";
			var definitions = "";
			
			var hasfunctions = true;
			
			if(arr.length == 0)
			  hasfunctions = false;
				
			if(arr.length == 1)
			{
			  var f = Utilities.ReplaceAll(arr[0].Name, " ", "");
				if(f =="")
				  hasfunctions = false;
			}
			
			if(!hasfunctions)
			{
			  _control.removeAttr("function");
			  _control.removeAttr("definition");
				return;
			}
  	
  	  for(var i = 0; i<arr.length; i++)
  		{
			  var f = Utilities.ReplaceAll(arr[i].Name, " ", "");
				if(f.length > 0)
			  {
    		  functions += arr[i].Name + "|";
    			definitions += arr[i].Body + "|";
			  }
  		}
  		
			if(arr.length > 0)
			{
  			functions = functions.removeLastChar();
    		definitions = definitions.removeLastChar();
			}
  		
			_control.attr("function", functions);
			
  		_control.attr("definition", definitions);
		  
    }catch(err){Log.Add("TemplateBase.SetFunctions", err, LogType.Error)}
	}		
	
	
	this.GetTabIndex = function()
	{
	  try{
		  return _input.attr("tabindex");
    }catch(err){Log.Add("TemplateBase.GetTabOrder", err, LogType.Error)}		
	}
	
	this.SetTabIndex = function(newTabIndex)
	{
	  try{
		  var _index = parseInt(newTabIndex);
			
			if(_index < 1)
			  return;
				
			if($("*[tabindex='" + _index + "']").length > 0)
			  reAssignTabIndexes(_index);
		
		  _input.attr("tabindex", newTabIndex);
			
    }catch(err){Log.Add("TemplateBase.GetTabOrder", err, LogType.Error)}		
	}
	
  this.GetValueLessAttrs = function()
  {
    try{
		
				if(!_input)
			    return;
			
    	  var str = _input.attr("valuelessAttrs");
  			
  			if(!str)
  			  return;
		
			  var str = _input.attr("valuelessAttrs");
				
				var attrs = str.match(/[a-zA-Z0-9#_]+/g);
				
				if(attrs == null)
				  return "";
				
				var ret = attrs.toString();
					
				return ret.replace(/,/g, " ");
    
    } catch(err){ Log.Add( "TemplateBase.GetValueLessAttrs", err, LogType.Error); }
  };
	

	this.SetValueLessAttrs = function(newValue)
  {
    try{
		
				if(!_input)
			    return;
					
	      _input.removeAttr("valuelessAttrs");					
			
				var attrs = newValue.match(/[a-zA-Z0-9#_]+/g);

				if(attrs == null)
					return;

	      attrs = attrs.toString();
				
				_input.attr("valuelessAttrs", attrs.replace(/,/g, " "));

	       
    } catch(err){ Log.Add("templatebase.SetValueLessAttrs", err, LogType.Warning); }
  };		
	
	
	this.GetTooltip = function(){
	  try{
		  
			if(_input == null)
			  return "";
				
			var ret = _input.attr("title");
			
		  if(!ret)
			  return "";
				
			return ret; 
		
    }catch(err){Log.Add("TemplateBase.GetTooltip", err, LogType.Error)}	
	}
	
	this.SetTooltip = function(newValue){
	  try{
		  
			if(_input == null)
			  return;
			
			_input.attr("title", newValue);

    }catch(err){Log.Add("TemplateBase.SetTooltip", err, LogType.Error)}	
	}


	
	
	this.GetLeft = function()
	{
	  try{
		
  	  return _control.css("left");
			
    }catch(err){Log.Add("TemplateBase.GetLeft", err, LogType.Error)}			
	}
	
	this.SetLeft = function(newValue)
	{
	  try{
  	  _control.css("left", newValue);
			_control.attr("origL", newValue);			
    }catch(err){Log.Add("TemplateBase.SetLeft", err, LogType.Error)}			
	}	
	
	
	this.GetTop = function()
	{
	  try{
  	  return _control.css("top");
    }catch(err){Log.Add("TemplateBase.GetTop", err, LogType.Error)}
	}

	this.SetTop = function(newValue)
	{
	  try{
  	  _control.css("top", newValue);
			_control.attr("origT", newValue);
					
			
		
    }catch(err){Log.Add("TemplateBase.SetTop", err, LogType.Error)}			
	}
	
	// attaches the valueless attributes to the input
	function attachValuelessAttrs(){
	  try{
		  if(!_input)
			  return;
			
  	  var str = _input.attr("valuelessAttrs");
			
			if(!str)
			  return;
  		
  		var arr = str.match(/[a-zA-Z0-9#_]+/g);
  		
  		if(arr == null)
  		  return;
  		
  		for(var i = 0; i<arr.length; i++)
  		{
    		  if(arr[i].indexOf("#")>-1)
    				_input.attr(arr[i], "");
    			else
    			  _input.attr(arr[i], " ");
  		}
				
    }catch(err){Log.Add("TemplateBase.attachValuelessAttrs", err, LogType.Error)}					
	}


	// detaches the valueless attributes from the input
	function detachValuelessAttrs(){
	  try{
		  if(!_input)
			  return;
			
  	  var str = _input.attr("valuelessAttrs");
			
			if(!str)
			  return;
  		
  		var arr = str.match(/[a-zA-Z0-9#_]+/g);
  		
  		if(arr == null)
  		  return;
  		
  		for(var i = 0; i<arr.length; i++)
  		{
    		_input.removeAttr(arr[i]);
  		}
				
    }catch(err){Log.Add("TemplateBase.detachValuelessAttrs", err, LogType.Error)}					
	}
	
	
	function UserFunction(name, body)
	{
	  this.Name = name;
		this.Body = body;
	}
	
	function reAssignTabIndexes(beginIndex)
	{
	  $("*[tabindex]").each(function(){
		
		  var _index = parseInt($(this).attr("tabindex"));
		
			if(_index >= beginIndex)
			  $(this).attr("tabindex", _index+1);		
		
		});
	
	}


}
