// DataForm.js
// Javascript Behaviour for the DataForm Control
// Copyright (c) by Matthias Hertel, http://www.mathertel.de
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
// ----- 
// 16.06.2007 created by Matthias Hertel by extracting methods from the old ajaxForms.js
// 09.08.2007 eventnamespace added: the event namespace that is used for publishing OpenAjax events.
// 15.08.2007 registering in OpenAjax added.
// 12.12.2007 adding OpenAjax events.
// 18.12.2007 Simplifications and documentation.

jcl.DataFormBehavior = {

eventnamespace: "dataform",  /// <summary>Namespace of the events published by contained elements without a full qualified namespace.</summary>
_record: null,               /// <summary>current record of the form.</summary>
  
init: function() {
  /// <summary>Initializing the control.</summary>
  this._record = {};

  // register for events of the form elements
  if (this.eventnamespace) {
    OpenAjax.hub.subscribe(this.eventnamespace + ".*", this.handleEvent, this);
  } // if
},

// --- OpenAjax event handler ---


handleEvent: function (eventName, eventData) {
  /// <summary>Collecting the form data when values are changing.</summary>
  var en = jcl.LocalEventName(eventName);
  if ((en != "clear") && (en != "reset"))
    this._record[en] = eventData;
}, // handleEvent



///<summary>Walk all html INPUT, TEXTAREA and SELECT elements contained by the passed object
///and return the current values.</summary>
///<returns>The data of inside the form as XML Document.</returns>
read: function () {
  var n, aList, elem, val;
  var xData = this._getXMLDOM("<data></data>");
  var xNode;

  for (n in this._record) {
    xNode = xData.documentElement.appendChild(xData.createElement(n));
    xNode.appendChild(xData.createTextNode(this._record[n]));
  } // for
  
  return(xData);
}, // read


///<summary>This method transfers the values of the data into the corresponding INPUT, TEXTAREA and SELECT elements.
///All HTML elements of these types that have a name but no value will be cleared.</summary>
///<param name="data">The data for the form. This can be a XML string or an XML document.</param>
write: function(data) {
  var n, aList, dataElements;
  var xData, xElem, val;

  if (data == null)
    throw new Error("ajaxForms.setData: Argument 'data' must be set.");
    
  if (typeof(data) == "string")
    xData = this._getXMLDOM(data);
  else
    xData = data;
  
  OpenAjax.hub.publish(this.eventnamespace + ".clear", null);

  xElem = xData.documentElement.firstChild.firstChild;

  if (xElem.nodeName == "#text")
    xElem = xData.documentElement.firstChild;

  while (xElem) {
    OpenAjax.hub.publish(this.eventnamespace + "." + xElem.nodeName,
      (xElem.textContent || xElem.innerText || xElem.text || xElem.childNodes[0].nodeValue));
    xElem = xElem.nextSibling;
  }

  this.clearErrors();
}, // write


///<summary>This method clears the values of the html elements of type INPUT, TEXTAREA and SELECT that have a name.</summary>
clearData: function() {
  var n, aList, dataElements;

  OpenAjax.hub.publish(this.eventnamespace + ".clear", null);
  this._record = {};

  this.clearErrors();
}, // clearData


///<summary>This method clears the values of the html elements of type INPUT, TEXTAREA and SELECT that have a name.</summary>
resetData: function() {
  OpenAjax.hub.publish(this.eventnamespace + ".reset", null);
  this.clearErrors();
}, // resetData


///<summary>Parse an exception for an ArgumentException and set the error annotations</summary>
///<param name="ex">An exception object.</param>
processException: function(ex) {
  var txt = ex.description;
  if ((ex.message == "soap:Server") && (txt != null) && (txt.indexOf("System.ArgumentException: ") > 0)) {
  
    txt = txt.substr(txt.indexOf("System.ArgumentException: ") + 26).split('\n');
    var param = txt[1].substr(txt[1].indexOf(':')+2);
    
    var aList = document.getElementsByTagName("SPAN");
    for (var n = 0; n < aList.length; n++) {
      if ((aList[n].className == "AJAXFORMEXCEPTION") && (aList[n].getAttribute("name") == param)) {
        aList[n].style.display = "inline";
        aList[n].innerText = txt[0]; // IE
        aList[n].textContent = txt[0]; // FF
        break;
      } // if
    } // for
  } else {
    proxies.alertException(ex);
  } // if
}, // processException


///<summary>This method clears the error annotations of the html elements of type SPAN
///that have the className AJAXFORMEXCEPTION.</summary>
clearErrors: function() {
  var n;
  var aList = document.getElementsByTagName("SPAN");
  for (n = 0; n < aList.length; n++) {
    if (aList[n].className == "AJAXFORMEXCEPTION") {
      aList[n].style.display = "none";
      aList[n].innerText = ""; // IE
      aList[n].textContent = ""; // FF
    } // if
  } // for
}, // clearErrors


///<summary>Get a browser specific implementation of the XMLDOM object, containing a XML document.</summary>
///<param name="xmlText">the xml document as string.</param>
_getXMLDOM: function (xmlText) {
  var obj = null;

  if (typeof(DOMParser) != "undefined") {
    // Gecko / Mozilla / Firefox
    var parser = new DOMParser();
    obj = parser.parseFromString(xmlText, "text/xml");

  } else {    
    // IE
    try {
      obj = new ActiveXObject("MSXML2.DOMDocument");
    } catch (e) { }

    if (obj == null) {
      try {
        obj = new ActiveXObject("Microsoft.XMLDOM");
      } catch (e) { }
    } // if
  
    if (obj != null) {
      obj.async = false;
      obj.validateOnParse = false;
    } // if
    obj.loadXML(xmlText);
  } // if
  return(obj);
} // _getXMLDOM
} // DataFormBehavior
