//\/////

//\  SOMI_G - You may not remove or change this notice.

//\  Do not sell this as your own work or remove this copyright notice.

//\  $Id: SOMI_G.js,v 1.84 2008/03/13 19:09:58 imacleod Exp $

//\

//\  Credit given (and copyright statements maintained) where code

//\  used directly or modified from other sources.

//\  

//\  This software is Copyright © 2006 The Regents of the University of

//\  California. All Rights Reserved.

//\  

//\  Permission to use, copy, modify, and distribute this software and its

//\  documentation for educational, research and non-profit purposes,

//\  without fee, and without a written agreement is hereby granted, provided

//\  that the above copyright notice, this paragraph and the following three

//\  paragraphs appear in all copies.

//\  

//\  Permission to incorporate this software into commercial products may be

//\  obtained by contacting

//\  Technology Transfer Office

//\  9500 Gilman Drive, Mail Code 0910

//\  University of California

//\  La Jolla, CA 92093-0910

//\  (858) 534-5815

//\  invent@ucsd.edu

//\  

//\  This software program and documentation are copyrighted by The Regents of the

//\  University of California. The software program and documentation are

//\  supplied "as is", without any accompanying services from The Regents.

//\  The Regents does not warrant that the operation of the program will be

//\  uninterrupted or error-free. The end-user understands that the program was

//\  developed for research purposes and is advised not to rely exclusively on

//\  the program for any reason.

//\  

//\  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO

//\  ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR

//\  CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING

//\  OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,

//\  EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF

//\  THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF

//\  CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,

//\  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF

//\  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

//\  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND

//\  THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO

//\  PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR

//\  MODIFICATIONS.

//\  

//\/////



//

// NO GLOBALS!  None used here.  Don't add any!

//

// Functions of generic use to SOMI, and other utilities.

//


// Sorting code (some of it) based on (http://www.tek-tips.com/faqs.cfm?fid=5347)

function G_sortSelectFormElement(element, asc) {
  if (arguments.length == 1) {
    asc = true;    // default to ascending sort

  }

  // copy options into an array

  var t_options = [];
  for (var i=0, len=element.options.length; i<len; i+=1) {
    var isSelected = false;
    if (element.selectedIndex == i) {
      isSelected = true;
    }
    t_options[i] = { text:element.options[i].text, value:element.options[i].value, selected:isSelected};
  }
  // sort array

  if (asc) {
    t_options.sort(G_compareOptionLabelsAsc);
  } else {
    t_options.sort(G_compareOptionLabelsDesc);
  }
  // copy sorted options from array back to select box

  // Do not forget to replace knowledge of which item

  // was selected before the sort.

  //

  element.options.length = 0;
  for (var i=0, len=t_options.length; i<len; i+=1) {
    var obj = document.createElement('option');
    obj.text = t_options[i].text;
    obj.value = t_options[i].value;
    element.options[element.options.length] = obj;
    if (t_options[i].selected) {
      element.selectedIndex = i;
    }
    // element.options.add(obj);  // Breaks in Safari

  }
};


function G_compareEventDates(a,b) {
   return a.dateTime - b.dateTime;
};


function G_compareOptionLabelsAsc(a,b) {
  var v1 = a.text.toLowerCase();
  var v2 = b.text.toLowerCase();
  if (v1 > v2) {
    return 1;
  }
  if (v1 < v2) {
    return -1;
  }
  return 0;
};


function G_compareOptionLabelsDesc(a,b) {
  var v1 = a.text.toLowerCase();
  var v2 = b.text.toLowerCase();
  if (v1 > v2) {
    return -1;
  }
  if (v1 < v2) {
    return 1;
  }
  return 0;
};


function G_removeDOMElement (id) {
  if (document.getElementById(id)) {
    var e = document.getElementById(id);
    //  Remove all of the elements' children first,

    //  then remove the child.

    //

    var child = e.firstChild;
    while (child) {
      e.removeChild(child);
      child = e.firstChild;
    }
    e.parentNode.removeChild(e);
  }
};


function G_parseXMLTextIntoDOM(text) {
    var doc;
    if (typeof DOMParser != 'undefined') {
        var parser = new DOMParser();
        doc = parser.parseFromString(text, "text/xml");
    }
    else if (typeof ActiveXObject != 'undefined') {
        doc=new ActiveXObject("Microsoft.XMLDOM");
        doc.async="false";
        doc.loadXML(text);
    }
    return doc;
};


function G_newXMLHttpRequest() {
  var xmlreq;

  // Build new XMLHttpRequest object, or catch and warn if this browser

  // does not support it.

  //

  // (see IBM - "Ajax for Java Developers: Build dynamic Java applications")

  //

  if (window.XMLHttpRequest) {
    // Create XMLHttpRequest object in non-Microsoft browsers

    xmlreq = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    // Create XMLHttpRequest via MS ActiveX

    try {
      // Try to create XMLHttpRequest in later versions of

      // Internet Explorer

      xmlreq = new ActiveXObject('Msxml2.XMLHTTP');
    } catch (e1) {
      // Failed to create required ActiveXObject

      try {
        // Try version supported by older versions of

        // Internet Explorer

        xmlreq = new ActiveXObject('Microsoft.XMLHTTP');
      } catch (e2) {
        // Last straw.  Unable to support our AJAX needs.  Bummer.

      }
    };
  }

  return xmlreq;
};



function G_getReadyStateHandler(req, responseXmlHandler, onComplete) {

   // Return an anonymous function that listens to the

   // XMLHttpRequest instance given to us.  Event-driven handlers

   // for document processing MUST be used or else LOTS of bad things

   // can happen.

   return function f () {

      // If the request's status is "complete"

      if (req.readyState == 4) {

        // Check that a successful server response was received

        if (req.status == 200) {

           // A successful response, and a complete

           // document.  We're done with the fetch...pass it

           // along to be processed.

           //

           var fetchedHeader = req.getResponseHeader('Date');
           var fetchedDate = new Date(fetchedHeader);
           responseXmlHandler(req,fetchedDate,onComplete);
        } else {
           // An HTTP problem has occurred

           alert("G_getReadyStateHandler : Error : HTTP request returned " + req.status);
        };
      }
   };
};






function G_resourceIsNewer(URI,type,date) {
  if (! date) {
    return false;
  }

  // 1. Obtain an XMLHttpRequest instance.

  //

  var req = G_newXMLHttpRequest();
  if (! req) {
     // Unsupported browser type

     alert("G_resourceIsNewer : Error : Could not perform AJAX (needed for our RSS capabilities) functions on this browser.  Sorry.  Please turn off RSS in SOMI.");
     return false;
  }

  // 2. Dispatch request for synchronous handling.

  //

  //    Third parameter in below open() indicates a synchronous request.

  //

  try {
    req.open('HEAD', URI, false);
    req.send(null);
    // Request for XML document was dispatched.

    // Processing will occur synchronously.

    // If the request's status is "complete"

    if (req.readyState == 4) {

        // Check that a successful server response was received

        if (req.status == 200) {

           // A successful response, and a complete

           // document.  We're done with the fetch...pass it

           // along to be processed.

           //

           var lastModified;
           var pattern = /\?/;
           if (URI.match(pattern)) {
             // A dynamic data source....always refresh!

             return true;
           }
           try {
             var lastModifiedHeader = req.getResponseHeader('Last-Modified');
             lastModified = new Date(lastModifiedHeader);
           } catch (e) {
             alert('G_resourceIsNewer : Error : Exception (' + e + ') encountered.');
           }
           if (lastModified > date) {
             return true;
           } else {
             return false;
           };
        } else {
           // An HTTP problem has occurred

           alert("G_resourceIsNewer : Error : HTTP HEAD returned " + req.status);
           return false;
        };
    } else {
      alert("G_resourceIsNewer : Error : HTTP HEAD request was not ready");
      return false;
    }
  } catch (e) {
    alert('G_resourceIsNewer : Error : ' + e.message + ' occurred because ' + e.reason +'.');
    return false;
  }
};



