/********************************
 * Ajax functions by Rob Becker
 *
 *   ddList() & insertDDList()
 *   ajaxObject class
 ********************************/

/**
 * NAME: ddList()
 *
 * DESCRIPTION:
 *    - Creates a drop-down list through ajax calls, or
 *    - Closes a drop-down list if one is already created and open, or
 *    - Opens a drop-down list if one is already created and closed.
 *    NOTE 1: The drop-down list will be inserted into the DOM structure 
 *      as a child of the element identified by the id argument.
 *    NOTE 2: The DOM element identified by the id argument will be assigned
 *      a class value, and so should not have a pre-assigned class, or be
 *      otherwise dynamically assigned a class value.
 *    NOTE 3: The drop-down list div container element will be given an id of
 *      'dd-list-' + id
 *
 * ARGUMENTS:
 *    params (category, date, no others implemented)
 *       ex:  category=3
 *            date=2008-11-27 (or fragments, such as YYYY-MM or MM-DD or YYYY)
 *
 * RETURNS: Nothing
 *
 * DEPENDENCIES:
 *    ajaxObject class, insertDDList(), ddList.php
 **/
function ddList(id, params) {
  try {
    var dom_node = document.getElementById(id);
    if (dom_node) {
      // Drop down list is open, so let's close it ...
      if (dom_node.className == 'open') {
        // Change [-] to [+] -- NOTE: if-else statement is used for IE compatibility
        if (dom_node.getElementsByTagName('a')[0].innerText) {
          dom_node.getElementsByTagName('a')[0].innerText = dom_node.getElementsByTagName('a')[0].innerText.replace('[-]', '[+]');
        } else {
          dom_node.getElementsByTagName('a')[0].textContent = dom_node.getElementsByTagName('a')[0].textContent.replace('[-]', '[+]');
        }
        dom_node.className = 'closed';
        document.getElementById('dd-list-' + id).className = 'hidden';
        
      // Drop down list is closed, so let's open it ...
      } else if (dom_node.className == 'closed') {
        // Change [+] to [-] -- NOTE: if-else statement is used for IE compatibility
        if (dom_node.getElementsByTagName('a')[0].innerText) {
          dom_node.getElementsByTagName('a')[0].innerText = dom_node.getElementsByTagName('a')[0].innerText.replace('[+]', '[-]');
        } else {
          dom_node.getElementsByTagName('a')[0].textContent = dom_node.getElementsByTagName('a')[0].textContent.replace('[+]', '[-]');
        }
        dom_node.className = 'open';
        document.getElementById('dd-list-' + id).className = '';
        
      // Drop-down list has never been opened, so let's get it from the server ...
      } else {
        // Change [+] to [-] -- NOTE: if-else statement is used for IE compatibility
        if (dom_node.getElementsByTagName('a')[0].innerText) {
          dom_node.getElementsByTagName('a')[0].innerText = dom_node.getElementsByTagName('a')[0].innerText.replace('[+]', '[-]');
        } else {
          dom_node.getElementsByTagName('a')[0].textContent = dom_node.getElementsByTagName('a')[0].textContent.replace('[+]', '[-]');
        }
        dom_node.className = 'open';
        // Create new div
        var dd_list_div = document.createElement('div');
        dd_list_div.id = 'dd-list-' + id;
        // Create new span
        var status_span = document.createElement('span');
        status_span.className = 'status';
        status_span.appendChild(document.createTextNode('Loading...'));
        // Append span to div
        dd_list_div.appendChild(status_span);
        // Append div to dom_node
        dom_node.appendChild(dd_list_div);
        // Create url, ajax Object, and start ajax call
        var url  =  'http://www.robbecker.com/wp-content/themes/greentree/scripts/ddList.php?' + params; // TODO: There has GOT to be a better way to spec this path!
              // TODO: Got to figure out a way to implement this code below
              /*
              if (!globals) {
                globals = new Object;
              }
              if (!globals.ddLists) {
                globals.ddLists = new Array;
              }
              if (!globals.ddLists[id].updating) {
                globals.ddLists[id] = new ajaxObject(id, url, insertDDList);
                globals.ddLists[id].genRequest();
              }
              idea...
              try {
                if (globals) {
                  if (globals.ddLists) {
                    if (!globals.ddLists[id].updating) { 
                      //DO NOTHING 
                    }
                  }
                }
              }
              catch(e) {
                // if we got an error, decode the error and initialize the appropriate global variable(s)
              }
              finally {
                globals.ddLists[id] = new ajaxObject(id, url, insertDDList);
                globals.ddLists[id].genRequest();
              }
              */
        var ddList = new ajaxObject(id, url, insertDDList); // TODO: create ajaxObject in such a way as there can be multiple concurent objects
        ddList.genRequest();
      }
    } else throw (new Error('DOM Id supplied to ddList function does not exist'));
  }
  catch(e) {
    alert(e.name + '\n Line: ' + e.lineNumber + '\n' + e.message + '\n' + e.description);
    // TODO: for 'production' version of code, remove alert and possibly implement redirect to appropriate page
  }
}

/**
 * NAME: insertDDList()
 *
 * DESCRIPTION:
 *    Callback function for ddList().  Inserts the ajax response into
 *    the html document
 *
 * ARGUMENTS:
 *    response - an Ajax Call return object with these properties
 *     .text
 *     .xml
 *     .html   -- not implemented
 *     .domId
 *
 * RETURNS: Nothing
 *
 * DEPENDENCIES: None
 **/
function insertDDList(response) {
  var dd_list_div = document.getElementById('dd-list-' + response.id);
  if (response) {
    dd_list_div.innerHTML = response.text;
  } else {
    dd_list_div.innerHTML = "<p>No items found</p>";
  } 
}


/**
 * NAME: ajaxObject
 *
 * DESCRIPTION:
 *    Definition of the ajaxObject class, a generic object for making
 *    ajax calls
 *
 * ARGUMENTS:
 *    id ................... a DOM id
 *    url .................. the url of the server-side ajax script  
 *    processingFunction ... the function that will handle the ajax response
 *
 * PUBLIC PROPERTIES & METHODS:
 *    updating
 *    callback
 *    genRequest()
 *    abort()
 *
 * DEPENDENCIES: None
 **/
function ajaxObject(id, url, processingFunction) {

  // That is this ... DUH!
  // In asynchronous callback, we loose our 'this' reference
  // so we save our 'this' as 'that'.
  var that = this;
  var urlCall = url;
  
  this.domId = id; // TODO: Do I want this var public or private???
  
  //this.timestamp = time(); // TODO: Remove old timestamp scheme and simplify with this timestamp property
  
  // Boolean that tells us if our XHRobj is being processed
  this.updating = false;
  
  this.callback = processingFunction || function () { }; // TODO: Do I want this method public or private???
  //var callback = processingFunction || function () { };
  

  this.genRequest = function() {
    if (that.updating) {
      return false; 
    } else {
      that.XHRobj = null; 
      if (window.XMLHttpRequest) { 
        that.XHRobj = new XMLHttpRequest();
      } else if (window.ActiveXObject) { 
        that.XHRobj = new ActiveXObject("Microsoft.XMLHTTP");
      } 
      if (that.XHRobj) {
        that.XHRobj.onreadystatechange = function() { handleResponse(); }   
        that.updating = new Date();
        /* Code for POST -- ignoring for now
        if (/post/i.test(postMethod)) {
          var uri = urlCall + '?' + that.updating.getTime();
          that.XHRobj.open("POST", uri, true);
          that.XHRobj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
          that.XHRobj.setRequestHeader("Content-Length", passData.length);
          that.XHRobj.send(passData);
        } else { }
        */
        var uri=urlCall + '&timestamp=' + (that.updating.getTime()); 
        that.XHRobj.open("GET", uri, true); 
        that.XHRobj.send(null);
      } else {
        // Couldn't create an XHRobj
        return false;
      }         
    }
  }
  
  
  // var handleResponse = function() { // will this work?  I doubt it.
  handleResponse = function() {
    if (that.XHRobj.readyState == 4) {
      if (that.XHRobj.status == 200) {
        that.updating = false;
        // Create response object  // TODO: I don't like this syntax
        var response = new Object;
        response.text = that.XHRobj.responseText;
        response.xml = that.XHRobj.responseXML;
        response.id = that.domId;
        // Call processing function
        that.callback(response); 
        that.XHRobj = null; 
      } else {
        return false;
      }
    }
  }
  
  
  // Abort method, used to kill our XHRobj (in case it times out or
  // offends us in other ways)
  this.abort = function() {
    if (that.updating) {
      that.updating = false;
      that.XHRobj.abort();
      that.XHRobj = null;
    }
  }

  
}
