/* EventCalendar. Copyright (C) 2005, Alex Tingle.  $Revision: 257 $
 * This file is licensed under the GNU GPL. See LICENSE file for details.
 */

// Set in HTML file:
//   var ec3.start_of_week
//   var ec3.month_of_year
//   var ec3.month_abbrev
//   var ec3.myfiles
//   var ec3.home
//   var ec3.hide_logo
//   var ec3.viewpostsfor

/** Register an onload function. */
function WindowOnload(f)
{
  var prev=window.onload;
  window.onload=function(){ if(prev)prev(); f(); }
}

// namespace
function ec3()
{
  WindowOnload( function()
  {
    // Overwrite the href links in ec3_prev & ec3_next to activate EC3.
    var prev=document.getElementById('ec3_prev');
    var next=document.getElementById('ec3_next');
    if(prev && next)
    {
      // Check for cat limit in month link
      var xCat=new RegExp('&cat=[0-9]+$');
      var match=xCat.exec(prev.href);
      if(match)
        ec3.catClause=match[0];
      // Replace links
      prev.onclick=ec3.go_prev;
      next.onclick=ec3.go_next;
      prev.className='ec3_button';
      next.className='ec3_button';
      // Pre-load image.
      ec3.imgwait=new Image(14,14);
      ec3.imgwait.src=ec3.myfiles+'/ec_load.gif';
      // Convert strings from PHP into Unicode
      ec3.viewpostsfor=unencode(ec3.viewpostsfor);
      for(var i=0; i<ec3.month_of_year.length; i++)
        ec3.month_of_year[i]=unencode(ec3.month_of_year[i]);
      for(var j=0; j<ec3.month_abbrev.length; j++)
        ec3.month_abbrev[j]=unencode(ec3.month_abbrev[j]);
    }
  } );

  /** Converts HTML encoded text (e.g. "&copy Copyright") into Unicode. */
  function unencode(text)
  {
    if(!ec3.unencodeDiv)
      ec3.unencodeDiv=document.createElement('div');
    ec3.unencodeDiv.innerHTML=text;
    return (ec3.unencodeDiv.innerText || ec3.unencodeDiv.firstChild.nodeValue);
  }

  function get_child_by_tag_name(element,tag_name)
  {
    var results=element.getElementsByTagName(tag_name);
    if(results)
      for(var i=0; i<results.length; i++)
        if(results[i].parentNode==element)
          return results[i];
    return 0;
  }
  ec3.get_child_by_tag_name=get_child_by_tag_name;


  function calc_day_id(day_num,month_num,year_num)
  {
    if(ec3.today_day_num==day_num &&
       ec3.today_month_num==month_num &&
       ec3.today_year_num==year_num)
    {
      return 'today';
    }
    else
    {
      return 'ec3_'+year_num+'_'+month_num+'_'+day_num;
    }
  }


  function create_calendar(table,month_num,year_num)
  {
    // Take a deep copy of the current calendar.
    var table=table.cloneNode(1);

    // Calculate the zero-based month_num
    var month_num0=month_num-1;

    // Set the new caption
    var caption_text=ec3.month_of_year[month_num0] + ' ' + year_num;
    var themonth=document.getElementById('ec3_themonth');
    if(themonth && themonth.firstChild && themonth.firstChild.nodeType==ec3.TEXT_NODE )
    	themonth.firstChild.data=caption_text;


    var tbody=get_child_by_tag_name(table,'tbody');

    // Remove all children from the table body
    while(tbody.lastChild)
      tbody.removeChild(tbody.lastChild);

    // Make a new calendar.
    var date=new Date(year_num,month_num0,1, 12,00,00);

    var tr=document.createElement('tr');
    var td,div;
    tbody.appendChild(tr);
    var day_count=0
    var col=0;
    while(date.getMonth()==month_num0 && day_count<40)
    {
      var day=(date.getDay()+7-ec3.start_of_week)%7;
      if(col>6)
      {
        tr=document.createElement('tr');
        tbody.appendChild(tr);
        col=0;
      }
      if(col<day)
      {
        // insert padding
        td=document.createElement('td');
        td.colSpan=day-col;
        td.className='pad';
        tr.appendChild(td);
        col=day;
      }
      // insert day
      td=document.createElement('td');
      td.appendChild(document.createTextNode(date.getDate()));
      td.id=calc_day_id(date.getDate(),month_num,year_num);
      tr.appendChild(td);
      col++;
      day_count++;
      date.setDate(date.getDate()+1);
    }
    // insert padding
    if(col<7)
    {
      td=document.createElement('td');
      td.colSpan=7-col;
      td.className='pad';
      tr.appendChild(td);
    }

    // add the 'dog'
    if((7-col)>1 && !ec3.hide_logo)
    {
      a=document.createElement('a');
      a.href='http://blog.firetree.net/?ec3_version='+ec3.version;
      a.title='Event Calendar '+ec3.version;
      td.style.verticalAlign='bottom';
      td.appendChild(a);
      div=document.createElement('div');
      div.className='ec3_ec';
      div.align='right'; // keeps IE happy
      a.appendChild(div);
    }

    // set table's element id
    table.id='ec3_'+year_num+'_'+month_num;

    return table;
  } // end create_calendar()


  /** Dispatch an XMLHttpRequest for a month of calendar entries. */
  function loadDates(month_num,year_num)
  {
    var req=new XMLHttpRequest();
    if(req)
    {
      ec3.reqs.push(req);
      req.onreadystatechange=process_xml;
      req.open("GET",
        ec3.home+'/?ec3_xml='+year_num+'_'+month_num,true);
      set_spinner(1);
      //var themonth=document.getElementById('ec3_themonth');
      //if(themonth && themonth.firstChild && themonth.firstChild.nodeType==ec3.TEXT_NODE )
//      	themonth.firstChild.data="Loading";
      req.send(null);
    }
  }


  /** Obtain an array of all the calendar tables. */
  function get_calendars()
  {
    var div=document.getElementById('wp-calendar');
    var result=new Array();
    for(var i=0; i<div.childNodes.length; i++)
    {
      var c=div.childNodes[i];
      if(c.id && c.id.search('ec3_[0-9]')==0 && c.style.display!='none')
        result.push(div.childNodes[i]);
    }
    if(result.length>0)
      return result;
    else
      return 0;
  }
  ec3.get_calendars=get_calendars;


  /** Changes the link text in the forward and backwards buttons.
   *  Parameters are the 0-based month numbers. */
  function rewrite_controls(month_num0, year_num, prev_month0, next_month0)
  {
    var prev=document.getElementById('ec3_prev');
    if(prev && prev.firstChild && prev.firstChild.nodeType==ec3.TEXT_NODE) {
    	prev.title=ec3.month_of_year[prev_month0%12];
    }
    var next=document.getElementById('ec3_next');
    if(next && next.firstChild && next.firstChild.nodeType==ec3.TEXT_NODE)
      next.title=ec3.month_of_year[next_month0%12];

    // Set the new caption
    var caption_text=ec3.month_of_year[month_num0-1] + ' ' + year_num;
    var themonth=document.getElementById('ec3_themonth');
    if(themonth && themonth.firstChild && themonth.firstChild.nodeType==ec3.TEXT_NODE )
    	themonth.firstChild.data=caption_text;
  }


  /** Turn the busy spinner on or off. */
  function set_spinner(on)
  {
    var spinner=document.getElementById('ec3_spinner');
    var publish=document.getElementById('ec3_publish');
    if(spinner)
    {
      if(on)
      {
        spinner.style.display='inline';
        if(publish)
          publish.style.display='none';
      }
      else
      {
        spinner.style.display='none';
        if(publish)
          publish.style.display='inline';
      }
    }
  }


  /** Called when the user clicks the 'previous month' button. */
  function go_prev()
  {
    var calendars=get_calendars();
    if(!calendars)
      return;
    var pn=calendars[0].parentNode;

    // calculate date of new calendar
    var id_array=calendars[0].id.split('_');
    if(id_array.length<3)
      return;
    var year_num=parseInt(id_array[1]);
    var month_num=parseInt(id_array[2])-1;
    if(month_num==0)
    {
      month_num=12;
      year_num--;
    }
    // Get new calendar
    var newcal=document.getElementById('ec3_'+year_num+'_'+month_num);
    if(newcal)
    {
      // Add in the new first calendar
      newcal.style.display="block"//ec3.calendar_display;
    }
    else
    {
      newcal=create_calendar(calendars[0],month_num,year_num);
      pn.insertBefore( newcal, calendars[0] );
      loadDates(month_num,year_num);
    }
    // Hide the last calendar
    ec3.calendar_display=calendars[calendars.length-1].style.display;
    calendars[calendars.length-1].style.display='none';

    // Re-write the forward & back buttons.
    rewrite_controls(month_num, year_num, month_num+10,month_num+calendars.length-1);
  }
  ec3.go_prev=go_prev;


  /** Called when the user clicks the 'next month' button. */
  function go_next()
  {
    var calendars=get_calendars();
    if(!calendars)
      return;
    var pn=calendars[0].parentNode;
    var last_cal=calendars[calendars.length-1];

    // calculate date of new calendar
    var id_array=last_cal.id.split('_');
    if(id_array.length<3)
      return;
    var year_num=parseInt(id_array[1]);
    var month_num=1+parseInt(id_array[2]);
    if(month_num==13)
    {
      month_num=1;
      year_num++;
    }
    // Get new calendar
    var newcal=document.getElementById('ec3_'+year_num+'_'+month_num);
    if(newcal)
    {
      // Add in the new last calendar
      newcal.style.display='block';//ec3.calendar_display;
    }
    else
    {
      newcal=create_calendar(calendars[0],month_num,year_num);
      if(last_cal.nextSibling)
        pn.insertBefore(newcal,last_cal.nextSibling);
      else
        pn.appendChild(newcal);
      loadDates(month_num,year_num);
    }
    // Hide the first calendar
    ec3.calendar_display=calendars[0].style.display;
    calendars[0].style.display='none';

    // Re-write the forward & back buttons.
    rewrite_controls(month_num, year_num, month_num-calendars.length+11,month_num);
  }
  ec3.go_next=go_next;


  /** Triggered when the XML load is complete. Checks that load is OK, and then
   *  updates calendar days. */
  function process_xml()
  {
    var busy=0;
    for(var i=0; i<ec3.reqs.length; i++)
    {
      var req=ec3.reqs[i];
      if(req)
      {
        if(req.readyState==4)
        {
          ec3.reqs[i]=0;
          if(req.status==200)
            update_days(req.responseXML.documentElement);
        }
        else
          busy=1;
      }
    }
    if(!busy)
    {
      // Remove old requests.
      while(ec3.reqs.shift && ec3.reqs.length && !ec3.reqs[0])
        ec3.reqs.shift();
      set_spinner(0);
    }
  }


  /** Adds links to the calendar for each day listed in the XML. */
  function update_days(month_xml)
  {
    var days=month_xml.getElementsByTagName('day');
    if(!days)
      return;
    for(var i=0; i<days.length; i++)
    {
      var td=document.getElementById(days[i].getAttribute('id'));
      if(td && td.firstChild && td.firstChild.nodeType==ec3.TEXT_NODE)
      {
        td.className='ec3_postday';
        var txt=td.removeChild(td.firstChild);
        var a=document.createElement('a');
        a.href=days[i].getAttribute('link');
        a.title=days[i].getAttribute('titles');
        if(days[i].getAttribute('is_event'))
        {
          td.className+=' ec3_eventday';
          a.className='eventday';
        }
        a.appendChild(txt);
        td.appendChild(a);
      }
    }
    if(typeof ec3_Popup != 'undefined')
    {
      var month=
        document.getElementById(month_xml.childNodes[0].getAttribute('id'));
      if(month)
        ec3_Popup.add_tbody( get_child_by_tag_name(month,'tbody') );
    }
  }


} // end namespace ec3

// Export public functions from ec3 namespace.
ec3();

// Set up static variables in namespace 'ec3'.

// Get today's date.
// Note - DO THIS ONCE, so that the value of today never changes!
ec3.today=new Date();
ec3.today_day_num=ec3.today.getDate();
ec3.today_month_num=1+ec3.today.getMonth();
ec3.today_year_num=ec3.today.getFullYear();

// Holds ongoing XmlHttp requests.
ec3.reqs=new Array();

ec3.ELEMENT_NODE=1;
ec3.TEXT_NODE=3;

ec3.version='3.1.1._rc1';




















































/* EventCalendar. Copyright (C) 2005, Alex Tingle.  $Revision: 65 $
 * This file is licensed under the GNU GPL. See LICENSE file for details.
 */

/** class ec3_Popup */
function ec3_Popup()
{

  WindowOnload( function()
  {
    var calendars=ec3.get_calendars();
    if(!calendars)
      return;
    // Pre-load images.
    ec3.imgShadow0=new Image(8,32);
    ec3.imgShadow1=new Image(500,16);
    ec3.imgShadow2=new Image(8,32);
    ec3.imgShadow0.src=ec3.myfiles+'/shadow0.png';
    ec3.imgShadow1.src=ec3.myfiles+'/shadow1.png';
    ec3.imgShadow2.src=ec3.myfiles+'/shadow2.png';

    // Generate the popup (but keep it hidden).
    var table,tbody,tr,td;
    ec3_Popup.popup=document.createElement('table');
    ec3_Popup.popup.style.display='none';
    ec3_Popup.popup.id='ec3_popup';
    ec3_Popup.popup.className='ec3_popup';
    tbody=ec3_Popup.popup.appendChild( document.createElement('tbody') );
    tr=tbody.appendChild( document.createElement('tr') );
    td=tr.appendChild( document.createElement('td') );
    td.id='ec3_shadow0';
    td.rowSpan=2;
    td.appendChild( document.createElement('div') );
    td=tr.appendChild( document.createElement('td') );
    ec3_Popup.contents=td.appendChild( document.createElement('table') );
    ec3_Popup.contents.style.width=500;
    td=tr.appendChild( document.createElement('td') );
    td.id='ec3_shadow2';
    td.rowSpan=2;
    td.appendChild( document.createElement('div') );
    tr=tbody.appendChild( document.createElement('tr') );
    td=tr.appendChild( document.createElement('td') );
    td.id='ec3_shadow1';

    document.body.appendChild(ec3_Popup.popup);

    // Add event handlers to the calendars.
    for(var i=0; i<calendars.length; i++)
      add_tbody( ec3.get_child_by_tag_name(calendars[i],'tbody') );
  } );

  function add_tbody(tbody)
  {
    if(!tbody)
      return;
    var anchor_list=tbody.getElementsByTagName('a');
    if(!anchor_list)
      return;
    for(var i=0; i<anchor_list.length; i++)
    {
      var a=anchor_list[i];
      var td=a.parentNode;
      // 'title' might have become 'nicetitle' if that plugin is being run.
      var titleattr=a.getAttribute('nicetitle');
      if(!titleattr)
          titleattr=a.getAttribute('title');
      if(titleattr && td.nodeName=='TD' && td.className!='pad')
      {
        td.setAttribute('ec3_title',titleattr);
        a.removeAttribute('nicetitle');
        a.removeAttribute('title');
        addEvent(td,'mouseover',show);
        addEvent(td,'mouseout',hide);
        addEvent(td,'focus',show);
        addEvent(td,'blur',hide);
      }
    }
  }
  ec3_Popup.add_tbody=add_tbody;

  function show(e)
  {
    var n;
    if(e.currentTarget)
        n=e.currentTarget; // Mozilla/Safari/w3c
    else if(window.event)
        n=window.event.srcElement; // IE
    else
        return;

    // Find the TD element and the calendar node.
    // (IE will sometimes randomly give us a child instead).
    var td,cal;
    while(1)
    {
      if(!n || n==document.body)
      {
        return;
      }
      else if(n.tagName=='TABLE')
      {
        cal=n;
        break;
      }
      else if(n.tagName=='TD')
      {
        td=n;
      }
      n=n.parentNode;
    }

    var ec3_title=td.getAttribute('ec3_title');
    if(typeof ec3_title == 'undefined')
      return;
    if(ec3_Popup.just_hidden)
       ec3_Popup.popup.style.display = "block";
    else
       ec3_Popup.show_timer=setTimeout(
         function(){ec3_Popup.popup.style.display = "block";},
         600
       );

    ec3_Popup.contents.style.width=''+(cal.offsetWidth-2)+'px';
    ec3_Popup.popup.style.top=''+(findPosY(cal)+cal.offsetHeight)+'px';
    ec3_Popup.popup.style.left=''+(findPosX(cal)-8)+'px';

    var tbody=ec3.get_child_by_tag_name(ec3_Popup.contents,'tbody');
    if(tbody)
      ec3_Popup.contents.removeChild(tbody);
    tbody=ec3_Popup.contents.appendChild(document.createElement('tbody'));

    var titles=ec3_title.split(', ');
    for(var i=0; i<titles.length; i++)
    {
      tr=tbody.appendChild(document.createElement('tr'));
      td=tr.appendChild(document.createElement('td'));
      td.appendChild(document.createTextNode(titles[i]));
      if(titles[i].indexOf('@')!=-1)
        td.className='eventday';
    }

    // Let's put this event to a halt before it starts messing things up
    window.event? window.event.cancelBubble=true: e.stopPropagation();
  }

  function hide()
  {
    if(ec3_Popup.show_timer)
      clearTimeout(ec3_Popup.show_timer);
    if(ec3_Popup.popup.style.display!='none')
    {
     ec3_Popup.just_hidden=1;
     ec3_Popup.hide_timer=setTimeout(function(){ec3_Popup.just_hidden=0;},900);
    }
    ec3_Popup.popup.style.display='none';

  }

  //=====================================================================
  // Event Listener
  // by Scott Andrew - http://scottandrew.com
  // edited by Mark Wubben, <useCapture> is now set to false
  //=====================================================================
  function addEvent(obj, evType, fn){
    if(obj.addEventListener){
      obj.addEventListener(evType, fn, false);
      return true;
    } else if (obj.attachEvent){
      var r = obj.attachEvent('on'+evType, fn);
      return r;
    } else {
      return false;
    }
  }

  //=====================================================================
  // From http://www.quirksmode.org/
  //=====================================================================
  function findPosX(obj)
  {
    var curleft = 0;
    if (obj.offsetParent)
    {
      while(1)
      {
        curleft += obj.offsetLeft;
	if(!obj.offsetParent) break;
        obj = obj.offsetParent;
      }
    }
    else if (obj.x)
      curleft += obj.x;
    return curleft;
  }

  function findPosY(obj)
  {
    var curtop = 0;
    if (obj.offsetParent)
    {
      while(1)
      {
        curtop += obj.offsetTop;
	if(!obj.offsetParent) break;
        obj = obj.offsetParent;
      }
    }
    else if (obj.y)
      curtop += obj.y;
    return curtop;
  }

} // end namespace ec3_Popup

// Export public functions from ec3_Popup namespace.
ec3_Popup();
























































/*********************************/
/*

Cross-Browser XMLHttpRequest v1.2
=================================

Emulate Gecko 'XMLHttpRequest()' functionality in IE and Opera. Opera requires
the Sun Java Runtime Environment <http://www.java.com/>.

by Andrew Gregory
http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/

This work is licensed under the Creative Commons Attribution License. To view a
copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ or
send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California
94305, USA.

Attribution: Leave my name and web address in this script intact.

Not Supported in Opera
----------------------
* user/password authentication
* responseXML data member

Not Fully Supported in Opera
----------------------------
* async requests
* abort()
* getAllResponseHeaders(), getAllResponseHeader(header)

*/
// IE support
if (window.ActiveXObject && !window.XMLHttpRequest) {
  window.XMLHttpRequest = function() {
    var msxmls = new Array(
      'Msxml2.XMLHTTP.5.0',
      'Msxml2.XMLHTTP.4.0',
      'Msxml2.XMLHTTP.3.0',
      'Msxml2.XMLHTTP',
      'Microsoft.XMLHTTP');
    for (var i = 0; i < msxmls.length; i++) {
      try {
        return new ActiveXObject(msxmls[i]);
      } catch (e) {
      }
    }
    return null;
  };
}
// Gecko support
/* ;-) */
// Opera support
if (window.opera && !window.XMLHttpRequest) {
  window.XMLHttpRequest = function() {
    this.readyState = 0; // 0=uninitialized,1=loading,2=loaded,3=interactive,4=complete
    this.status = 0; // HTTP status codes
    this.statusText = '';
    this._headers = [];
    this._aborted = false;
    this._async = true;
    this._defaultCharset = 'ISO-8859-1';
    this._getCharset = function() {
      var charset = _defaultCharset;
      var contentType = this.getResponseHeader('Content-type').toUpperCase();
      val = contentType.indexOf('CHARSET=');
      if (val != -1) {
        charset = contentType.substring(val);
      }
      val = charset.indexOf(';');
      if (val != -1) {
        charset = charset.substring(0, val);
      }
      val = charset.indexOf(',');
      if (val != -1) {
        charset = charset.substring(0, val);
      }
      return charset;
    };
    this.abort = function() {
      this._aborted = true;
    };
    this.getAllResponseHeaders = function() {
      return this.getAllResponseHeader('*');
    };
    this.getAllResponseHeader = function(header) {
      var ret = '';
      for (var i = 0; i < this._headers.length; i++) {
        if (header == '*' || this._headers[i].h == header) {
          ret += this._headers[i].h + ': ' + this._headers[i].v + '\n';
        }
      }
      return ret;
    };
    this.getResponseHeader = function(header) {
      var ret = getAllResponseHeader(header);
      var i = ret.indexOf('\n');
      if (i != -1) {
        ret = ret.substring(0, i);
      }
      return ret;
    };
    this.setRequestHeader = function(header, value) {
      this._headers[this._headers.length] = {h:header, v:value};
    };
    this.open = function(method, url, async, user, password) {
      this.method = method;
      this.url = url;
      this._async = true;
      this._aborted = false;
      this._headers = [];
      if (arguments.length >= 3) {
        this._async = async;
      }
      if (arguments.length > 3) {
        opera.postError('XMLHttpRequest.open() - user/password not supported');
      }
      this.readyState = 1;
      if (this.onreadystatechange) {
        this.onreadystatechange();
      }
    };
    this.send = function(data) {
      if (!navigator.javaEnabled()) {
        alert("XMLHttpRequest.send() - Java must be installed and enabled.");
        return;
      }
      if (this._async) {
        setTimeout(this._sendasync, 0, this, data);
        // this is not really asynchronous and won't execute until the current
        // execution context ends
      } else {
        this._sendsync(data);
      }
    }
    this._sendasync = function(req, data) {
      if (!req._aborted) {
        req._sendsync(data);
      }
    };
    this._sendsync = function(data) {
      this.readyState = 2;
      if (this.onreadystatechange) {
        this.onreadystatechange();
      }
      // open connection
      var url = new java.net.URL(new java.net.URL(window.location.href), this.url);
      var conn = url.openConnection();
      for (var i = 0; i < this._headers.length; i++) {
        conn.setRequestProperty(this._headers[i].h, this._headers[i].v);
      }
      this._headers = [];
      if (this.method == 'POST') {
        // POST data
        conn.setDoOutput(true);
        var wr = new java.io.OutputStreamWriter(conn.getOutputStream(), this._getCharset());
        wr.write(data);
        wr.flush();
        wr.close();
      }
      // read response headers
      // NOTE: the getHeaderField() methods always return nulls for me :(
      var gotContentEncoding = false;
      var gotContentLength = false;
      var gotContentType = false;
      var gotDate = false;
      var gotExpiration = false;
      var gotLastModified = false;
      for (var i = 0; ; i++) {
        var hdrName = conn.getHeaderFieldKey(i);
        var hdrValue = conn.getHeaderField(i);
        if (hdrName == null && hdrValue == null) {
          break;
        }
        if (hdrName != null) {
          this._headers[this._headers.length] = {h:hdrName, v:hdrValue};
          switch (hdrName.toLowerCase()) {
            case 'content-encoding': gotContentEncoding = true; break;
            case 'content-length'  : gotContentLength   = true; break;
            case 'content-type'    : gotContentType     = true; break;
            case 'date'            : gotDate            = true; break;
            case 'expires'         : gotExpiration      = true; break;
            case 'last-modified'   : gotLastModified    = true; break;
          }
        }
      }
      // try to fill in any missing header information
      var val;
      val = conn.getContentEncoding();
      if (val != null && !gotContentEncoding) this._headers[this._headers.length] = {h:'Content-encoding', v:val};
      val = conn.getContentLength();
      if (val != -1 && !gotContentLength) this._headers[this._headers.length] = {h:'Content-length', v:val};
      val = conn.getContentType();
      if (val != null && !gotContentType) this._headers[this._headers.length] = {h:'Content-type', v:val};
      val = conn.getDate();
      if (val != 0 && !gotDate) this._headers[this._headers.length] = {h:'Date', v:(new Date(val)).toUTCString()};
      val = conn.getExpiration();
      if (val != 0 && !gotExpiration) this._headers[this._headers.length] = {h:'Expires', v:(new Date(val)).toUTCString()};
      val = conn.getLastModified();
      if (val != 0 && !gotLastModified) this._headers[this._headers.length] = {h:'Last-modified', v:(new Date(val)).toUTCString()};
      // read response data
      var reqdata = '';
      var stream = conn.getInputStream();
      if (stream) {
        var reader = new java.io.BufferedReader(new java.io.InputStreamReader(stream, this._getCharset()));
        var line;
        while ((line = reader.readLine()) != null) {
          if (this.readyState == 2) {
            this.readyState = 3;
            if (this.onreadystatechange) {
              this.onreadystatechange();
            }
          }
          reqdata += line + '\n';
        }
        reader.close();
        this.status = 200;
        this.statusText = 'OK';
        this.responseText = reqdata;
        this.readyState = 4;
        if (this.onreadystatechange) {
          this.onreadystatechange();
        }
        if (this.onload) {
          this.onload();
        }
      } else {
        // error
        this.status = 404;
        this.statusText = 'Not Found';
        this.responseText = '';
        this.readyState = 4;
        if (this.onreadystatechange) {
          this.onreadystatechange();
        }
        if (this.onerror) {
          this.onerror();
        }
      }
    };
  };
}
// ActiveXObject emulation
if (!window.ActiveXObject && window.XMLHttpRequest) {
  window.ActiveXObject = function(type) {
    switch (type.toLowerCase()) {
      case 'microsoft.xmlhttp':
      case 'msxml2.xmlhttp':
      case 'msxml2.xmlhttp.3.0':
      case 'msxml2.xmlhttp.4.0':
      case 'msxml2.xmlhttp.5.0':
        return new XMLHttpRequest();
    }
    return null;
  };
}