/**
 *  object to control a form
 *
 *  @author   Tobias Hettinger
 *  @version  $Id: form.js,v 1.2 2009/02/20 14:15:16 tobias Exp $
 */


//=====================================================================================================================
//  input control tools
//=====================================================================================================================

/**
 *  function to get the caret position of the passed input field
 *
 *  @param object field  input field to analyse. This can be a textarea or an input field
 *
 *  @return array  the function returns a hash array that contains the keys
 *                 - start -
 *                   start position of the current selection
 *                 - end -
 *                   end position of the current selection
 */
function watFormGetCaret(field)
{
  //  initialize the result array
  var result = new Array();
  result['start'] = 0;
  result['end'] = 0;
  
  //  the internet explorer does not know selectionStart and selectionEnd :-(
  if (typeof field.selectionStart == 'undefined')
  { 
    //  idea for a solution is taken from
    //  http://the-stickman.com/web-development/javascript/finding-selection-cursor-position-in-a-textarea-in-internet-explorer/

    //  the current selection
    var range = document.selection.createRange();
    //  use this as a 'dummy' range
    var stored_range = range.duplicate();
    //  select all text
    if (field.type == 'textarea') stored_range.moveToElementText(field);
      else stored_range.expand('textedit');
    //  now move 'dummy' end point to end point of original range
    stored_range.setEndPoint('EndToEnd', range);
    //  calculate start and end points
    result['start'] = stored_range.text.length - range.text.length;
    result['end'] = result['start'] + range.text.length;
  }
  else
  {
    //  the easy way of getting the caret position ...
    result['start'] = field.selectionStart;
    result['end'] = field.selectionEnd;
  }
  
  //  return the result
  return result;
}


//=====================================================================================================================
//  form field
//=====================================================================================================================

/**
 *  constructor of the field object
 *
 *  @param string id    id of the input field
 *  @param string type  type of the input field ('text', 'editor', ...) or
 *                      NULL if the type is to be determined automatically
 */
var WATFormField = function(id, type)
{
  //  set the member variables
  this.id = id;
  this.type = type;
  this.mask = null;
  this.frameName = null;
  this.sheetName = null;
  
  //  status variables
  this.initialized = false;
  this.created = false;
  this.name = null;
  
  //  variables that are used by extensions
  this.maskNextChar = '';
  this.editor = null;
  this.editorFieldName = null;
  this.editorClass = null;
  this.editorStyleBaseUrl = null;
  this.editorStyleName = null;
  this.editorCss = null;
  
  //  get the control
  this.control = document.getElementById(id);
  
  //  the control has been detected
  if (this.control) this.initialized = true;
}


WATFormField.prototype.Create = function()
{
  if (this.initialized && !this.created)
  {
    switch(this.type)
    {
      case 'editor' :
        if (this.name != null)
        {
          this.editor = new WATDivEditor(this.name + '.editor', this.id, this.editorFieldName, this.editorClass,
                                         this.editorStyleBaseUrl, this.editorStyleName);
          this.editor.propertyEditorCss = this.editorCss;
          this.editor.EnableEditor();
          this.created = true;
        }
        break;
    }
  }
}

WATFormField.prototype.Remove = function()
{
  if (this.initialized && this.created)
  {
    switch(this.type)
    {
      case 'editor' :
        this.editor.RemoveObject();
        break;
    }
    
    this.initialized = false;
    this.created = false;
  }
}


/**
 *  function to set an input mask
 *
 *  @param string mask  input mask for the control
 */
WATFormField.prototype.SetMask = function(mask)
{
  //  save the field object
  var obj = this;

  //  key press event handler
  function __MaskKeyPress(event)
  {
    obj.wat_form_mask_keypress(event);
  }

  //  key up event handler
  function __MaskKeyUp(event)
  {
    obj.wat_form_mask_keyup(event);
  }

  if (this.control)
  {
    //  register the events if the mask is set for the first time
    if (this.mask == null)
    {
      switch(this.control.type)
      {
        //  text input field
        case 'text' :
          if (WATBrowserInfo.IsIE)
          {
            this.control.attachEvent('onkeypress', __MaskKeyPress);
            this.control.attachEvent('onkeyup', __MaskKeyUp);
          }
          else
          {
            this.control.addEventListener('keypress', __MaskKeyPress, true);
            this.control.addEventListener('keyup', __MaskKeyUp, true);
          }
          break;
      }
    }
  
    //  set the input mask
    this.mask = mask;
  }
}


//=====================================================================================================================
//  form manager
//=====================================================================================================================

/**
 *  constructor of the form controller
 *
 *  @param string name  name of the form control object
 */
var WATForm = function(name)
{
  //  set the member variables
  this.name = name;
  this.fields = new Array();
}

/**
 *  function to register the passed control
 *
 *  @param string name   name to address the passed control (not necessarily the id of the control)
 *  @param object field  field object to register
 */
WATForm.prototype.RegisterControl = function(name, field)
{
  //  register the field
  this.fields[name] = field;
  field.name = this.name + '.fields[\'' + name + '\']';
}

/**
 *  function to get the control with the passed name
 *
 *  @param string name  name of the required field
 *
 *  @return object  the function returns the field object if it has been found or NULL if the field was not found
 */
WATForm.prototype.GetControl = function(name)
{
  //  search the control
  for (var i in this.fields)
    if (this.fields[i].name == name) return this.fields[i];

  //  the field was not found
  return null;
}

WATForm.prototype.RemoveControls = function(frameName, sheetName)
{
  for (var i in this.fields)
    if (this.fields[i].frameName == frameName && this.fields[i].sheetName == sheetName)
    {
      this.fields[i].Remove();
    }
}


//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//  XML parser

/**
 *  function to parse an XML structure
 *
 *  @param object xml        xml structure to parse
 *  @param string frameName  name of the desktop frame in which the control is located or NULL if this information is
 *                           not available or not required. If the control is located on a lightbox, the frameName
 *                           has to be 'lightbox'
 *  @param string sheetName  name of the desktop sheet in which the control is located or NULL if this information is
 *                           not available or not required. If the control is located on a lightbox, the sheetName
 *                           parameter has to contain the name of the lightbox
 */
WATForm.prototype.ParseXML = function(xml, frameName, sheetName)
{
  if (xml)
  {
    //  parse the passed xml structure
    var node = xml.firstChild;
    while(node)
    {
      switch(node.nodeName)
      {
        //  an input field definition has been sent
        case 'f' :
          var id = node.getAttribute('id');
          if (id)
          {
            //  get the control if it is already registered or create a new one if the control is not registered yet
            var formField = this.GetControl(id);
            if (formField == null) formField = new WATFormField(id);
          
            //  parse the input field definition
            var field = node.firstChild;
            while(field)
            {
              switch(field.nodeName)
              {
                //  an input mask has been sent
                case 'm' :
                  if (field.firstChild) formField.SetMask(field.firstChild.data);
                  break;
              }
          
              field = field.nextSibling;
            }
          }
          break;
          
        //  an editor field definition has been sent
        case 'edit' :
          var id = node.getAttribute('id');
          if (id)
          {
            //  get the control if it is already registered or create a new one if the control is not registered yet
            var formField = null;//this.GetControl(id);
            if (formField == null) formField = new WATFormField(id, 'editor');
            this.RegisterControl(id, formField);
            
            formField.frameName = frameName;
            formField.sheetName = sheetName;
            
            formField.editorFieldName = node.getAttribute('n'); 
            formField.editorClass = node.getAttribute('class');
            formField.editorStyleBaseUrl = node.getAttribute('sbu');
            formField.editorStyleName = node.getAttribute('sn');
            formField.Create();
          }
          break;
      }
      
      //  get the next node
      node = node.nextSibling;
    }
  }
}

