// 1.1.102

/*
Version History:
  1.1.102 (2010-03-13)
    1) Tweak to get_taxes_applied() to simplify logic very slightly.
       Also changed variables to reflect that this uses BILLING addresses
  1.1.101 (2010-03-12)
    1) Added get_taxes_applied() - formerly produced by Tax_Regime
       This routine now handles unlimited tax types, wildcard matches and even inversions:
          e.g. 'CAN.*', '*.*', '!CAN.*'
  1.1.100 (2010-02-13)
    1) Change to popup_layer() to accept community_member_dashboard NOT community_dashboard
  1.1.99 (2010-02-03)
    1) Added inline_signin_hide_msg()
  1.1.98 (2010-01-06)
    1) Change in validate_payment_details() to prevent year detection range fault in FF when this year > 2009
       Was due to non-y2k safe use of getYear() instead of getUTCFullYear()
  1.1.97 (2010-01-04)
    1) Change to Calendar.prototype.hideShowCovered() to prevent operation if IE8+ is in use
       (Fixes bug XIM 35)
  1.1.96 (2009-12-23)
    1) Added popWin_post() to overcome 20 selected items limit
    2) selected_operation() removed 200 item limit
    3) Moved selected_operation to member.js
    4) Eliminated last of suppor for non-friendly URLs
  1.1.95 (2009-12-19)
    1) Added flowplayer support - flowplayer_popup() and flowplayer_video()
  1.1.94 (2009-11-25)
    1) Change to ajax_report() to propagate DD, MM and YYYY -
       used in visitor stats reports, closes bug XIM-54
  1.1.93 (2009-11-11)
    1) Change to geid_val() for type 'select-one' to return '' if there is no option selected (i.e. -1)
  1.1.92 (2009-10-20)
    1) Added bug_form()
  1.1.91 (2009-10-17)
    1) Change to ajax_config_display() to handle library_csstatus
  1.1.90 (2009-10-14)
    1) Change to keytest_enter_transfer() to focus on the target button before activating the click
    2) Change to filterbar_value_onkeypress() to focus on the target button before activating the click
    3) Change to filterbar_save_onclick() to apply filter value before saving new filter

  (older history - see ./functions_changelog.txt)

*/

// ************************************
// * Browser detection:               *
// ************************************
var isNS4 =	(navigator.appName.indexOf("Netscape")>=0 && !document.getElementById) ? true : false;
var isNS6 =	(document.getElementById && navigator.appName.indexOf("Netscape")>=0 ) ? true : false;
var isW3C =	(document.getElementById && 1) ? true : false;

var isIE =	(document.uniqueID) ? true : false;
var isIE4 =	(isIE && !document.getElementById) ? true : false;
var isIE5 =	(isIE && window.clipboardData && !window.createPopup) ? true : false;
var isIE55 =	(isIE && window.createPopup && !document.compatMode) ? true : false;
var isIE6 =	(isIE && document.compatMode && !window.XMLHttpRequest) ? true : false;
var isIE7 =	(isIE && window.XMLHttpRequest) ? true : false;
var isIE8 =	(isIE && window.toStaticHTML) ? true : false;

var isIE_lt6 =	(isIE && !document.compatMode) ? true : false;
var isIE_lt7 =	(isIE && !window.XMLHttpRequest) ? true : false;
var isIE_lt8 =	(isIE && !window.toStaticHTML) ? true : false;

var popup_msg =	'';
var ajax_controls = [];


// These are for browsers with JS < 1.2 such as IE5

//not working for Mozilla
/*
if (!Array.prototype.shift) {
  Array.prototype.shift = function() {
    var temp = this[0];
    this = this.slice(1);
    return temp;
  }
}

if (!Array.prototype.unshift) {
  Array.prototype.unshift = function(e) {
    var temp = new Array();
    temp.concat(e, this);
    this = temp.slice(0);
    return this.length;
  }
}
*/
if (!Array.prototype.pop) {
  Array.prototype.pop = function() {
    var temp = this[this.length-1];
    this.length--;
    return temp;
  }
}

if (!Array.prototype.push) {
  Array.prototype.push = function(item) {
    this[this.length] = item;
    return this.length;
  }
}

if(typeof encodeURIComponent != "function") {
  encodeURIComponent = function(str){
    var decVals = ["%",'"'," ","<",">","\\[","\\]","\\\\","\\^","~","\\{","\\}","\\|","\\:",";","#","\\$","&",",","/","=","\\?","@"];
    var encVals = ["%25","%22","%20","%3C","%3E","%5B","%5D","%5C","%5E","~","%7B","%7D","%7C","%3A","%3B","%23","%24","%26","%2C","%2F","%3D","%3F","%40"];
    for(var i=0;i<decVals.length;i++){
       document.title = decVals[i];
       var re = new RegExp(decVals[i],"gi");
       str = str.replace(re,encVals[i]);
    }
    return str;
  }
}



function copy_clip(meintext){
  if (window.clipboardData) {
    window.clipboardData.setData("Text", meintext);
    return true;
  }
  if (window.netscape){
    try { 
      netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
      var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
      if (!clip)
        return false;
      var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
      if (!trans)
        return false;
      trans.addDataFlavor('text/unicode');
      var str = new Object();
      var len = new Object();
      var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
      var copytext=meintext;
      str.data=copytext;
      trans.setTransferData("text/unicode",str,copytext.length*2);
      var clipid=Components.interfaces.nsIClipboard;
      if (!clip)
        return false;
      clip.setData(trans,null,clipid.kGlobalClipboard);
      return true
    }
    catch(e){
      alert(
        "For Firefox you need to enable the privilege:\n"+
        "  1) Type   about:config   in the address bar\n"+
        "  2) In the filter bar enter 'signed'\n"+
        "  3) Double click on the line 'signed.applets.codebase_principal_support'\n"+
        "  4) Now try again - and then confirm that you do indeed trust this site.\n"
      );
      return false;
    }
  }
  return false;
}


// ************************************
// * externalLinks                    *
// ************************************
// Ref: http://www.sitepoint.com/article/standards-compliant-world/3
//      http://www.biblegateway.com/passage/?search=matthew+10:16
//
// 'Try / Catch' Fix suggested by James Fraser to prevent hrefs with '%' crashing JS engine in IE

function externalLinks() { 
  if (!document.getElementsByTagName) return; 
  var anchors = document.getElementsByTagName("a");
  for (var i=0; i<anchors.length; i++) { 
    var anchor = anchors[i];
    try{
      if (typeof anchor.getAttribute("href")=='string' && anchor.getAttribute("href") && anchor.getAttribute("rel") == "external"){
        anchor.target = "_blank";
      }
      if (anchor.className=='rss-item') {
        anchor.target = "_blank";
      }
      if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "disabled"){
        anchor.disabled = true;
      }
    }
    catch (e) {
      alert("This link has an invalid href:\n"+anchor.outerHTML);
    }
  } 
}

// ************************************
// * getElementById() aliases         *
// ************************************
function geid(id) {
  if(typeof(id)=='string' && id!='') {
    if (document.getElementById(id)) {
      return document.getElementById(id);
    }
    if (document.getElementById('form') && document.getElementById('form').elements[id]){
      return document.getElementById('form').elements[id];
    }
    return null;
  }
  return id;
}

function geid_val(id) {
  if (id=='') {
    return false;
  }
  // FF fails on getElementByID where ID is one of several
  var obj, element_arr;
  obj = geid(id);
  if (obj && typeof obj.type !='undefined'){
    switch (obj.type) {
      case 'checkbox':
        return (obj.checked ? obj.value : '')
      break;
      case 'file':
      case 'hidden':
      case 'password':
      case 'text':
      case 'textarea':
        return obj.value;
      break;
      case 'radio':
        return radio_group_get(id);
      break;
      case 'select-one':
        if (obj.selectedIndex==-1){
          return "";
        }
        return obj.options[obj.selectedIndex].value;
      break;
    }
  }
  if (document.getElementsByName) {
    element_arr = document.getElementsByName(id);
    if (typeof element_arr[0]=='undefined') {
      return false;
    }
    switch (element_arr[0].type) {
      case 'radio':
        return radio_group_get(id);
      break;
    }
  }
//  alert("Error:\ngeid_val('"+id+"') found unhandled object type "+element_arr[0].type);
  return obj.value;
}

function geid_set(id,value) {
  // FF fails on getElementByID where ID is one of several
  var obj, element_arr;
  obj = geid(id);
  if (obj && typeof obj.type !='undefined'){
    switch (obj.type) {
      case 'checkbox':
        obj.checked = value;
        return true;
      break;
      case 'file':
      case 'hidden':
      case 'password':
      case 'text':
      case 'textarea':
        obj.value = value;
        return true;
      break;
      case 'radio':
        alert('Cannot set radio using this function yet');
        return false;
      break;
      case 'select-one':
        var n;
        for (var n=0; n<obj.length; n++){
          if (obj.options[n].value==value) {
            obj.selectedIndex = n;
            return true;
          }
        }
        return false;
      break;
    }
  }
  alert("Error:\ngeid_set('"+id+"') found unhandled object type");
  return false;

}
// ************************************
// * Input validation                 *
// ************************************
function match_picture(picture,val) {
  for (i=0; i<picture.length; i++){
    if (val.length<=i) {
      break;
    }
    switch(picture.substr(i,1)) {
      case "0":
        rexp = /[\d]/;
        if (!rexp.test(val.substr(i,1))){
          return val.substr(0,i);
        }
      break;
      case "-":
        rexp = /[\-]/;
        if (!rexp.test(val.substr(i,1))){
          return val.substr(0,i)+"-";
        }
      break;
      case " ":
        rexp = /[ ]/;
        if (!rexp.test(val.substr(i,1))){
          return val.substr(0,i)+" ";
        }
      break;
      case ":":
        rexp = /[\:]/;
        if (!rexp.test(val.substr(i,1))){
          return val.substr(0,i)+":";
        }
      break;
    }
  }
  return val
}

function afb(id,type,args) {
  return attach_field_behaviour(id,type,args);
}

function attach_field_behaviour(id,type,args) {
  var obj, fn, val, yyyy, mm, dd, dash, leap, _hh, _mm, i;
  var pattern, rexp;

  obj = geid(id);
  if (!obj) {
    return;
  }
  switch (type){
    case 'currency':
    case 'currency_s':
      fn = function(e){
        val = geid(id).value;
        if (typeof args!='undefined' && typeof args['min']!='undefined') {
          val = (val < args['min'] ? args['min'] : val);
        }
        if (typeof args!='undefined' && typeof args['max']!='undefined') {
          val = (val > args['max'] ? args['max'] : val);
        }
        geid(id).value=two_dp(val);
        if (typeof geid(id).onchange=='function'){
          geid(id).onchange();
        }
      } 
      addEvent(obj, "blur", fn); 
    break;
    case 'date':
    case 'datetime':
      fn = function(e){
        val = match_picture('0000-00-00 00:00',geid_val(id).toString());
        if (val.length>=4) {
          yyyy = parseFloat(val.substr(0,4));
          leap = ((yyyy%4==0) && (yyyy%100!=0)) || (yyyy%400==0);
          if (yyyy!=0 && yyyy<1900) {
            geid_set(id,'1900');
            return;
          }
          if (yyyy>2100) {
            geid_set(id,'2100');
            return;
          }
        }
        if (val.length>=7) {
          mm = parseFloat(val.substr(5,2));
          if (mm<1) {
            geid_set(id,val.substr(0,5)+'01');
            return;
          }
          if (mm>12) {
            geid_set(id,val.substr(0,5)+'12');
            return;
          }
        }
        if (val.length>=10) {
          dd = parseFloat(val.substr(8,2));
          if (dd<1) {
            geid_set(id,val.substr(0,8)+'01');
            return;
          }
          if (!leap && mm==2 && dd>28) {
            geid_set(id,val.substr(0,8)+'28');
            return;
          }
          if (leap && mm==2 && dd>29) {
            geid_set(id,val.substr(0,8)+'29');
            return;
          }
          if ((mm==4 ||  mm==6 || mm==9 || mm==11) && dd>30) {
            geid_set(id,val.substr(0,8)+'30');
            return;
          }
          if (dd>31) {
            geid_set(id,val.substr(0,8)+'31');
            return;
          }
        }
        if (val.length>=13) {
          _hh = parseFloat(val.substr(11,2));
          if (_hh<1) {
            geid_set(id,val.substr(0,11)+'00');
            return;
          }
          if (_hh>23) {
            geid_set(id,val.substr(0,11)+'23');
            return;
          }
        }
        if (val.length>=16) {
          _mm = parseFloat(val.substr(14,2));
          if (_mm<1) {
            geid_set(id,val.substr(0,14)+'00');
            return;
          }
          if (_mm>59) {
            geid_set(id,val.substr(0,14)+'59');
            return;
          }
        }
        if (val.length>=19) {
          _ss = parseFloat(val.substr(17,2));
          if (_ss<1) {
            geid_set(id,val.substr(0,17)+'00');
            return;
          }
          if (_ss>59) {
            geid_set(id,val.substr(0,17)+'59');
            return;
          }
        }
        geid_set(id,val);
      }
      addEvent(obj, "keyup", fn); 
    break;
    case 'hh:mm':
      fn = function(e){
        val = match_picture('00:00',geid_val(id).toString());
        if (val.length>=1) {
          var hh_10 = parseInt(val.substr(0,1));
          if (hh_10>2) {
            geid_set(id,'2'+val.substr(1));
            return;
          }
        }
        if (val.length>=2) {
          var hh_1 = parseInt(val.substr(1,1));
          if (hh_10==2 && hh_1>3) {
            geid_set(id,val.substr(0,1)+'3'+val.substr(2));
            return;
          }
        }
        if (val.length>=4) {
          var mm_10 = parseInt(val.substr(3,1));
          if (mm_10>5) {
            geid_set(id,val.substr(0,3)+'5');
            return;
          }
        }
        geid_set(id,val);
      }
      addEvent(obj, "keyup", fn); 
    break;
    case 'posting_name':
      fn =
        function(e){
          if (geid(id) && geid_val(id)=='' && geid('title')){
            geid_set(id,geid_val('title'));
          }
          var name =
            geid_val(id).toLowerCase().
              replace(/[\(\)]/g,'').replace(/  /g,' ').
              replace(/ - /g,'-').replace(/ /g,'-').
              replace(/\%/g,'pc').replace(/[^0-9\-a-zA-Z\(\)\%]/g,'');
          geid_set(id,name);
        };
      addEvent(window,'load',fn);
      addEvent(geid(id), "change", fn);
      addEvent(geid('title'), "change", fn);
    break;
    case 'qty':
      // Up button:
      fn = function(e){geid(id).value=parseInt(geid(id).value)+1;geid(id).onchange();}
      addEvent(geid(id+'_up'), "click", fn);
      fn = function(e){geid(id+'_up').style.backgroundPosition='-1434px 0px'}
      addEvent(geid(id+'_up'), "mouseover", fn);
      fn = function(e){geid(id+'_up').style.backgroundPosition='-1423px 0px'}
      addEvent(geid(id+'_up'), "mouseout", fn);


      // Down button:
      fn = function(e){if (parseInt(geid(id).value)>0){geid(id).value=parseInt(geid_val(id))-1;geid(id).onchange();}}
      addEvent(geid(id+'_down'), "click", fn);
      fn = function(e){if (parseInt(geid(id).value)>0){geid(id+'_down').style.backgroundPosition='-1434px 8px'}}
      addEvent(geid(id+'_down'), "mouseover", fn);
      fn = function(e){if (parseInt(geid(id).value)>0){geid(id+'_down').style.backgroundPosition='-1423px 8px'}}
      addEvent(geid(id+'_down'), "mouseout", fn);


      switch (parseInt(obj.value)){
        case 0:
          geid(id+'_down').style.backgroundPosition='-1445px 8px';
        break;
        default:
          geid(id+'_down').style.backgroundPosition='-1423px 8px';
        break;
      }
    break;

    case 'readonly':
      obj.style.backgroundColor='#f0f0f0';
      obj.style.color='#404040';
      fn = function(e){this.blur();}; 
      addEvent(obj, "focus", fn);
    break;

    case 'seq':
      if (geid_val('ID')) {
        geid(id).style.backgroundColor="";
        geid(id+'_up').style.backgroundPosition='-1423px 0px';
        switch (parseInt(obj.value)){
          case 0:
          case 1:
          break;
          default:
            geid(id+'_down').style.backgroundPosition='-1423px 8px';
          break;
        }
      }   

      // Up button:
      fn = function(e){
        if (geid_val('ID')){
          geid(id).style.backgroundColor='#e8e8e8';
          geid(id+'_up').onclick=null;
          geid(id+'_up').onmouseover=null;
          geid(id+'_up').onmouseout=null;
          geid(id+'_down').onclick=null;
          geid(id+'_down').onmouseover=null;
          geid(id+'_down').onmouseout=null;
          geid('targetField').value=id;
          geid('targetValue').value=parseInt(geid(id).value)+1;
          geid('submode').value='seq_up';
          geid(id+'_up').style.backgroundPosition='-1445px 0px';
          geid(id+'_down').style.backgroundPosition='-1445px 8px';
          geid('form').submit();
        }
      }
      geid(id+'_up').onclick=fn;

      fn = function(e){
        if (geid_val('ID')) {
          geid(id+'_up').style.backgroundPosition='-1434px 0px';
        }
      }
      geid(id+'_up').onmouseover=fn;

      fn = function(e){
        if (geid_val('ID')) {
          geid(id+'_up').style.backgroundPosition='-1423px 0px';
        }
      }
      geid(id+'_up').onmouseout=fn;

      // Down button:
      fn = function(e){
        if (geid_val('ID') && parseInt(geid(id).value)>0){
          geid(id).style.backgroundColor='#e8e8e8';
          geid(id+'_up').onclick=null;
          geid(id+'_up').onmouseover=null;
          geid(id+'_up').onmouseout=null;
          geid(id+'_down').onclick=null;
          geid(id+'_down').onmouseover=null;
          geid(id+'_down').onmouseout=null;
          geid('targetField').value=id;
          geid('targetValue').value=parseInt(geid(id).value)-1;
          geid('submode').value='seq_down';
          geid(id+'_up').style.backgroundPosition='-1445px 0px';
          geid(id+'_down').style.backgroundPosition='-1445px 8px';
          geid('form').submit();
        }
      }
      geid(id+'_down').onclick=fn;

      fn = function(e){
        if (geid_val('ID') && parseInt(geid(id).value)>0){
          geid(id+'_down').style.backgroundPosition='-1434px 8px'
        }
      }
      geid(id+'_down').onmouseover=fn;

      fn = function(e){
        if (geid_val('ID') && parseInt(geid(id).value)>0){
          geid(id+'_down').style.backgroundPosition='-1423px 8px';
        }
      }
      geid(id+'_down').onmouseout=fn;
    break;

    case 'swatch':
      obj.value=obj.value.toUpperCase();
    break;
  }
  fn = function(e){return keytest(e,type,obj);} 
  addEvent(obj, "keypress", fn); 
}

  
function keytest(e,type,obj){
  var keynum, keychar, rexp, ok, value, delete2;
  rexp = false;
  if (window.event) {
    keynum = e.keyCode;
  }
  else {
    keynum = e.which;
  }
  keychar = String.fromCharCode(keynum);
  switch (type) {
    case 'currency':
      rexp = /[\d\.\-]/;
    break;
    case 'currency_s':
      rexp = /[\d\.]/;
    break;
    case 'date':
      rexp = /[\d\-]/;
    break;
    case 'datetime':
      rexp = /[\d\-\: ]/;
    break;
    case 'hh:mm':
      rexp = /[\d\:]/;
    break;
    case 'int':
    case 'seq':
      rexp = /[\d\-]/;
    break;
    case 'int_s':
      rexp = /[\d]/;
    break;
    case 'posting_name':
      rexp = /[\d\-a-zA-Z\(\)]/;
    break;
    case 'qty':
      rexp = /[\d]/;
    break;
    case 'percent':
      rexp = /[\d\.]/;
    break;
    case 'swatch':
      if (e.keyCode>96 && e.keyCode<122){
        e.keyCode-=32;
      }
      rexp = /[\dabcdefABCDEF]/;
    break;
    default:
//      alert(type+' is not handled');
    break;
  }
  var result = rexp!==false && rexp.test(keychar);
  if (!result && e.preventDefault) {
    switch (e.keyCode) {
      case 8: case 27: case 37: case 38: case 39: case 40: case 46:
      break;
      default: 
        e.preventDefault();
      break;
    }
  }
  return result;
}
function keytest_enter_execute(e,fn) {
  var keynum = (window.event ? e.keyCode : e.which);
  if(keynum == 13) {
    fn();
    return false;
  }
  return true; 
}
function keytest_enter_transfer(e,btn) {
  fn = function(){
    geid(btn).focus();
    geid(btn).click();
  };
  return keytest_enter_execute(e,fn);
}

function bugtracker_form(){
  var h,j,div;
  h="<div id='popup_form' style='padding:4px;'>Loading...</div>";
  popup_dialog('Report a Bug',h,524,400,'','');

  var post_vars = "ajax=1";
  popup_layer_submit(base_url+'_bug',post_vars);
  return false;
}

function bugtracker_form_onsubmit(){
  geid('bugtracker_form_cancel').disabled=true;
  geid('bugtracker_form_submit').disabled=true;
  var post_vars =
    "ajax=1" +
    "&subject="+encodeURIComponent(geid_val('bugtracker_form_subject')) +
    "&submode=bugtracker_submit";
  popup_layer_submit(base_url+'_bug',post_vars);
}

function char_counter(input,max,countID) {
  var _count = document.getElementById(countID);
  if (input.value.length>max) {input.value = input.value.substr(0,max); }
  _count.innerHTML = max - input.value.length + ' character' + (input.value.length==max-1 ? '' : 's')+' left';
}


function comment(mode,ID,submode,commentID) {
  var obj,js,pw;
  pw =
     "<img class='fl' src='"+base_url+"img/?mode=sysimg&img=progress_indicator.gif' width='16' height='16' alt='Please wait...'>"
    +"<div class='fl' style='color:#808080'><em>&nbsp;Loading... Please Wait</em></div><div class='clr_b'></div>";
  switch (submode){
    case "cancel":
      geid('comment_button_cancel').disabled=true;
      geid('comment_button_submit').disabled=true;
      if (geid_val('comment_text') + geid_val('captcha_key') == '' || confirm('Really cancel? Your changes will be lost.')){
        window.focus();
        geid('comment_new').innerHTML="<p><a href=\"javascript:void comment('"+mode+"','"+ID+"','new')\">Add Comment</a></p>";
      }
      else {
        geid('comment_button_cancel').disabled=false;
        geid('comment_button_submit').disabled=false;
      }
      return false;
    break;
    case "delete":
      return comment_delete(mode,ID,commentID);
    break;
    case "edit":
      window.focus();
      xFn = function() { comment_get_count(mode,ID) };
      include(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode='+submode+'&commentID='+commentID,'comment_'+commentID,xFn);
      return false;
    break;
    case "mark_approved":
      return comment_mark(mode,ID,commentID,'approved');
    break;
    case "mark_pending":
      return comment_mark(mode,ID,commentID,'pending');
    break;
    case "mark_spam":
      return comment_mark(mode,ID,commentID,'spam');
    break;
    case "new":
      window.focus();
      geid('comment_new').innerHTML=pw;
      include(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode='+submode,'comment_new');
      return false;
    break;
    case "post":
      window.focus();
      geid('comment_button_cancel').disabled=true;
      geid('comment_button_submit').disabled=true;

      var abort = false;
      geid('th_comment_name').style.color = 	(geid_val('comment_name')=='' ? '#ff0000' : '');
      geid('th_comment_email').style.color =	(geid_val('comment_email')=='' ? '#ff0000' : '');
      geid('th_comment_text').style.color =	(geid_val('comment_text')=='' ? '#ff0000' : '');
      geid('th_captcha_key').style.color =	(geid_val('captcha_key')=='' ? '#ff0000' : '');

      if (geid_val('comment_name')=='' || geid_val('comment_email')=='' || geid_val('comment_text')=='' || geid_val('captcha_key')=='') {
        abort=true;
      }
      if (abort){
        alert('Missing fields');
        geid('comment_button_cancel').disabled=false;
        geid('comment_button_submit').disabled=false;
      }
      else {
        window.focus();
        post_vars =
          "comment_name="+encodeURIComponent(geid_val('comment_name'))+
          "&comment_email="+encodeURIComponent(geid_val('comment_email'))+
          "&comment_url="+encodeURIComponent(geid_val('comment_url'))+
          "&comment_text="+encodeURIComponent(geid_val('comment_text'))+
          "&captcha_key="+encodeURIComponent(geid_val('captcha_key'));
        xFn =
          function() {
            comment_show_all(mode,ID);
          }
        ajax_post(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode='+submode,'comment_new',post_vars,xFn);
      }
      return false;
    break;
    case "save":
      window.focus();
      var abort = false;
      geid('th_comment_name').style.color = 	(geid_val('comment_name')=='' ? '#ff0000' : '');
      geid('th_comment_email').style.color =	(geid_val('comment_email')=='' ? '#ff0000' : '');
      geid('th_comment_text').style.color =	(geid_val('comment_text')=='' ? '#ff0000' : '');

      if (geid_val('comment_name')=='' || geid_val('comment_email')=='' || geid_val('comment_text')=='') {
        abort=true;
      }
      if (abort){
        alert('Missing fields');
      }
      else {
        window.focus();
        post_vars =
          "comment_approved="+encodeURIComponent(geid_val('comment_approved'))+
          "&comment_name="+encodeURIComponent(geid_val('comment_name'))+
          "&comment_email="+encodeURIComponent(geid_val('comment_email'))+
          "&comment_url="+encodeURIComponent(geid_val('comment_url'))+
          "&comment_text="+encodeURIComponent(geid_val('comment_text'));
        xFn = function() { comment_show_all(mode,ID) };
        ajax_post(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode='+submode+'&commentID='+commentID+'&rnd='+Math.random(),'comment_'+commentID,post_vars,xFn);
      }
      return false;
    break;
    case "show":
      window.focus();
      include(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode='+submode+'&commentID='+commentID+'&rnd='+Math.random(),'comment_'+commentID);
      return false;
    break;
  }
  return false;
}
function comment_get_count(mode,ID) {
  include(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode=get_count&rnd='+Math.random(),'comment_count');
}
function comment_mark(mode,ID,commentID,status) {
  window.focus();
  post_vars = "comment_approved="+status;
  xFn = function() { comment_get_count(mode,ID) };
  ajax_post(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode=mark&commentID='+commentID+'&rnd='+Math.random(),'comment_'+commentID,post_vars,xFn);
  return false;
}
function comment_delete(mode,ID,commentID) {
  window.focus();
  xFn = function() { comment_get_count(mode,ID) };
  include(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode=delete&commentID='+commentID,'comment_'+commentID,xFn);
  obj = geid('comment_'+commentID);
  obj.parentNode.removeChild(obj);
}
function comment_show_all(mode,ID) {
  include(base_url+'?command=comment&mode='+mode+'&ID='+ID+'&submode=show_all','comments_list')
}
function csv_item_set(csv,value,add){
  var val_arr, new_arr, new_csv;
  val_arr = csv.split(',');
  new_arr =[];
  switch(add) {
    case false:
      for (var i=0; i<val_arr.length; i++){
        if (val_arr[i]!=='' && val_arr[i]!=value){
          new_arr.push(val_arr[i]);
        }
      }
    break;
    default:
      new_csv = csv_item_set(csv,value,false);
      new_arr = (new_csv!=='' ? new_csv.split(',') : []);
      new_arr.push(value);
    break;
  }
  return new_arr.join(',');
}

function cursorGetSelectionEnd(o) {
  if (o.createTextRange) {
    var r = document.selection.createRange().duplicate();
    r.moveStart('character', -o.value.length);
    return r.text.length;
  }
  return o.selectionEnd;
}

function cursorGetSelectionStart(o) {
  if (o.createTextRange) {
    var r = document.selection.createRange().duplicate();
    r.moveEnd('character', o.value.length);
    if (r.text == ''){
      return o.value.length;
    }
    return o.value.lastIndexOf(r.text);
  }
  return o.selectionStart;
}

function cursorIsAtEnd(o) {
  var end = o.value.length;
  if (cursorGetSelectionStart(o)==end){
    if (cursorGetSelectionEnd(o)<end){
      cursorSetPosition(o,end);
      return false;
    }
    return true;
  }
  return false;
}

function cursorIsAtStart(o) {
  if (cursorGetSelectionStart(o)==0){
    if (cursorGetSelectionEnd(o)>0){
      cursorSetPosition(o,0);
      return false;
    }
    return true;
  }
  return false;
}

function cursorSetPosition(o,pos){
  if (o.createTextRange) {
    var range = o.createTextRange();
    range.collapse(true);
    range.moveEnd('character', pos);
    range.moveStart('character', pos);
    range.select();
    return true;
  }
  else if (o.setSelectionRange) {
    o.focus();
    o.setSelectionRange(pos,pos);
    return true;
  }
  return false;
}

function date_selector_draw(base_id,date){
  var out = [], i, i_str;

  out.push(
     "<select class='formField' id='"+base_id+"_yyyy' onchange=\"date_selector_onchange('"+base_id+"')\">\n"
    +"  <option value=\"\"" + (date.length<4 ? " selected='selected'" : "") + ">----</option>\n"
  );

  for (i=_global_date_range_min.substr(0,4); i <= _global_date_range_max.substr(0,4); i++){
    out.push("  <option value=\""+i+"\"" + (date.length>=4 && date.substr(0,4)==i.toString() ? " selected='selected'" : "") + ">"+i+"</option>\n");
  }
  out.push("</select> - ");
  
  out.push(
     "<select class='formField' id='"+base_id+"_mm' onchange=\"date_selector_onchange('"+base_id+"')\">\n"
    +"  <option value=\"\"" + (date.length<7 ? " selected='selected'" : "") + ">--</option>\n"
  );

  for (i=1; i<=12; i++){
    i_str = lead_zero(i.toString(),2);
    out.push("  <option value=\""+i_str+"\"" + (date.length>=5 && date.substr(5,2)==i_str ? " selected='selected'" : "") + ">"+i_str+"</option>\n");
  }
  out.push("</select> - ");
  out.push(
     "<select class='formField' id='"+base_id+"_dd'>\n"
    +"  <option value=\"\"" + (date.length<10 ? " selected='selected'" : "") + ">--</option>\n"
  );

  for (i=1; i<=31; i++){
    i_str = lead_zero(i.toString(),2);
    out.push("  <option value=\""+i_str+"\"" + (date.length>=10 && date.substr(8,2)==i_str ? " selected='selected'" : "") + ">"+i_str+"</option>\n");
  }
  out.push("</select>");
  return (out.join(''));
}

function date_selector_onchange(base_id) {
  var opt, yyyy, dd, leap, i;
  if (geid_val(base_id+'_yyyy')==''){
    geid_set(base_id+'_mm','');
  }
  if (geid_val(base_id+'_mm')==''){
    geid_set(base_id+'_dd','');
  }
  else {
    yyyy = parseFloat(geid_val(base_id+'_yyyy'));
    leap = ((yyyy%4==0) && (yyyy%100!=0)) || (yyyy%400==0);

    switch (parseFloat(geid_val(base_id+'_mm'))){
      case 4: case 6: case 9: case 11:
        max_dd = 30;
      break;
      case 2:
        max_dd = (leap ? 29 : 28);
      break;
      default:
        max_dd = 31;
      break
    }

    dd = geid_val(base_id+"_dd");

    for (i=0; i< geid(base_id+'_dd').length; i++) {
      geid(base_id+'_dd').remove(i);
    }

    opt = new Option();
    opt.text = '--';
    opt.value = '';
    if (dd=='') {
      opt.selected = true;
    }
    geid(base_id+'_dd').options[0] = opt;

    for (i=1; i<=max_dd; i++) {
      i_str = lead_zero(i.toString(),2);
      opt = new Option();
      opt.text = i_str;
      opt.value = i_str;
      if (dd == i_str){
        opt.selected = true;
      }
      geid(base_id+'_dd').options[i] = opt;
    }
    if (parseFloat(dd)>max_dd){
      geid(base_id+"_dd").options[geid(base_id+"_dd").length-1].selected=true;
    }
  }
  geid(base_id+'_mm').disabled = (geid_val(base_id+'_yyyy')=='' ? true : false);
  geid(base_id+'_dd').disabled = (geid_val(base_id+'_mm')=='' ? true : false);

}

function div_toggle(id){
  var div = geid(id);
  div.style.display=(div.style.display=='none' ? '' : 'none');
  return false;
}

// ************************************
// * Document Reader functions        *
// ************************************
function document_reader(div) {
  var p =
    (window.location.hash.length && parseFloat(window.location.hash.substr(1)) ?
       parseFloat(window.location.hash.substr(1)-1)
     : 0
    );
  var out = [], page, pages, link_title_lbl_this_prefix;
  pages = doc.pages_total;
  out.push(
     "<div style='margin:0 auto;' class='txt_c'>"
    +"  <div style='margin:0 auto;width:160px;height:30px;' class='txt_c clr_b'>\n"
    +"    <div id='mag_1' class='fl' style='margin:5px;width:15px;background-color:#c0c0c0;display:inline;font-weight:bold'></div>\n"
    +"    <div id='mag_2' class='fl' style='margin:5px;width:100px;background-color:#c0c0c0;font-weight:bold'></div>\n"
    +"    <div id='mag_3' class='fl' style='margin:5px;width:15px;background-color:#c0c0c0;font-weight:bold'></div>\n"
    +"  </div>"
    +"  <div class='clr_b'></div>"
    +"[ ");

  for (var i=0; i<pages; i++) {
    page = document_reader_get_page_name(i,pages);
    link_title_prefix = document_reader_get_page_prefix(i);
    out.push(
       "<a href='#' title='View "+link_title_prefix+page+"' onclick='return document_reader_goto_page("+i+")'>"
      +"<span id='p"+(i)+"'>"+page+"</span>"
      +"</a> ");
  }
  out.push(" ]</div>");
  out.push("<p class=\"txt_c\"><img id=\"img_doc\" border=\"1\" alt=\"\" src=\""+(doc.cover_file)+"\" /></p>");
  geid(div).innerHTML = out.join('');
  document_reader_goto_page(p,pages);
}

function document_reader_get_page_name(page){
  if (typeof(doc.named_pages[page+1])!='undefined'){
    return doc.named_pages[page+1];
  }
  if (typeof(doc.named_pages[-1*(doc.pages_total-page)])!='undefined'){
    return doc.named_pages[-1*(doc.pages_total-page)];
  }
  if (page<0 || page>doc.pages_total) {
    return "&nbsp;"
  }
  if (doc.pages_per_image==1) {
    return (page+1-doc.number_offset);
  }
  var start = ((page - 1 )*doc.pages_per_image)+ doc.number_offset;
  var end =   start+doc.pages_per_image-1;
  return start+"-"+end;
}
function document_reader_get_page_prefix(page){
  if (typeof(doc.named_pages[page+1])!='undefined'){
    return "";
  }
  if (typeof(doc.named_pages[-1*(doc.pages_total-page)])!='undefined'){
    return "";
  }
  if (page<0 || page>doc.pages_total) {
    return ""
  }
  if (doc.pages_per_image==1) {
    return "Page ";
  }
  return "Pages ";
}


function document_reader_goto_page(page) {
  var lbl_back, lbl_back_prefixed, lbl_this, lbl_next, lbl_next_prefixed, link_back, link_next;
  var m_1 = geid('mag_1');
  var m_2 = geid('mag_2');
  var m_3 = geid('mag_3');

  lbl_back =          document_reader_get_page_name(page-1);
  lbl_back_prefixed = document_reader_get_page_prefix(page-1)+lbl_back;
  link_back =	     "<a href='#' title='View "+lbl_back_prefixed+"' onclick='return document_reader_goto_page("+(page-1)+")'>&lt;</a>";

  lbl_next =          document_reader_get_page_name(page+1);
  lbl_next_prefixed = document_reader_get_page_prefix(page+1)+lbl_next;
  link_next =        "<a href='#' title='View "+lbl_next_prefixed+"' onclick='return document_reader_goto_page("+(page+1)+")'>&gt;</a>";

  m_1.innerHTML = (page==0 ? '&nbsp;' : link_back);
  m_2.innerHTML = document_reader_get_page_name(page);
  m_3.innerHTML = (page==doc.pages_total-1 ? '&nbsp;' : link_next);

  for (var i=0; i<doc.pages_total; i++){
    geid('p'+(i)).style.backgroundColor='#ffffff';
  }
  geid('p'+(page)).style.backgroundColor='#ffff00';
  geid('img_doc').src = (page==0 ? doc.cover_file : doc.pages_filepath+(page+1)+doc.pages_filetype);
  return false;
}
function image_rotator(id,img_arr,idx,secShow,secFade) {
  window.setTimeout(function(){image_rotator_step(id,img_arr,1,idx,secShow,secFade)},secShow*1000);
}

function image_rotator_step(id,img_arr,step,idx,secShow,secFade) {
  var img1 = geid(id+'_1');
  var img2 = geid(id+'_2');
  if (step == 10) {
    img2.style.opacity = 0;
    img2.style.filter = 'alpha(opacity=0)';
    img1.src = img2.src;
    window.setTimeout(function(){image_rotator(id,img_arr,idx,secShow,secFade)}, secShow*1000);
  }
  else if(step == 1) {
    if (idx == img_arr.length - 1) {
      idx = -1;
    }
    idx++;
    img2.style.opacity = 0.1;
    img2.style.filter = 'alpha(opacity=10)';
    img2.src = img_arr[idx].image;
    step++;
    window.setTimeout(function(){image_rotator_step(id,img_arr,step,idx,secShow,secFade)}, secFade*100);
  }
  else {
    img2.style.opacity = step / 10;
    img2.style.filter = 'alpha(opacity=' + step * 10 + ')';
    step++;
    window.setTimeout(function(){image_rotator_step(id,img_arr,step,idx,secShow,secFade)}, secFade*100);
  }
}

function inline_signin_hide_msg(){
  var div;
  if (div = geid('topbar_signin_msg')){
    div.style.display='none';
  }
}


// ************************************
// * open_item()                      *
// ************************************
function open_item(type,ID,page) {
  switch (type) {
    case 'article':
    case 'event':
    case 'news':
    case 'job':
    case 'podcast':
      popWin(
        base_url+type+'/'+ID,type+'_'+ID,'location=1,status=1,scrollbars=1,resizable=1',720,400,1
      );
    break;
    case 'page':
      popWin(
        base_url+page,type+'_'+ID,'location=1,status=1,scrollbars=1,resizable=1',720,400,1
      );
    break;
    default:
      alert("open_item() - unknown type '"+type+"'");
    break;
  }
}

// ************************************
// * Polling functions                *
// ************************************
function poll(mode,ID) {
  var pw =
     "<img class='fl' src='"+base_url+"img/sysimg/progress_indicator.gif' width='16' height='16' alt='Please wait...'>"
    +"<div class='fl' style='color:#808080'><em>&nbsp;Loading... Please Wait</em></div><div class='clr_b'></div>";
  switch (mode){
    case "limit":
      var a = geid_val('poll_choice_for_'+ID);
      var a_count = (a==='' ? 0 : a.split(',').length);
      var max=parseInt(geid_val('poll_max_votes_for_'+ID));

      var elements = geid('poll_'+ID).getElementsByTagName('input');
      var ids = [];
      for (var i=0; i<elements.length; i++){
        if(elements[i].type=='checkbox'){
          geid('poll_choice_row_'+elements[i].value).className=(elements[i].checked ? 'selected ' : '');
          if (a_count>=max) {
            geid('poll_choice_row_'+elements[i].value).className+=(elements[i].checked ? '' : 'disabled ');
            elements[i].disabled=!elements[i].checked;
            if (elements[i].disabled) {
            }
          }
          else {
            elements[i].disabled=false;
          }
        }
      }
    break;
    case "result":
      geid('poll_'+ID).innerHTML=pw;
      include(base_url+'?command=poll_result&targetID='+ID,'poll_'+ID);
      return false;
    break;
    case "show":
      geid('poll_'+ID).innerHTML=pw;
      include(base_url+'?command=poll_show&targetID='+ID,'poll_'+ID);
      return false;
    break;
    case "vote":
      var a=geid_val('poll_choice_for_'+ID);
      var a_count = (a==='' ? 0 : a.split(',').length);
      var max=parseInt(geid_val('poll_max_votes_for_'+ID));
      if (!a_count) {
        alert('Please choose '+(max>1 ? 'up to '+max+' options' : 'an option'));
        return false;
      }
      if (a_count<max){
        if (!confirm('You may choose up to '+max+' options - continue with '+a_count+'?')) {
          return false;
        }
      }
      geid('poll_'+ID).innerHTML=pw;
      include(base_url+'?command=poll_vote&targetID='+ID+'&targetValue='+a,'poll_'+ID);
      return false;
    break;
  }
  return true;
}

// ************************************
// * Rating functions                 *
// ************************************
function rating_blocks_init(){
  var fn, i, j, k, l, obj, obj2;
  var n = 1;

  for (i=0; i<rating_blocks.length; i++) {
    obj = geid('rating_'+rating_blocks[i]);
    for (j=0; j<obj.childNodes.length; j++){
      for (k = 0, l = obj.childNodes[j].childNodes.length; k < l; k++) {
        var obj2 = obj.childNodes[j].childNodes[k];
        if (obj2.nodeType === 1) {
          rating_blocks_set_fn(rating_blocks[i],obj2,n++);
        }
      }      
    }
  }
  function rating_blocks_set_fn(id,obj,value){
    obj.title='Click to award a rating of '+value;
    var fn =
      function(e){
      var obj2 = geid('rating_'+id);
      var n=0;
      for (i=0; i<obj2.childNodes.length; i++){
        obj3 = obj2.childNodes[i];
        if (obj3.nodeType === 1) {
          obj3.style.backgroundPosition=(value>n++ ? '0px -26px' : '0px -39px');
        }
      }
    }
    obj.onmouseover=fn; // workaround since addEvent method fails in this context for Opera - don't know why.
    fn =
      function(e){
        var obj2 = geid('rating_'+id)
        for (i=0; i<obj2.childNodes.length; i++){
          obj3 = obj2.childNodes[i];
          if (obj3.nodeType === 1) {
            obj3.style.backgroundPosition='0px -39px';
          }
        }
      }
    obj.onmouseout=fn;
    fn =
      function(){
        this.blur();rating_submit(id,value);return false;
      }
    obj.onclick=fn;
  }
}
function rating_submit(id,value) {
  var pw =
     "<img class='fl' src='"+base_url+"img/?mode=sysimg&img=progress_indicator.gif' width='16' height='16' alt='Please wait...'>"
    +"<div class='fl' style='color:#808080'><em>&nbsp;Recording... Please Wait</em></div><div class='clr_b'></div>";
  geid('rating_block_'+id).innerHTML=pw;
  include(base_url+'?command=rating_submit&targetID='+id+'&targetValue='+value,'rating_block_'+id);
}

// ************************************
// * Popup Layer functions            *
// ************************************
/**
 * POPUP WINDOW CODE v1.1
 * By Seth Banks (webmaster at subimage dot com)
 * http://www.subimage.com/
 *
 * Contributions by Eric Angel (tab index code) and Scott (hiding/showing selects for IE users)
 * Up to date code can be found at http://www.subimage.com/dhtml/subModal
 * This code is free for you to use anywhere, just keep this comment block.
 */

// Popup code
var gPopupMask = null;
var gPopupContainer = null;
var gPopFrame = null;
var gReturnFunc;
var gPopupIsShown = false;
var gFckEditorsLoading = new Array();

var gHideSelects = false;


var gTabIndexes = new Array();
// Pre-defined list of tags we want to disable/enable tabbing into
var gTabbableTags = new Array("A","BUTTON","TEXTAREA","INPUT","IFRAME");

// If using Mozilla or Firefox, use Tab-key trap.
if (!document.all) {
	document.onkeypress = keyDownHandler;
}

/**
 * Initializes popup code on load.
 */

/**
 * @argument width - int in pixels
 * @argument height - int in pixels
 * @argument returnFunc - function to call when returning true from the window.
 */
function showPopWin(title,body,width,height,returnFunc) {
  gPopupMask =		geid("popupMask");
  gPopupContainer =	geid("popupContainer");
  gPopFrame =		geid("popupFrame");

  // check to see if this is IE version 6 or lower. hide select boxes if so
  // maybe they'll fix this in version 7?

  var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10);
  if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE") > -1) {
    gHideSelects = true;
  }

  gPopupIsShown = true;
  disableTabIndexes();
  gPopupMask.style.display = "block";
  gPopupContainer.style.display = "block";

  // calculate where to place the window on screen
  centerPopWin(width, height);
  var titleBarHeight = parseInt(geid("popupTitleBar").offsetHeight, 10);

  if (width)  { gPopupContainer.style.width = width + "px"; }
  if (height) { gPopupContainer.style.height = (height+titleBarHeight) + "px"; }

  geid("popupTitle").innerHTML='<strong>'+system_family+'</strong>: '+title;
  geid("popupBody").innerHTML=body;
  gReturnFunc = returnFunc;
  // for IE
  if (gHideSelects == true) {
    hideSelectBoxes();
  }

  new Draggable('popupInner',{handle:'popupTitleBar'});

}
function setFocus(id) {
  if (!geid(id)){
    return;
  }
  var obj = geid(id);
  obj.focus(); // needs to be done twice for IE7 - don't know why
} 

//
var gi = 0;
function centerPopWin(width, height) {
  if (gPopupIsShown == true) {
    if (width == null || isNaN(width)) {
      width = gPopupContainer.offsetWidth;
    }
    if (height == null) {
      height = gPopupContainer.offsetHeight;
    }

    var fullHeight = getViewportHeight();
    var fullWidth = getViewportWidth();

    var theBody = document.documentElement;

    var scTop = parseInt(theBody.scrollTop,10);
    var scLeft = parseInt(theBody.scrollLeft,10);

    gPopupMask.style.height = fullHeight + "px";
    gPopupMask.style.width = fullWidth + "px";
    gPopupMask.style.top = scTop + "px";
    gPopupMask.style.left = scLeft + "px";

    var titleBarHeight = parseInt(geid("popupTitleBar").offsetHeight, 10);

    gPopupContainer.style.top = (scTop + ((fullHeight - (height+titleBarHeight)) / 2)) + "px";
    gPopupContainer.style.left =  (scLeft + ((fullWidth - width) / 2)) + "px";
    //alert(fullWidth + " " + width + " " + gPopupContainer.style.left);
  }
}
addEvent(window, "resize", centerPopWin);
addEvent(window, "scroll", centerPopWin);
window.onscroll = centerPopWin;

/**
 * @argument callReturnFunc - bool - determines if we call the return function specified
 * @argument returnVal - anything - return value
 */
function hidePopWin(callReturnFunc) {
  gPopupIsShown = false;
  restoreTabIndexes();
  if (gPopupMask == null) {
    return;
  }
  gPopupMask.style.display = "none";
  gPopupContainer.style.display = "none";
  if (callReturnFunc == true && gReturnFunc != null) {
    gReturnFunc(window.frames["popupFrame"].returnVal);
  }
  // display all select boxes
  if (gHideSelects == true) {
    displaySelectBoxes();
  }
}

/**
 * Sets the popup title based on the title of the html document it contains.
 * Uses a timeout to keep checking until the title is valid.
 */

// Tab key trap. iff popup is shown and key was [TAB], suppress it.
// @argument e - event - keyboard event that caused this function to be called.
function keyDownHandler(e) {
    if (gPopupIsShown && e.keyCode == 9)  return false;
    return true;
}

// For IE.  Go through predefined tags and disable tabbing into them.
function disableTabIndexes() {
  if (document.all) {
    var i = 0;
    for (var j = 0; j < gTabbableTags.length; j++) {
      var tagElements = document.getElementsByTagName(gTabbableTags[j]);
      for (var k = 0 ; k < tagElements.length; k++) {
        gTabIndexes[i] = tagElements[k].tabIndex;
        tagElements[k].tabIndex="-1";
        i++;
      }
    }
  }
}

// For IE. Restore tab-indexes.
function restoreTabIndexes() {
  if (document.all) {
    var i = 0;
    for (var j = 0; j < gTabbableTags.length; j++) {
      var tagElements = document.getElementsByTagName(gTabbableTags[j]);
      for (var k = 0 ; k < tagElements.length; k++) {
        tagElements[k].tabIndex = gTabIndexes[i];
        tagElements[k].tabEnabled = true;
        i++;
      }
    }
  }
}


/**
* Hides all drop down form select boxes on the screen so they do not appear above the mask layer.
* IE has a problem with wanted select form tags to always be the topmost z-index or layer
*
* Thanks for the code Scott!
*/
function hideSelectBoxes() {
  for(var i = 0; i < document.forms.length; i++) {
    for(var e = 0; e < document.forms[i].length; e++){
      if(document.forms[i].elements[e].tagName == "SELECT") {
        document.forms[i].elements[e].style.visibility="hidden";
      }
    }
  }
}

/**
* Makes all drop down form select boxes on the screen visible so they do not reappear after the dialog is closed.
* IE has a problem with wanted select form tags to always be the topmost z-index or layer
*/
function displaySelectBoxes() {
  for(var i = 0; i < document.forms.length; i++) {
    for(var e = 0; e < document.forms[i].length; e++){
      if(document.forms[i].elements[e].tagName == "SELECT") {
      document.forms[i].elements[e].style.visibility="visible";
      }
    }
  }
}

function popup_hide_on_loaded() {
  if (gFckEditorsLoading==0) {
    hidePopWin(null);
  }
  else {
    setTimeout('popup_hide_on_loaded()',500);
  }
}

// ************************************
// * (End of Popup Layer functions)   *
// ************************************
// These ones are mine...

// ************************************
// * Popup Dialog                     *
// ************************************
function popup_dialog(title,html,width,height,btn_ok_txt,btn_cancel_txt,btn_ok_js,focus){
  var h,response;
  h = "<div id='popup_wait' style='display:none;'>"
     +"<img class='fl' src='"+base_url+"img/sysimg/icon_hourglass.gif' width='32' height='32' alt='Please wait...'>"
     +"<div class='fl' id='popup_wait_txt'></div>"
     +"<div class='clr_b'></div>"
     +"</div>"
     +"<div id='popup_content'>"
     +html
     +"</div>"
     +(btn_ok_txt || btn_cancel_txt ? "<div id='popup_buttons' style='padding-top:5px;margin:auto' class='txt_c'>" : "")
     +(btn_ok_txt=='' ?
         ""
      :
         "<input type='button' id='btn_ok' class='formButton' style='width:60px;' value='"+btn_ok_txt+"' "
        +"onclick=\""
        +(btn_ok_js!='' ? btn_ok_js+";" : "")
        +"this.disabled=1;if(geid('btn_cancel')){geid('btn_cancel').disabled=1;};"
        +"hidePopWin(null);response=true;"
        +"\" />"
     )
     +(btn_cancel_txt=="" ?
        ""
      : "<input type='button' id='btn_cancel' class='formButton' style='width:60px;' value='"+btn_cancel_txt+"' onclick='hidePopWin(null);response=false;' />"
      )
     +(btn_ok_txt || btn_cancel_txt ? "</div>" : "")
     ;
  showPopWin(title,h,width,height,null);
  setFocus(focus);
  return response;
}
function popup_wait(txt) {
  geid('popup_buttons').style.display='none';
  geid('popup_wait_txt').innerHTML=txt;
  geid('popup_content').style.display='none';
  geid('popup_wait').style.display='';
}
function popup_layer(title,mode,width,height){
  var h,j,xFn;
  h="<div id='popup_form'><div style='padding:4px'>Loading...</div></div>";
  if (mode=='community_member_dashboard') {
    popup_dialog(title,h,width,height,'','');
  }
  else {
    popup_dialog(title,h,width,height,'','Close');
  }
  url = base_url+'_popup_layer/'+mode+'/'+width+'/'+height;
  new Ajax.Request(
    url,
    {
      method: 'post',
      onSuccess: function(transport){
        var layer = $('popup_form');
        var json = transport.responseText.evalJSON();
        layer.innerHTML=json.html;
        eval(json.js);
        if (json.css){ cssAddJsonStyle(eval(json.css)) ;}
      }
    }
  );
}
function cssAddJsonStyle(cssObj) {
  var css, i, ob;
  for (i=0; i<cssObj.length; i++){
    $$(cssObj[i][0]).each(function(el){el.setStyle(cssObj[i][1])})
  }
}

function popup_layer_submit(url,args){
  var post_vars, frm, field, i, uri, value;
  window.focus();

  frm = geid('form');
  post_vars = [];
  for (i=0; i<frm.elements.length; i++){
    field = frm.elements[i].name;
    value = geid_val(field);
    if (value!='') {
      switch(field) {
        case "goto":
        case "mode":
          // do nothing
        break;
        default:
          post_vars.push(field+'='+encodeURIComponent(value));
        break;
      }
    }
  }
  var vars = '?'+post_vars.join('&')+(typeof('args')!='undefined' ? '&'+args : '');
  new Ajax.Request(
    url,
    {
      method: 'post',
      postBody : vars,
      onSuccess: function(transport){
        var layer = $('popup_form');
        var json = transport.responseText.evalJSON();
        layer.innerHTML=json.html;
	eval(json.js);
        if (json.css){ cssAddJsonStyle(eval(json.css)) ;}
      }
    }
  );
}

function show_popup_screensize(current,option_csv) {
  var h, j, option_arr;
  option_arr = option_csv.split(',');
  var valid = false;
  for (i=0; i<option_arr.length; i++) {
    option = option_arr[i];
    if (option==current) {
      valid=true;
    }
  }
  if (!valid) { current = option_arr[0];}

  h = "<div style='padding:4px;'>Please select your preferred screen size:"
     +"<input type='hidden' id='screen_size_old' value='"+current+"'/>"
     +"<input type='hidden' id='screen_size_new' value='"+current+"'/>"
     +"<div style='padding:5px;'>";

  for (i=0; i< option_arr.length; i++) {
    option = option_arr[i];
    h +=
      "<label>"
     +"<input type='radio' name='screen_size' value='" + option + "'"
     +(current==option ? " checked='checked'" : '')
     +" onchange=\"geid('screen_size_new').value=this.value;\"/>"
     +option
     +"</label><br/>";
  }
  h += "</div></div>";
  j = "if(geid_val('screen_size_old')==geid_val('screen_size_new')){"
     +"hidePopWin(null);return false;}"
     +"popup_wait('Please wait...<br/>Saving preferences');"
     +"setScreenSize(geid_val('screen_size_new'));geid('form').submit();";
  popup_dialog("Screen size",h,200,260,'OK','Cancel',j);
}

function show_popup_please_wait(msg,h,w) {
  if (typeof msg=='undefined') { msg = "Loading...<br />Please wait"; }
  if (typeof h=='undefined')   { h = 120 }
  if (typeof w=='undefined')   { w = 180 }
  var html =
    "<div style='padding:4px'>" +
    "<img class='fl' src='"+base_url+"img/sysimg/icon_hourglass.gif' width='32' height='32' alt='Please wait...'>" +
    msg +
    "<br class='clr_b' /></div>";
  showPopWin("",html,h,w,null);
}


function selector_csv_add(div,value,hasWeight){
  var selector = geid('selector_csv_'+div);
  var out_txt =  new Array();
  var out_val =  new Array();

  var val_arr = geid_val(div).split(',');
  var included = false
  for (var i=0; i<val_arr.length; i++){
    if (Trim(val_arr[i])==value){
      included = true;
    }
  }
  if (!included) {
    val_arr.push((hasWeight ? value+'[1]' : value));
    geid(div).value=val_arr.join(', ');
    selector_csv_delete(div,'',hasWeight); // Clear null value if present
  }
  selector_csv_show(div,hasWeight);
  selector.selectedIndex=0;
}

function selector_csv_delete(div,setting,hasWeight){
  var selector = geid('selector_csv_'+div);
  var out_txt =  new Array();
  var out_val =  new Array();

  var input_arr = geid_val(div).split(',');
  for (var i=0; i<input_arr.length; i++){
    if (Trim(input_arr[i].split('[')[0]) != setting.split('[')[0]){
      for (var j=0; j<selector.options.length; j++){

        list_item = Trim(input_arr[i]).toUpperCase();
        list_item_arr = list_item.split('[');
        list_item_param = list_item_arr[0];
        list_item_value = (typeof(list_item_arr[1])!='undefined' ? list_item_arr[1].split(']')[0] : "");
        ctrl_item_param = selector.options[j].value.toUpperCase();

        if (list_item_param==ctrl_item_param){
          out_val[out_val.length] = selector.options[j].value+(list_item_value=="" ? "" : "["+list_item_value+"]");
        }
      }
    }
  }
  geid(div).value=out_val.join(', ');
  selector_csv_show(div,hasWeight)
}
function selector_csv_edit(div,setting,hasWeight){
  if (hasWeight!=1){
    selector_csv_delete(div,setting,hasWeight);
    return;
  }
  var setting_arr = setting.split('[');
  var param =  setting_arr[0];
  var value =  (typeof(setting_arr[1])!='undefined' ? setting_arr[1].split(']')[0] : "");


  var h =
    "<div style='padding:4px;'><p>Please give a weighting for <b>"+param+"</b><br />"
   +"<input type='text' class='formField' style='width:25px' id='selector_csv_edit_val' value='"+value+"' /></p>"
   +"<p>Or <a href=\"javascript:selector_csv_delete('"+div+"','"+param+"',1);hidePopWin(null);\"><b>click here</b></a> "
   +"to remove this entry.</p></div>";

  j = "var new_val = parseFloat(geid_val('selector_csv_edit_val'));if(isNaN(new_val)){new_val=0};"
     +"selector_csv_delete('"+div+"','"+param+"',1);"
        +"selector_csv_add('"+div+"','"+param+"'+(new_val==0 ? '' : '['+new_val+']'),1);"
     +"hidePopWin(null);return false;"

  popup_dialog("Set weighting",h,230,300,'OK','Cancel',j);
}

function selector_csv_show(div,hasWeight){
  var selector = geid('selector_csv_'+div);
  var out_txt =  new Array();
  var out_val =  new Array();
  var bgcolorClass, label, tooltip, value;
  var list_item, ctrl_item;
 
  var input_arr = geid_val(div).replace(/ ,/g,',').split(',');
  for (var i=0; i<input_arr.length; i++){
    for (var j=0; j<selector.options.length; j++){

      list_item = Trim(input_arr[i]).toUpperCase();
      list_item_arr = list_item.split("[");
      list_item_param = list_item_arr[0];
      list_item_value = (typeof(list_item_arr[1])!='undefined' ? list_item_arr[1].split(']')[0] : "");
      ctrl_item_param = selector.options[j].value.toUpperCase();

      if (list_item_param==ctrl_item_param){
        bgcolorClass = selector.options[j].className;
        label =        selector.options[j].text;
        label =        Trim((label.substr(0,2)=='* ' ? label.substr(2) : label).split("(")[0]);
        label =	       label+(list_item_value=="" ? "" : "["+list_item_value+"]");
        tooltip =      (label.substr(0,2)=='* ' ? label.substr(2) : label);
        tooltip =      (tooltip.substr(tooltip.length-1)==')' ? tooltip.substr(0,tooltip.indexOf('(')) : tooltip);
        value =        selector.options[j].value+(list_item_value=="" ? "" : "["+list_item_value+"]");
        out_txt[out_txt.length] =
           "<a class=\""+bgcolorClass+"\" title=\""
          +(value ?
               "Click to"
              +(hasWeight ? " edit or" : "")
              +" remove '<b>"+tooltip+"</b>' from this list\\nor choose more options from the dropdown list"
            : "Choose entries from the dropdown list"
           )
          +"\" href=\"javascript:selector_csv_edit('"+div+"','"+value+"',"+hasWeight+")\">"
          +label+"</a>";
      }
    }
  }
  geid('selector_csv_div_'+div).innerHTML=out_txt.join(', ');
  ToolTips.out();ToolTips.attachBehavior();
}

function status_message_hide(id){
  if (geid(id)){
    window.focus();
    geid(id).style.display = 'none';
    geid(id).innerHTML = '';
  }
}

function status_message_show(id,message,severity,noclose){
  var border, bg, color, div, highlight;
  if (typeof noclose =='undefined') {
    noclose = false;
  }
  div = geid(id);
  if (div==false) {
    return false;
  }
  switch(severity){
    case 0:
      border = '#008000'; bg = '#d0ffd0'; color = '#004000'; highlight = '#80ff80';
    break;
    case 1:
      border = '#808000'; bg = '#FFFFD0'; color = '#404000'; highlight = '#FFFF80';
    break;
    case 2:
      border = '#ff0000'; bg = '#ffd0d0'; color = '#800000'; highlight = '#ff8080';
    break;
  }
  div.className =		'form_status';
  div.style.background = 	bg;
  div.style.borderColor = 	border;
  div.style.color = 		color;
  div.style.display =		'none';
  div.style.lineHeight =	'2em';
  div.innerHTML =
    "<div class='fl'>"+message+"</div>\n" +
    (noclose ?
      ""
    :
      "  <input type='button' value='OK' class='formButton fr' style='width:50px;'" +
      " onclick=\"window.focus();this.parentNode.style.display='none';return false\" />"
    ) +
    "  <div class='clr_b'></div>";
  div.style.display='';
  new Effect.Highlight(id, {startcolor:highlight,duration: 3});
  return true;
}


// ************************************
// * Text Resizer functions           *
// ************************************
function cssAttributeGet(selectorText,attribute) {
  var styleSheet, rules, i, ii;
  selectorText=selectorText.toLowerCase();
  if (!document.styleSheets) {
    return false;
  }
  for (i=0; i<document.styleSheets.length; i++) {
    styleSheet=document.styleSheets[i];
    rules = (styleSheet.cssRules ? styleSheet.cssRules : styleSheet.rules);
    for (ii=0; ii<rules.length; ii++) {
      if (
        rules[ii] && rules[ii].selectorText &&
        rules[ii].selectorText.toLowerCase()==selectorText &&
        rules[ii].style[attribute]
      ){
        return (rules[ii].style[attribute]);
      }
    }
  }
  return false;
}
function cssAttributeSet(selectorText,attribute,value) {
  var styleSheet, rules, i, ii;
  selectorText=selectorText.toLowerCase();
  if (!document.styleSheets) {
    return false;
  }
  for (i=0; i<document.styleSheets.length; i++) {
    styleSheet=document.styleSheets[i];
    rules = (styleSheet.cssRules ? styleSheet.cssRules : styleSheet.rules);
    for (ii=0; ii<rules.length; ii++) {
      if (
        rules[ii] && rules[ii].selectorText &&
        rules[ii].selectorText.toLowerCase()==selectorText
      ){
        rules[ii].style[attribute]=value;
        return true;
      }
    }
  }
  return false;
}

function setTextSize(size){
  var expdate = new Date();
  expdate.setTime(expdate.getTime() + (1000*3600*24*365));
  document.cookie = 'textsize=' + size + '; expires=' + expdate.toGMTString();
  var font_scale = (cur_size=='80%' ? '120' : '80');
  if (!cssAttributeSet('.zoom_text','fontSize',font_scale+'%')){
    self.location.reload();
  }
}
function setScreenSize(size){
  var expdate = new Date();
  expdate.setTime(expdate.getTime() + (1000*3600*24*365));
  document.cookie = 'screensize=' + size + '; expires=' + expdate.toGMTString();
}

function toggleTextSize() {
  var cur_size = cssAttributeGet('.zoom_text','fontSize');
  var expdate = new Date();
  expdate.setTime(expdate.getTime() + (1000*3600*24*365));
  document.cookie = 'textsize=' + (cur_size=='80%' ? 'big' : 'small') + '; expires=' + expdate.toGMTString();
  setDisplay('text_sizer_reduce',cur_size=='80%');
  setDisplay('text_sizer_enlarge',cur_size=='120%');

  cssAttributeSet('.zoom_help','fontSize',(cur_size=='80%' ? '10pt' : '7pt'));
  var font_scale = (cur_size=='80%' ? '120' : '80');
  if (!cssAttributeSet('.zoom_text','fontSize',font_scale+'%')){
    self.location.reload();
  }
}


function toggle_attachment_delete_flag(field){
  var state = geid(field+'_mark_delete').checked;
  geid('div_'+field+'_mark_delete_0').style.display = (state==true ? 'none' : '');
  geid('div_'+field+'_mark_delete_1').style.display = (state==true ? '' : 'none');
}


// ************************************
// * Static Tooltips                  *
// ************************************
/**
 * General Horde UI effects javascript.
 * $Horde: horde/js/horde.js,v 1.14.2.5 2006/05/25 18:07:26 slusarz Exp $
 * Changes by Martin Francis in 1.0.36 (2007-07-24) to initialise variables with var keyword
 * See http://www.fsf.org/copyleft/lgpl.html for LGPL licencing
 */

var ToolTips = {
  CURRENT: null,
  TIMEOUT: null,
  LINK: null,
  attachBehavior: null,
  over: null,
  out: null,
  show: null
}

function initialise_tooltips() {
  ToolTips.attachBehavior = function(){
    links = document.getElementsByTagName('a');
    for (i = 0; i < links.length; i++) {
      if (links[i].title) {
        links[i].setAttribute('nicetitle', links[i].title);
        links[i].removeAttribute('title');
        addEvent(links[i], 'mouseover', ToolTips.over);
        addEvent(links[i], 'mouseout', ToolTips.out);
        addEvent(links[i], 'focus', ToolTips.over);
        addEvent(links[i], 'blur', ToolTips.out);
      }
    }
  }
  ToolTips.over = function(e){
    if (typeof ToolTips == 'undefined') {
      return;
    }
    if (ToolTips.TIMEOUT) {
      window.clearTimeout(ToolTips.TIMEOUT);
    }
    if (window.event && window.event.srcElement) {
      ToolTips.LINK = window.event.srcElement;
    } else if (e && e.target) {
      ToolTips.LINK = e.target;
    }
    ToolTips.TIMEOUT = window.setTimeout('ToolTips.show()', 300)
  }
  ToolTips.out = function() {
    if (typeof ToolTips == 'undefined') {
      return;
    }
    if (ToolTips.TIMEOUT) {
      window.clearTimeout(ToolTips.TIMEOUT);
    }
    if (ToolTips.CURRENT) {
      document.getElementsByTagName('body')[0].removeChild(ToolTips.CURRENT);
      ToolTips.CURRENT = null;
      var iframe = geid('iframe_tt');
      if (iframe != null) {
        iframe.style.display = 'none';
      }
    }
  }
  ToolTips.show = function() {
    var link, nicetitle, d, i, STD_WIDTH, MAX_WIDTH, nicetitle_length, lines, w, mpos;
    var h_pixels, t_pixels, mpos, mx, my, left;
    if (typeof ToolTips == 'undefined' || !ToolTips.LINK) {
      return;
    }
    if (ToolTips.CURRENT) {
      ToolTips.out();
    }
    link = ToolTips.LINK;
    while (!link.getAttribute('nicetitle') && link.nodeName.toLowerCase() != 'body') {
      link = link.parentNode;
    }
    nicetitle = link.getAttribute('nicetitle');
    if (!nicetitle) {
      return;
    }
    nicetitle = nicetitle.replace(/ /g,"&nbsp;").replace(/\[b\]/g,"<b>").replace(/\[\/b\]/g,"</b>").replace(/\\n/g,"<br />");
    d = document.createElement('div');
    d.className = 'nicetitle';
    d.innerHTML = nicetitle;
    STD_WIDTH = 100;
    MAX_WIDTH = 600;
    if (window.innerWidth) {
      MAX_WIDTH = Math.min(MAX_WIDTH, window.innerWidth - 20);
    }
    if (document.body && document.body.scrollWidth) {
      MAX_WIDTH = Math.min(MAX_WIDTH, document.body.scrollWidth - 20);
    }
    nicetitle_length = 0;
    
    lines = nicetitle.replace(/<br ?\/>/g, "\n").split("\n");
    for (i = 0; i < lines.length; i++) {
      nicetitle_length = Math.max(nicetitle_length, lines[i].length);
    }
    h_pixels = nicetitle_length * 6.5;
    t_pixels = nicetitle_length * 6.5;
    if (h_pixels > STD_WIDTH) {
      w = h_pixels;
    } else if (STD_WIDTH > t_pixels) {
      w = t_pixels;
    } else {
      w = STD_WIDTH;
    }

    mpos = obj_getCoords(link);
    mx = mpos['left'];
    my = mpos['top'];

    left = mx + 20;
    if (window.innerWidth && ((left + w) > window.innerWidth)) {
      left = window.innerWidth - w - 40;
    }
    if (document.body && document.body.scrollWidth && ((left + w) > document.body.scrollWidth)) {
      left = document.body.scrollWidth - w - 25;
    }
    d.id = 'toolTip';
    d.style.left = Math.max(left, 5) + 'px';
    d.style.width = Math.min(w, MAX_WIDTH) + 'px';
    d.style.top = (my + 25) + 'px';
    d.style.display = "block";
    try {
      document.getElementsByTagName('body')[0].appendChild(d);
      ToolTips.CURRENT = d;

      if (typeof ToolTips_Option_Windowed_Controls != 'undefined') {
        var iframe = geid('iframe_tt');
        if (iframe == null) {
          iframe = document.createElement(
            "<iframe src='javascript:false;' name='iframe_tt' id='iframe_tt' scrolling='no' frameborder='0' style='position:absolute; top:0px; left:0px; display:none;'></iframe>"
          );
          document.getElementsByTagName('body')[0].appendChild(iframe);
        }
        iframe.style.width = d.offsetWidth;
        iframe.style.height = d.offsetHeight;
        iframe.style.top = d.style.top;
        iframe.style.left = d.style.left;
        iframe.style.position = "absolute";
        iframe.style.display = "block";
        d.style.zIndex = 300;
        iframe.style.zIndex = 299;
      }
    }
    catch (e) {
    }
  }
};

var EventCache = function(){
  var listEvents = [];
  return {
    listEvents: listEvents,
    add: function(node, sEventName, fHandler, bCapture) {
      listEvents.push(arguments);
    },
    flush: function() {
      var i, item;
      for (i = listEvents.length - 1; i >= 0; i = i - 1) {
        item = listEvents[i];
        if (item[0].removeEventListener) {
          item[0].removeEventListener(item[1], item[2], item[3]);
        };
        /* From this point on we need the event names to be
         * prefixed with 'on'. */
        if (item[1].substring(0, 2) != 'on') {
          item[1] = 'on' + item[1];
        }
        if (item[0].detachEvent) {
          item[0].detachEvent(item[1], item[2]);
        }
        item[0][item[1]] = null;
      }
    }
  };
}();

/**
 * end of General Horde UI effects javascript.
 * See http://www.fsf.org/copyleft/lgpl.html for LGPL licencing
 */

// ************************************
// * Navsuite code                    *
// ************************************
// Fired on navbar button mouseover
function img_state(img,state) {
  var obj =	geid('btn_'+img);
  var h =	obj.height;
  var pos_arr =	obj.style.backgroundPosition.split(' ');
  var new_pos = ""
  switch (state) {
    case 'a':
      new_pos = 0;
    break;
    case 'd':
      new_pos = -1*h;
    break;
    case 'n':
      new_pos = -2*h;
    break;
    case 'o':
      new_pos = -3*h;
    break;
  }
  obj.style.backgroundPosition = pos_arr[0]+' '+new_pos+'px'
  return true;
}

function img_state_v(img,state) {
  var obj =	geid(img);
  var h =	obj.width;
  var pos_arr =	obj.style.backgroundPosition.split(' ');
  var new_pos = ""
  switch (state) {
    case 'a':
      new_pos = 0;
    break;
    case 'd':
      new_pos = -100;
    break;
    case 'n':
      new_pos = -200;
    break;
    case 'o':
      new_pos = -300;
    break;
  }
  obj.style.backgroundPosition = new_pos+'% '+pos_arr[1];
  return true;
}

function add_btn(ID,parentID) {
  var obj = geid("nav_link_"+ID);
  if (obj) {  // invisible buttons may still be cached - don't try to link to them
    addEvent(obj, 'mousedown', function(e){ return img_state(ID,'d');});
    if (parentID==1) {
      addEvent(obj, 'mouseover', function(e){return img_state(ID,'o');});
      addEvent(obj, 'mouseout',  function(e){_CM_type='';return img_state(ID,(global_active_btns.toString().indexOf(ID)!==-1 ? 'a' :'n'));});
    }
    else {
      addEvent(obj, 'mouseover', function(e){return img_state(ID,'o');});
      addEvent(obj, 'mouseout',  function(e){_CM_type='';return img_state(ID,(global_active_btns.toString().indexOf(ID)!==-1 ? 'a' :'n'));});
    }
  }
}

// Called for IE only to initialise events for mouseover list items
function dropdownMenu(theMenu) {
  if (document.all && document.getElementById) {
    navRoot = geid(theMenu);
    if (!navRoot) {
      return;
    }
    for (var i=0; i<navRoot.childNodes.length; i++) {
      node = navRoot.childNodes[i];
      if (node.nodeName=='LI') {
        node.onmouseover=function() {
          this.className+=' over';
          this.style.zIndex=2;
        }
        node.onmouseout=function() {
          this.className=this.className.replace(' over', '');
          this.style.zIndex=1;
        }

        for (var j=0; j<node.childNodes.length; j++) {
          subnode = node.childNodes[j];
          if (subnode.nodeName=='UL') {
            subnode.onmouseover=function() {
              this.parentNode.style.zIndex=2;
              this.style.zIndex=2;
            }
            subnode.onmouseout=function() {
              this.parentNode.style.zIndex=1;
              this.style.zIndex=1;
            }

            for (var k=0; k<subnode.childNodes.length; k++) {
              subsubnode = subnode.childNodes[k];
              if (subsubnode.nodeName=='LI') {
                subsubnode.onmouseover=function() {
                  this.className+=' over';
                  this.parentNode.style.zIndex=2;
                  this.style.zIndex=2;
                }
                subsubnode.onmouseout=function() {
                  this.className=this.className.replace(' over', '');
                  this.parentNode.style.zIndex=1;
                  this.style.zIndex=1;
                }
              }
            }

          }
        }
      }
    }
  }
}

// ************************************
// * SDMenu Functions                 *
// ************************************
function SDMenu(id) {
  if (!document.getElementById || !document.getElementsByTagName)
    return false;
  this.menu = document.getElementById(id);
  this.submenus = this.menu.getElementsByTagName("div");
  this.remember = false;
  this.speed = 3;
  this.markCurrent = true;
  this.oneSmOnly = false;
  return true;
}
SDMenu.prototype.init = function() {
  var mainInstance = this;
  for (var i = 0; i < this.submenus.length; i++)
    this.submenus[i].getElementsByTagName("span")[0].onclick = function() {
      mainInstance.toggleMenu(this.parentNode);
    };
  if (this.markCurrent) {
    var location = window.location.protocol + "//" + window.location.host + "/" + geid_val('goto');
    var links = this.menu.getElementsByTagName("a");
    for (var i = 0; i < links.length; i++) {
      if (location == links[i].href) {
        links[i].className = "current";
        break;
      }
      if (location == links[i].href+'home') {
        links[i].className = "current";
        break;
      }
    }
    var sd_current, sd_links;
    for (var i=0; i < this.submenus.length; i++) {
      sdmenu_current = false;
      sdmenu_links = this.submenus[i].getElementsByTagName('a');
      for (var j = 0; j < sdmenu_links.length; j++){
        if (location == sdmenu_links[j].href) {
          sdmenu_current = true;
        }
        if (location == sdmenu_links[j].href+'home') {
          sdmenu_current = true;
        }
      }
      if (sdmenu_current) {
        this.expandMenu(this.submenus[i]);
      }
      else {
        this.collapseMenu(this.submenus[i]);
      }
    }
  }
  if (this.remember) {
    var regex = new RegExp("sdmenu_" + encodeURIComponent(this.menu.id) + "=([01]+)");
    var match = regex.exec(document.cookie);
    if (match) {
      var states = match[1].split("");
      for (var i = 0; i < states.length; i++)
        this.submenus[i].className = (states[i] == 0 ? "collapsed" : "");
    }
  }
};
SDMenu.prototype.toggleMenu = function(submenu) {
  if (submenu.className == "collapsed")
    this.expandMenu(submenu);
  else
    this.collapseMenu(submenu);
};
SDMenu.prototype.expandMenu = function(submenu) {
  var fullHeight = submenu.getElementsByTagName("span")[0].offsetHeight;
  var links = submenu.getElementsByTagName("a");
  for (var i = 0; i < links.length; i++)
    fullHeight += links[i].offsetHeight;
  var moveBy = Math.round(this.speed * links.length);
  
  var mainInstance = this;
  var intId = setInterval(function() {
    var curHeight = submenu.offsetHeight;
    var newHeight = curHeight + moveBy;
    if (newHeight < fullHeight)
      submenu.style.height = newHeight + "px";
    else {
      clearInterval(intId);
      submenu.style.height = "";
      submenu.className = "";
      mainInstance.memorize();
    }
  }, 30);
  this.collapseOthers(submenu);
};
SDMenu.prototype.collapseMenu = function(submenu) {
  var minHeight = submenu.getElementsByTagName("span")[0].offsetHeight;
  var moveBy = Math.round(this.speed * submenu.getElementsByTagName("a").length);
  var mainInstance = this;
  var intId = setInterval(function() {
    var curHeight = submenu.offsetHeight;
    var newHeight = curHeight - moveBy;
    if (newHeight > minHeight)
      submenu.style.height = newHeight + "px";
    else {
      clearInterval(intId);
      submenu.style.height = "";
      submenu.className = "collapsed";
      mainInstance.memorize();
    }
  }, 30);
};
SDMenu.prototype.collapseOthers = function(submenu) {
  if (this.oneSmOnly) {
    for (var i = 0; i < this.submenus.length; i++)
      if (this.submenus[i] != submenu && this.submenus[i].className != "collapsed")
        this.collapseMenu(this.submenus[i]);
  }
};
SDMenu.prototype.expandAll = function() {
  var oldOneSmOnly = this.oneSmOnly;
  this.oneSmOnly = false;
  for (var i = 0; i < this.submenus.length; i++)
    if (this.submenus[i].className == "collapsed")
      this.expandMenu(this.submenus[i]);
  this.oneSmOnly = oldOneSmOnly;
};
SDMenu.prototype.collapseAll = function() {
  for (var i = 0; i < this.submenus.length; i++)
    if (this.submenus[i].className != "collapsed")
      this.collapseMenu(this.submenus[i]);
};
SDMenu.prototype.memorize = function() {
  if (this.remember) {
    var states = new Array();
    for (var i = 0; i < this.submenus.length; i++)
      states.push(this.submenus[i].className == "collapsed" ? 0 : 1);
    var d = new Date();
    d.setTime(d.getTime() + (30 * 24 * 60 * 60 * 1000));
    document.cookie = "sdmenu_" + encodeURIComponent(this.menu.id) + "=" + states.join("") + "; expires=" + d.toGMTString() + "; path=/";
  }
};
SDMenu.prototype.expandByPage = function(page) {
  var location = window.location.protocol + '//' + window.location.host + '/' +page;
  for (var i=0; i < this.submenus.length; i++) {
    sdmenu_current = false;
    sdmenu_links = this.submenus[i].getElementsByTagName('a');
    for (var j = 0; j < sdmenu_links.length; j++){
      if (location == sdmenu_links[j].href) {
        sdmenu_current = true;
      }
    }
    if (sdmenu_current) {
      this.expandMenu(this.submenus[i]);
    }
    else {
      this.collapseMenu(this.submenus[i]);
    }
  }
}


function ajax_config_display(result, div) {
  var assoc = [];
  var out = [];
  var checksum_final = '';

  for(var i=1; i<=result[0]; i++) {
    if (result[i]['category']=='config') {
      assoc[result[i]['title']] = result[i]['content'];
    }
    if (result[i]['category']=='checksum' && result[i]['title']=='checksum_final') {
      checksum_final = result[i]['content'];
    }
  }
  assoc['URL'] = "<a href=\"javascript:void popWin('"+assoc['URL']+"','"+assoc['URL'].replace(/[.\/\:]+/g,'_')+"','scrollbars=1,resizable=1,status=0',800,600,'centre');\"><b>"+assoc['URL']+"</b></a>";

  if (result[0]>2) {
    assoc['db_cstarget'] =
      (assoc['db_cstarget']==checksum_final ?
        "<span style='color:#008000'><b>" + checksum_final + "</b></span>"
      :
        "<span style='color:#FF0000'><b>" + checksum_final + "</b></span> (expected " + assoc['db_cstarget'] + ")"
      );
  
    assoc['libraries_csstatus'] =
      (assoc['libraries_csstatus']=='Pass' ?
        "<span style='color:#008000'><b>" + assoc['libraries_csstatus'] + "</b></span>"
      :
        "<span style='color:#FF0000'><b>" + assoc['libraries_csstatus'] + "</b></span>"
      );

    assoc['classes_checksum_status'] =
      (assoc['classes_checksum_status']=='Pass' ?
        "<span style='color:#008000'><b>" + assoc['classes_checksum_status'] + "</b></span>"
      :
        "<span style='color:#FF0000'><b>" + assoc['classes_checksum_status'] + "</b></span>"
      );

    assoc['checksum_status'] =
      (assoc['checksum_status']=='Pass' ?
        "<span style='color:#008000'><b>" + assoc['checksum_status'] + "</b></span>"
      :
        "<span style='color:#FF0000'><b>" + assoc['checksum_status'] + "</b></span>"
      );
  
    assoc['akismet_key_status'] = 
      (assoc['akismet_key_status']=='Valid' ?
        "<span style='color:#008000'><b>" +  assoc['akismet_key_status'] + "</b></span>"
      :
        "<span style='color:#FF0000'><b>" + assoc['akismet_key_status'] + "</b></span>"
      );
  
    assoc['google_key_status'] = 
      (assoc['google_key_status']=='Pass' ?
        "<span style='color:#008000'><b>" +  assoc['google_key_status'] + "</b></span>"
      :
        "<span style='color:#FF0000'><b>" + assoc['google_key_status'] + "</b></span>"
      );
  
    assoc['build_version'] = "<a href=\"javascript:void version('"+assoc['build_version']+"')\"><b>"+assoc['build_version']+"</b></a>";
  
  }
  out.push("<table cellpadding='2' cellspacing='0' class='report'>");
  for (i=0; i < config_rows.length; i++) {
    out.push("<tr>");
    out.push((config_rows[i]=='URL' ? "<td style='background-color: #e8e8e8;border-left:none'>" : "<td style='border-left:none'>"));
    out.push((typeof assoc[config_rows[i]] !='undefined' && assoc[config_rows[i]]!='' ? assoc[config_rows[i]] : '&nbsp;'));
    out.push("</td></tr>");
  }
  out.push("</table>\n");
  geid(div).innerHTML = out.join('');
}

function ajax_div_loading(obj,msg) {
  var c = obj_getCoords(obj);

  var div1 = obj.appendChild(document.createElement("div"));
  var div2 = obj.appendChild(document.createElement("div"));
  var ds1 = div1.style;
  var ds2 = div2.style;

  ds1.backgroundColor = "#aaaaaa";
  ds1.zIndex = 998;
  ds1.opacity = "0.6";
  ds1.filter = "alpha(opacity=60)";
  ds1.top = c['top'];
  ds1.left = c['left'];
  ds1.height = obj.offsetHeight;
  ds1.width = parseFloat(obj.offsetWidth)+20+"px";
  ds1.position = "absolute";

  ds2.backgroundColor = "#f0f0ff";
  ds2.color = "#404060";
  ds2.zIndex = 999;
  ds2.opacity = "0.95";
  ds2.filter = "alpha(opacity=95)";
  ds2.top = parseFloat(c['top'])+10+"px";
  ds2.left = parseFloat(c['left'])+10+"px";
  ds2.lineHeight = "40px";
  ds2.width = obj.offsetWidth;
  ds2.position = "absolute";
  ds2.textAlign = "center";
  ds2.fontSize = "14pt";
  ds2.border = "solid 1px #8080a0";
  div2.innerHTML = msg;
}

function ajax_keytest(e) {
  if(!e) {
    e=window.event;
  }
  keys_arr = new Array(9,37,38,39,40);
  for (var i=0; i<keys_arr.length; i++) {
    if (e.keyCode==keys_arr[i]) {
      return false;
    }
  }
  return true;
}

function ajax_post(xUrl,xId,xParams,xFn) {
  if (ajax_controls[xId]) {
    ajax_controls[xId].abort();
    delete ajax_controls[xId];
  }
  var xmlhttp = false;

  /*@cc_on @*/
  /*@if (@_jscript_version >= 5)
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  }
  catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
      xmlhttp = false;
    }
  }
  @end @*/
  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
    xmlhttp = new XMLHttpRequest();
  }
  xmlhttp.open("POST",xUrl,true);
  xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4) {
      delete ajax_controls[xId];
      if (geid(xId)) {
        geid(xId).innerHTML = xmlhttp.responseText;
      }
      if (typeof xFn=='function') {
        xFn(xmlhttp.responseText);
      }
    }
  }
  ajax_controls[xId]=xmlhttp;
  xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xmlhttp.setRequestHeader("Content-length", xParams.length);
  xmlhttp.setRequestHeader("Connection", "close");
  xmlhttp.send(xParams)
}


function ajax_post_streamed(xUrl,xId,xParams,xFn) {
  if (ajax_controls[xId]) {
    ajax_controls[xId].abort();
    delete ajax_controls[xId];
  }
  var xmlhttp = false;

  /*@cc_on @*/
  /*@if (@_jscript_version >= 5)
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  }
  catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
      xmlhttp = false;
    }
  }
  @end @*/
  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
    xmlhttp = new XMLHttpRequest();
  }
  xmlhttp.open("POST",xUrl,true);
  xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4) {
      delete ajax_controls[xId];
      if (geid(xId)) {
        var json = xmlhttp.responseText.evalJSON();
        geid(xId).innerHTML=json.html;
        eval(json.js);
        if (json.css){ cssAddJsonStyle(eval(json.css)) ;}
      }
      if (typeof xFn=='function') {
        xFn(xmlhttp.responseText);
      }
    }
  }
  ajax_controls[xId]=xmlhttp;
  xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xmlhttp.setRequestHeader("Content-length", xParams.length);
  xmlhttp.setRequestHeader("Connection", "close");
  xmlhttp.send(xParams)
}

function ajax_report(reportID,report_name,toolbar,ajax_popup_url) {
  var pw =
     "<img src='"+base_url+"img/?mode=sysimg&img=progress_indicator.gif' width='16' height='16' alt='Please wait...'>"
    +"&nbsp; <strong>"+system_family+" loading...</strong>";
  ajax_div_loading(geid('report_'+reportID),pw);
  xFn =
    function() {
      externalLinks();
      if (window.CM_load) { CM_load(); }
      ToolTips.out();ToolTips.attachBehavior();
    }

  ajax_post(
    base_url+'?command=report',
    'report_'+encodeURI(reportID),
     'report_name='+encodeURI(report_name)
    +(typeof ajax_popup_url!='undefined' ? '&ajax_popup_url='+encodeURI(ajax_popup_url) : '')
    +'&eventID='+encodeURI(geid_val('eventID'))
    +'&filterField='+encodeURI(geid_val('filterField'))
    +'&filterExact='+encodeURI(geid_val('filterExact'))
    +'&filterValue='+encodeURI(geid_val('filterValue'))
    +'&limit='+encodeURI(geid_val('limit'))
    +'&offset='+encodeURI(geid_val('offset'))
    +'&selectID='+encodeURI(geid_val('selectID'))
    +'&sortBy='+encodeURI(geid_val('sortBy'))
    +'&submode='+encodeURI(geid_val('submode'))
    +'&toolbar='+encodeURI(toolbar)
    +'&targetReportID='+encodeURI(geid_val('targetReportID'))
    +'&DD='+encodeURI(geid_val('DD'))
    +'&MM='+encodeURI(geid_val('MM'))
    +'&YYYY='+encodeURI(geid_val('YYYY')),

     xFn
  );
  externalLinks();
}

function column_over(obj_cell,int_state) {
  switch (int_state) {
    case 'n': obj_cell.className = 'grid_head_n'; break;
    case 'o': obj_cell.className = 'grid_head_o'; break;
    case 'd': obj_cell.className = 'grid_head_d'; break;
  }
  return true;
}


function combo_selector_set(field_name,width){
  var val, obj_field, obj_field_alt, obj_field_sel, field_alt_span;

  obj_field =          geid(field_name);
  obj_field_alt =      geid(field_name+'_alt');
  obj_field_sel =      geid(field_name+'_selector');
  field_alt_span = field_name+'_alt_span';

  val = obj_field_sel.options[obj_field_sel.selectedIndex].value;

  if (val=='--') {
    setDisplay(field_alt_span,1);
    if (width) {
      obj_field_sel.style.width=(parseInt(width)/2)+'px';
    }
    obj_field.value=obj_field_alt.value;
  }
  else {
    setDisplay(field_alt_span,0);
    if (obj_field_sel && obj_field_sel.style && obj_field_sel.style.width && width) {
      obj_field_sel.style.width=(parseInt(width)+4)+'px';
    }
    obj_field.value=val;
    obj_field_alt.value = '';
  }
  if (val=='') {
    obj_field_sel.selectedIndex=0;
  }
  return obj_field.value;
}

function donate(key) {
  geid('command').value='donate';
  geid('form').target='_blank';
  geid('targetValue').value=key;
  geid('form').submit();
  geid('command').value='';
  geid('targetValue').value='';
  geid('form').target='';
}

function get_taxes_applied(BCountryID,BSpID,tax_arr) {
  var invert, place, result, tax, taxes;
  result = {};
  taxes = Object.keys(tax_arr)
  for(var n=0; n < taxes.length; n++){
    tax = taxes[n];
    result[tax] = 0;
    for (var i=0; i<tax_arr[tax][2].length; i++){
      place =  tax_arr[tax][2][i];
      invert = (place.substr(0,1)=='!');
      if (invert){
        place = place.substr(1);
        if (
          place != BCountryID+'.'+BSpID &&
          place != BCountryID+'.*' &&
          place != '*.'+BSpID &&
          place != '*.*'
        ){
          result[tax] = tax_arr[tax][0];
        }
      }
      else if (
        place == BCountryID+'.'+BSpID ||
        place == BCountryID+'.*' ||
        place == '*.'+BSpID ||
        place == '*.*'
      ){
        result[tax] = tax_arr[tax][0];
      }
    }
  }
  return result;
}

function get_valid_name(name) {
  if (isNaN(name.substr(0,1))) {
    return name;
  }
  return valid_prefix+name;
}

function goto_page(what) {
  geid('goto').value=what;
  geid('mode').value='';
  geid('form').submit();
}

function img_over(obj,baseimg,state) {
  var src = "";
  switch (baseimg) {
    case "link":
      src = base_url+'img/?mode=sysimg&img=txt_link_'+(state ? 'o' : 'n')+'.gif';
    break;
    case "map":
      src = base_url+'img/?mode=sysimg&img=txt_map_'+(state ? 'o' : 'n')+'.gif';
    break;
    case "read_more":
      src = base_url+'img/?mode=sysimg&img=txt_read_more_'+(state ? 'o' : 'n')+'.gif';
    break;
    default:
      src = base_url+'img/?mode=sysimg&img='+baseimg+'_'+(state ? 'o' : 'n')+'.gif';
    break;     
  }
  obj.src = src;
  return true;
}

function include(xUrl,xId,xFn) {
  // http://jmaguire.com/downloads/source_code/javascript/client_side_include/
  // Used by Daily Bible Verse
  if (typeof(ajax_controls[xId]) != 'undefined') {
    xmlhttp.abort();
    delete ajax_controls[xId];
  }
  var xmlhttp = false;
  /*@cc_on @*/
  /*@if (@_jscript_version >= 5)
  try {
    xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  }
  catch (e) {
    try {
      xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    } catch (E) {
      xmlhttp = false;
    }
  }
  @end @*/
  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
    xmlhttp = new XMLHttpRequest();
  }
  xmlhttp.open("GET", xUrl,true);
  xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==4) {
      delete ajax_controls[xId];
      if (geid(xId)) {
        geid(xId).innerHTML = xmlhttp.responseText;
      }
      if (xFn) {
        xFn();
      }
    }
  }
  ajax_controls[xId]=xmlhttp;
  xmlhttp.send(null)
}

function makeReadOnly(id) {
  geid(id).style.backgroundColor='#f0f0f0';
  geid(id).style.color='#404040';
  geid(id).attachEvent(
    "onfocus",
    function(){
      geid(id).blur();
    }
  );
}


// ************************************
// * nav_mouse()                      *
// ************************************
// simplifies nav rollovers for trees:
function nav_mouse(div,state,parentDiv){
  switch (state) {
    case "o":
      img_state(div,'o');
      if (parent!=null) {
        img_state(parentDiv,'o');
      }
    break;
    case "n":
      img_state(div,'n');
      if (parent!=null) {
        img_state(parentDiv,'n');
      }
    break;
  }
  return true;
}

function obj_getCoords(obj) {
  var xp, yp, op;
  xp = obj.offsetLeft;	// Element's offset x in pixels
  yp = obj.offsetTop;	// Element's offset y in pixels
  // Now loop through all parent containers, adding offsets as we do so
  while (obj.offsetParent) {
    op = obj.offsetParent;	// Get container parent
    xp = xp + op.offsetLeft;	// Add this element's offset x in pixels
    yp = yp + op.offsetTop;		// Add this element's offset y in pixels
    obj = obj.offsetParent;	// Update current container
  }
  return {'left': xp, 'top': yp};
}

function pad(text,spaces) {
  if (text.length>=spaces) {
    return text;
  }
  var padstr = '                 ';
  return text+padstr.substr(0,spaces-text.length);
}
function lead_zero(text,digits) {
  if (text.length>=digits) {
    return text;
  }
  var leadstr = '0000000000000000';
  return leadstr.substr(0,digits-text.length)+text;
}

// ************************************
// * popWin()                         *
// ************************************
function popWin(url,winName,features,width,height,centre) {
  if (centre == "centre") {
    var availx = screen.availWidth;
    var availy = screen.availHeight;
    var posx = (availx - width)/2;
    var posy = (availy - height)/2;
    var theWin =
      window.open(
        url,
        winName,
        features+',width='+width+',height='+height+',left='+posx+',top='+posy
      );
  }
  else {
    var theWin =
      window.open(
        url,
        winName,
        features+',width='+width+',height='+height+',left=25,top=25'
      );
  }
  theWin.focus();
  return theWin;
}

function popWin_post(url,width,height){
  var targetReportID =	geid_val('targetReportID');
  var targetID =	geid_val('targetID');
  var eventID =		geid_val('eventID');
  var selectID =	geid_val('selectID');
  var filterField =	geid_val('filterField');
  var filterExact =	geid_val('filterExact');
  var filterValue =	geid_val('filterValue');
  var window_name =	('pop_'+url).replace(/[\?\&\= :,\/\-\.]/ig,'');
  var html =
     "<html>\n"
    +"<head>\n"
    +"</head>\n"
    +"<body onload=\"document.getElementById('form').submit();\">\n"
    +"<p>Loading...</p>\n"
    +"<form id='form' action='"+url+"' method='post'>\n"
    +"<input type='hidden' name='targetReportID' id='targetReportID' value='"+targetReportID+"' />\n"
    +"<input type='hidden' name='targetID' id='targetID' value='"+targetID+"' />\n"
    +"<input type='hidden' name='eventID' id='eventID' value='"+eventID+"' />\n"
    +"<input type='hidden' name='selectID' id='selectID' value='"+selectID+"' />\n"
    +"<input type='hidden' name='filterField' id='filterField' value='"+filterField+"' />\n"
    +"<input type='hidden' name='filterExact' id='filterExact' value='"+filterExact+"' />\n"
    +"<input type='hidden' name='filterValue' id='filterValue' value='"+filterValue+"' />\n"
    +"</form>\n"
    +"</body>\n"
    +"</html>";
  var window_hd = popWin('',window_name,'scrollbars=1,resizable=1',width,height,'centre');
  window_hd.focus();
  window_hd.document.write(html);
  window_hd.document.close();
}

function popup_calendar_large(URL){
  popWin(
    URL+"?YYYY="+geid_val('YYYY')+"&MM="+geid_val("MM")+"&DD="+geid_val('DD'),
    'calendar_large','location=1,status=1,scrollbars=1,menubar=1,resizable=1',800,600,1
  );
}

function print_form(report_name,ID) {
  popWin(
    base_url+'print_form/'+report_name+'/'+ID, report_name+'_'+ID,'status=1, scrollbars=1,resizable=1',720,400,1
  );
}

function print_form_data() {
  var frm = geid('form'), id;
  var fields = [];
  for (var i=0; i<frm.elements.length; i++) {
    id = frm.elements[i].id;
    switch (id) {
      case "command":
      case "goto":
      case "mode":
      case "submode":
      break;
      default:
        if (typeof(geid(id).name)!='undefined') {
          fields.push(geid(id).name+'='+geid_val(id));
        }
      break;
    }
  }
  popWin(
    base_url
    + "?command=print_form_data"
    + "&"+fields.join('&'),'','status=1, scrollbars=1,resizable=1',600,600,1);
  return false;
}

function popup_map(system,page,ID) {
  popWin(system+'/?page='+page+'&ID='+ID+'&print=1',ID,'status=1, scrollbars=1,resizable=1',600,600,1);
}

function popup_help(page) {
  if (page===undefined) {
    popWin(base_url+'?mode=help','help','status=1, scrollbars=1,resizable=1',720,400,1);
  }
  else {
    popWin(base_url+'?mode=help&page='+page,'help','status=1, scrollbars=1,resizable=1',720,400,1);
  }
}

function popup_email_to_friend(url) {
  popWin(url,'email_to_a_friend','status=1, scrollbars=1,resizable=1',720,540,1);
  return false;
}

function print_friendly() {
  var theURL;
  if (window.location.search!="") {
    theURL = window.location.href+"&print=1";
  }
  else {
    theURL =
      window.location.href.toString().split('#')[0]+"?print=1" +
      (geid('goto') && geid_val('goto')!="" ? "&goto="+geid_val('goto') : "") +
      (geid('filterAggregate') && geid_val('filterAggregate')!="" ? "&filterAggregate="+geid_val('filterAggregate') : "") +
      (geid('filterField') && geid_val('filterField')!="" ? "&filterField="+geid_val('filterField') : "") +
      (geid('filterExact') && geid_val('filterExact')!="" ? "&filterExact="+geid_val('filterExact') : "") +
      (geid('filterValue') && geid_val('filterValue')!="" ? "&filterValue="+geid_val('filterValue') : "") +
      (geid('limit') && geid_val('limit')!="" ? "&limit="+geid_val('limit') : "") +
      (geid('offset') && geid_val('offset')!="" ? "&offset="+geid_val('offset') : "") +
      (geid('search_categories') && geid_val('search_categories')!="" ? "&search_categories="+geid_val('search_categories') : "") +
      (geid('search_keywords') && geid_val('search_keywords')!="" ? "&search_keywords="+geid_val('search_keywords') : "") +
      (geid('search_offset') && geid_val('search_offset')!="" ? "&search_offset="+geid_val('search_offset') : "") +
      (geid('search_type') && geid_val('search_type')!="" ? "&search_type="+geid_val('search_type') : "") +
      (geid('selectID') && geid_val('selectID')!="" ? "&selectID="+geid_val('selectID') : "") +
      (geid('topbar_search') && geid_val('topbar_search')!="" ? "&topbar_search="+geid_val('topbar_search') : "") +
      (geid('sortBy') && geid_val('sortBy')!="" ? "&sortBy="+geid_val('sortBy') : "");
  }
  popWin(theURL,'printFriendly','scrollbars=1,resizable=1,status=1,toolbar=1,menubar=1',600,400,1);
}

function radio_group_get(name) {
  var element_arr = document.getElementsByName(name);
  if(!element_arr) {
    return false;
  }
  for(var i = 0; i < element_arr.length; i++) {
    if(element_arr[i].checked) {
      return element_arr[i].value;
    }
  }
  return false;
}
function radio_group_set(name,val) {
  element_arr = document.getElementsByName(name);
  if(!element_arr) {
    return false;
  }
  for(var i = 0; i < element_arr.length; i++) {
    element_arr[i].checked = false;
    if (element_arr[i].value==val.toString()) {
      element_arr[i].checked = true;
      return true;
    }
  }
  return false;
}

function radio_groups_group_set(val,options_csv) {
  var options_arr = options_csv.split(',');
  for (var i=0; i<options_arr.length; i++) {
    if (geid('form')[options_arr[i]]) {
      if (val==options_arr[i]) {
        geid('form')[options_arr[i]][0].checked=0;
        geid('form')[options_arr[i]][1].checked=1;
      }
      else {
        geid('form')[options_arr[i]][0].checked=1;
        geid('form')[options_arr[i]][1].checked=0;
      }
    }
  }
}


function register_copy_my_details(form) {
  with (form) {
    NFirst.value=my_NFirst.value;
    NMiddle.value=my_NMiddle.value;
    NLast.value=my_NLast.value;
    PEmail.value=my_PEmail.value;
    ATelephone.value=my_ATelephone.value;
  }
}

function register_required(form) {
  if (form.NFirst.value=='' && form.NLast.value==''){
    alert('You must enter a name');
    return false;
  }
  if (form.PEmail.value=='') {
    alert('You must enter a contact email address');
    return false;
  }
  return true;
}


// ************************************
// * Report Filter Operations         *
// ************************************
function report_filter_set(reportID,filter) {
//  alert(filter.settings.ID);
  geid_set('filterField',filter.settings.criterion);
  geid_set('filterExact',filter.settings.matchmode);
  geid_set('filterValue',filter.settings.value);
  geid_set('filterAggregate',filter.settings.aggregate);

  var ff = geid('filterField_'+reportID);
  var fe = geid('filterExact_'+reportID);
  var fv = geid('filterValue_'+reportID);


  for (var i=0; i<ff.options.length; i++) {
    if (ff.options[i].value==filter.settings.criterion+'|'+filter.settings.aggregate) {
      ff.selectedIndex = i;
    }
  }
  for (var i=0; i<fe.options.length; i++) {
    if (fe.options[i].value==filter.settings.matchmode) {
      fe.selectedIndex = i;
    }
  }
  fv.value=filter.settings.value;
}
function filterbar_disable_controls(reportID) {
  if (geid('btn_go_'+reportID))    { geid('btn_go_'+reportID).disabled=true };
  if (geid('btn_clear_'+reportID)) { geid('btn_clear_'+reportID).disabled=true; }
  if (geid('btn_save_'+reportID))  { geid('btn_save_'+reportID).disabled=true; }
}
function filterbar_filterField_onchange(reportID) {
  if(geid_val('filterField_'+reportID)==''){
    geid('filterExact_'+reportID).selectedIndex=0;
    geid_set('filterExact','');
  };
  if(geid_val('filterField_'+reportID)!='' && geid_val('filterExact_'+reportID)==''){
    geid('filterExact_'+reportID).selectedIndex=1;
    geid_set('filterExact','0');
  }
  var ff_arr = geid_val('filterField_'+reportID).split('|');
  geid_set('filterField',ff_arr[0]);
  geid_set('filterAggregate',ff_arr[1]);
  return false;
}
function filterbar_filterExact_onchange(reportID) {
  geid_set('filterExact',geid_val('filterExact_'+reportID));
  if(geid_val('filterExact_'+reportID)==''){
    geid('filterField_'+reportID).selectedIndex=0;
  }
}

function filterbar_value_onblur(e,reportID,filterValueDefault){
  field = geid('filterValue_'+reportID);
  if (field.value==''){
    field.value=filterValueDefault;
    field.style.color='#0000ff';
  }
}
function filterbar_value_onclick(e,reportID,filterValueDefault){
  field = geid('filterValue_'+reportID);
  if (field.value==filterValueDefault){
    field.value='';
    field.style.color='#000000';
  }
}
function filterbar_value_onkeypress(e,reportID){
  var keynum = (window.event ? e.keyCode : e.which);
  if(keynum == 13) {
    geid_set('filterValue',geid_val('filterValue_'+reportID));
    geid('btn_go_'+reportID).focus();
    geid('btn_go_'+reportID).click();
    return false;
  }
  return true; 
}
function filterbar_go_onclick(reportID,report_name,toolbar){
  filterbar_disable_controls(reportID);
  geid_set('filterValue',geid_val('filterValue_'+reportID));
  if (report_name) {
    ajax_report(reportID,report_name,toolbar);
  }
  else {
    geid('form').submit();
  }
}
function filterbar_clear_onclick(reportID,report_name,toolbar){
  filterbar_disable_controls(reportID);
  geid_set('limit',10);
  geid_set('offset',0);
  geid_set('filterAggregate','');
  geid_set('filterExact','');
  geid_set('filterField','');
  geid_set('filterValue','');
  geid_set('filterExact_'+reportID,'');
  geid_set('filterValue_'+reportID,'');
  geid('filterField_'+reportID,'');
  if (geid('limit_'+reportID) && geid('limit_'+reportID).selectedIndex) { geid('limit_'+reportID).selectedIndex=0; }
  if (geid('offset_'+reportID) && geid('offset_'+reportID).selectedIndex) { geid('offset_'+reportID).selectedIndex=0;}
  if (report_name) {
    ajax_report(reportID,report_name,toolbar);
  }
  else {
    geid('form').submit();
  }
}
function filterbar_save_onclick(reportID,report_name,toolbar){
  var h, j;
  h = "<div style='padding:4px;'>Enter name for new Preset Filter"
     +"<div style='padding-top:10px;'>"
     +"<table class='minimal' summary='Grid layout for popup form'>\n"
     +"  <tr>\n"
     +"    <td style='width:50px;'>Name</td>\n"
     +"    <td><input type='text' id='filter_name' onkeyup=\"geid('btn_ok').disabled = this.value.length==0\" "
     +"class='formField fl' style='width:100px;' value='' /></td>\n"
     +"  </tr>\n"
     +"</table>\n"
     +"</div></div>";
  j = "if(geid_val('filter_name')==''){return false;}"
     +"filterbar_disable_controls('"+reportID+"');"
     +"geid_set('submode','filter_add');"
     +"geid_set('targetValue',geid_val('filter_name'));"
     +"geid_set('targetReportID','"+reportID+"');"
     +"geid_set('filterValue',geid_val('filterValue_"+reportID+"'));"

//     +"alert(geid('filterField').value);"
     +"geid('form').submit();"
  popup_dialog("Filter Save",h,200,260,'OK','Cancel',j,'filter_name');
  geid('btn_ok').disabled=true;
}


function select_item(ID){
  geid('selectID').value = ID;
  geid('form').submit();
}


function select_YYYY_MM(YYYY,MM,targetReportName) {
  geid('YYYY').value =    YYYY;
  geid('MM').value =      MM;
  geid('anchor').value =  targetReportName;
  geid('form').submit();
}
function setBackground(targDiv,color) {
  if (isW3C) { // DOM3 = IE5, NS6
    var div = geid(targDiv);
    if (div) {
      div.style.background = color;
    }
  }
}
function setBlock(targDiv,show) {
  if (isW3C) { // DOM3 = IE5, NS6
    var div = geid(targDiv);
    if (div) {
      div.style.display = (show ? "block" : "none");
    }
  }
}

function setDisplay(targDiv,show) {
  if (isW3C) { // DOM3 = IE5, NS6
    var div = geid(targDiv);
    if (div) {
      div.style.display = (show ? "" : "none");
    }
  }
}
 
function signup_required(form) {
  if ((form.PUsername && form.PUsername.value=='')) {
    alert('You must enter a requested username');
    return false;
  }
  if ((form.PEmail && form.PEmail.value=='')) {
    alert('You must enter a valid email address');
    return false;
  }
  return true;
}

function show_section(sections_arr,section) {
  var _section, div;
  geid('selected_section').value=section;
  for (var i=0; i<sections_arr.length; i++) {
    _section = sections_arr[i];
    div = geid('section_'+_section+'_heading');
    if (div) {
      setDisplay('section_'+_section,(section==_section));
      div.className = (section==_section ? 'tab_selected' : 'tab');
    }
  }
  return true;
}

function LTrim(str) {
  var whitespace = new String(" \t\n\r");
  var s = new String(str);
  if (whitespace.indexOf(s.charAt(0)) != -1) {
    var j=0, i = s.length;
    while (j < i && whitespace.indexOf(s.charAt(j)) != -1)
      j++;
    s = s.substring(j, i);
  }
  return s;
}

function RTrim(str) {
  var whitespace = new String(" \t\n\r");
  var s = new String(str);
  if (whitespace.indexOf(s.charAt(s.length-1)) != -1) {
    var i = s.length - 1;
    while (i >= 0 && whitespace.indexOf(s.charAt(i)) != -1)
      i--;
    s = s.substring(0, i+1);
  }
  return s;
}
function round(number,X) {
// rounds number to X decimal places, defaults to 2
  X = (!X ? 2 : X);
  return Math.round(number*Math.pow(10,X))/Math.pow(10,X);
}

function search_offset(offset,type){
  geid_set('search_offset',offset);
  geid_set('search_type',type);
  geid('form').submit();
  return false;
}

function search_setup_date_range() {
  geid('_search_date_start').innerHTML = date_selector_draw('_search_date_start',geid_val('search_date_start'));
  geid('_search_date_end').innerHTML =   date_selector_draw('_search_date_end',geid_val('search_date_end'));
}
function search_results_go() {
  if (geid('search_sites_selector')) {
    var sites_arr = 	[];
    var selector = 	geid('search_sites_selector');
    for (var i=0; i<selector.options.length; i++) {
      if (selector.options[i].selected){
        sites_arr.push(selector.options[i].value);
      }
    }
    geid_set('search_sites',sites_arr.join(','));
  }
  var start = geid_val('_search_date_start_yyyy')+"-"+geid_val('_search_date_start_mm')+"-"+geid_val('_search_date_start_dd');
  var end =   geid_val('_search_date_end_yyyy')+"-"+geid_val('_search_date_end_mm')+"-"+geid_val('_search_date_end_dd');

  var start_val = geid_val('_search_date_start_yyyy')*10000 + geid_val('_search_date_start_mm')*100 + geid_val('_search_date_start_dd');
  var end_val =   geid_val('_search_date_end_yyyy')*10000 +   geid_val('_search_date_end_mm')*100   + geid_val('_search_date_end_dd');

  if (start_val>end_val && end_val!=0){
    var tmp = start; start = end; end = tmp;
  }

  geid_set('mode','');
  geid_set('search_offset','0');
  geid_set('search_categories',geid('_search_categories') ? geid_val('_search_categories') : "");

  geid_set('search_date_start',start);
  geid_set('search_date_end',  end);

  geid_set('search_keywords',geid('_search_keywords') ? geid_val('_search_keywords') : "");
  geid_set('search_name',geid('_search_name') ? geid_val('_search_name') : "");
  geid_set('search_text',geid_val('_search_text'));
  geid_set('search_type',geid_val('_search_type'));
  geid('form').submit();
}
function search_go() {
  geid_set('goto','search_results');
  geid_set('mode','');
  geid_set('search_offset','0');
  geid_set('search_type','*');
  geid('form').submit();
}

function topbar_search_go() {
  geid_set('search_text',geid_val('topbar_search'));
  search_go();
}
function Trim(str) {
  return RTrim(LTrim(str));
}
function two_dp(amount){
  var i = parseFloat(amount);
  if(isNaN(i)) { i = 0.00; }
  var minus = '';
  if(i < 0) { minus = '-'; }
  i = Math.abs(i);
  i = parseInt((i + .005) * 100);
  i = i / 100;
  var s = new String(i);
  if(s.indexOf('.') < 0) { s += '.00'; }
  if(s.indexOf('.') == (s.length - 2)) { s += '0'; }
  s = minus + s;
  return s;
}

function textCounter(field, countfield, maxlimit) {
  if (field.value.length > maxlimit) // if too long...trim it!
    field.value = field.value.substring(0, maxlimit);
  else
    countfield.value = maxlimit - field.value.length;
}

function payment_method_change(disable_cc,id_method,id_card_name,id_card_number,id_card_exp_mm,id_card_exp_yy) {
  geid(id_card_name).disabled=disable_cc;
  geid(id_card_number).disabled=disable_cc;
  geid(id_card_exp_mm).disabled=disable_cc;
  geid(id_card_exp_yy).disabled=disable_cc;
  geid(id_card_name).style.backgroundColor=(disable_cc ? '#e0e0e0' : '');
  geid(id_card_number).style.backgroundColor=(disable_cc ? '#e0e0e0' : '');
  geid(id_card_exp_mm).style.backgroundColor=(disable_cc ? '#e0e0e0' : '');
  geid(id_card_exp_yy).style.backgroundColor=(disable_cc ? '#e0e0e0' : '');
}
function validate_payment_details(err_arr,id_method,id_card_name,id_card_number,id_card_ex_mm,id_card_exp_yy) {
  var n = err_arr.length;
	  if (geid(id_method).value==''){
	    err_arr[n++]= pad(''+n+')',4) +"Payment Method is missing";
	  }
  if (geid_val(id_method).indexOf('Pay Pal') == -1) {
	  if (geid(id_card_name).value ==''){
	    err_arr[n++]= pad(''+n+')',4) +"CardHolder Name is missing";
	  }
	  if (geid(id_card_number).value.replace(/[^0-9]+/ig,'')==''){
	    err_arr[n++]=pad(''+n+')',4)+"Credit card number missing";
	  }
	  else {
	    if (geid(id_card_number).value.replace(/[^0-9 ]+/ig,'')!=geid(id_card_number).value){
	      err_arr[n++]=pad(''+n+')',4)+"Credit card number contains invalid characters";
	    }
	    else {
	      if (geid(id_card_number).value.replace(/[^0-9]+/ig,'').length!=16) {
	//        err_arr[n++]= pad(''+n+')',4)+"Credit card number must have 16 digits";
	      }
	    }
	  }
	  if (geid(id_card_ex_mm).value.length==0 || geid(id_card_ex_mm).value.replace(/[^0-9]+/ig,'')!=geid(id_card_ex_mm).value || parseFloat(geid(id_card_ex_mm).value)<1 || parseFloat(geid(id_card_ex_mm).value)>12) {
	    err_arr[n++]= pad(''+n+')',4)+"Expiry Month value must be between 01 and 12";
	  }
	  var this_year=new Date().getUTCFullYear().toString().substr(2,2);
	  if (geid(id_card_exp_yy).value.length==0 || geid(id_card_exp_yy).value.replace(/[^0-9]+/ig,'')!=geid(id_card_exp_yy).value || parseFloat(geid(id_card_exp_yy).value)<parseFloat(this_year) || parseFloat(geid(id_card_exp_yy).value)>(parseFloat(this_year)+10)) {
	    err_arr[n++]= pad(''+n+')',4)+"Expiry Year value outside acceptable range ("+this_year+" to "+(parseFloat(this_year)+10)+")";
	  }
	}
  return err_arr;
}
function version(ver) {
  var name = ver.replace(/\./g,'_');
  popWin('http://www.ecclesiact.com/build?build='+ver,name,'scrollbars=1,resizable=1,status=0',800,600,'centre');
}
function view_event_registrants(eventID,width,height) {
  popWin(
    base_url+'view_event_registrants/?print=1&eventID='+eventID,'eventRegistrants','status=1, scrollbars=1,resizable=1',width,height,1
  );
}

function view_credit_memo(ID,width,height) {
  popWin(
    base_url+'view_credit_memo/?print=2&ID='+ID,'','status=1,scrollbars=1,resizable=1,menubar=1',width,height,1
  );
}

function view_order_details(ID,width,height) {
  popWin(
    base_url+'view_order/?print=2&ID='+ID,'','status=1,scrollbars=1,resizable=1,menubar=1',width,height,1
  );
}
function widget_toggle(ID){
  geid(ID+"_show").style.display=geid(ID).style.display;
  geid(ID).style.display=(geid(ID).style.display=='' ? 'none' : '');
  geid(ID+"_hide").style.display=geid(ID).style.display;
}


/**
 * COMMON DHTML FUNCTIONS (comments by original author)
 *
 * These are handy functions I use all the time.
 * By Seth Banks (webmaster at subimage dot com)
 * http://www.subimage.com/
 * Up to date code can be found at http://www.subimage.com/dhtml/
 * This code is free for you to use anywhere, just keep this comment block.
 */

function addEvent(obj, evType, fn){
  if (obj.addEventListener){
    obj.addEventListener(evType, fn, true);
    return true;
  }
  else if (obj.attachEvent) {
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  }
  else {
    return false;
  }
}
function removeEvent(obj, evType, fn, useCapture){
  if (obj.removeEventListener){
    obj.removeEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.detachEvent){
    var r = obj.detachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be removed");
    return false;
  }
}

/**
 * Code below taken from - http://www.evolt.org/article/document_body_doctype_switching_and_more/17/30655/
 * Modified 4/22/04 to work with Opera/Moz (by webmaster at subimage dot com)
 * Gets the full width/height because it's different for most browsers.
 */
function getViewportHeight() {
  if (window.innerHeight!=window.undefined) return window.innerHeight;
  if (document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;
  if (document.body) return document.body.clientHeight; 
  return window.undefined; 
}
function getViewportWidth() {
  var offset = 17;
  var width = null;
  if (window.innerWidth!=window.undefined) return window.innerWidth; 
  if (document.compatMode=='CSS1Compat') return document.documentElement.clientWidth; 
  if (document.body) return document.body.clientWidth;
  return false; 
}
/**
 * Gets the real scroll top
 */
function getScrollTop() {
  if (self.pageYOffset) {
    // all except Explorer
    return self.pageYOffset;
  }
  else if (document.documentElement && document.documentElement.scrollTop) {
    // Explorer 6 Strict
    return document.documentElement.scrollTop;
  }
  else if (document.body){ // all other Explorers
    return document.body.scrollTop;
  }
  return false; 
}
function getScrollLeft() {
  if (self.pageXOffset){
    // all except Explorer
    return self.pageXOffset;
  }
  else if (document.documentElement && document.documentElement.scrollLeft) {
    // Explorer 6 Strict
    return document.documentElement.scrollLeft;
  }
  else if (document.body) {
    // all other Explorers
    return document.body.scrollLeft;
  }
  return false; 
}

// ************************************
// * Calendar Functions:              *
// ************************************
function cal_picker(field) {
  var DD, MM, YY, YYYYMMDD;
  YYYYMMDD = geid(field).value;
  YYYY = YYYYMMDD.substr(0,4);
  MM = YYYYMMDD.substr(5,2);
  DD = YYYYMMDD.substr(8,2);
  popWin(
    base_url+'?mode=cal_picker&field='+field+
      (YYYY!='' ? '&YYYY='+YYYY : '')+
      (MM!='' ? '&MM='+MM : '')+
      (DD!='' ? '&DD='+DD : ''),
    'popCalPicker','scrollbars=0,resizable=1,status=1',220,215,'centre');
  return false;
}
function cal_set_date(YYYYMMDD,field) {
  window.opener.geid_set(field,YYYYMMDD);
  window.close();
}

/* -----------------------------------------------------------
 * Copyright Mihai Bazon, 2002-2005  |  www.bazon.net/mishoo
 * -----------------------------------------------------------
 *  From http://www.dynarch.com/projects/calendar - LGPL
 *  The DHTML Calendar, version 1.0 "It is happening again"
 *
 *  2008-12-30 (MFrancis)
 *    1) Many changes to better pass JSLint, remove 'with' keywords and properly bracket everything.
 *    2) Added new date proptotype method date.toISO()
 *    3) Incorporated calendar-setup.js and calendar-en.js (yes I know that's not always a good idea)
 *    4) Added ability to set up tooltip handler
 *
 * This script is distributed under the GNU Lesser General Public License.
 * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
 */

// global object that remembers the calendar
window._dynarch_popupCalendar = null;

// $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $
/** The Calendar object constructor. */


function Calendar(firstDayOfWeek, dateStr, onSelected, onClose) {
  // member variables
  this.activeDiv =	null;
  this.currentDateEl =	null;
  this.getDateStatus =	null;
  this.getDateToolTip =	null;
  this.getDateText =	null;
  this.timeout = 	null;
  this.onSelected = 	onSelected || null;
  this.onClose = 	onClose || null;
  this.dragging = 	false;
  this.hidden = 	false;
  this.link = 		false;
  this.minYear = 	1970;
  this.maxYear = 	2050;
  this.dateFormat = 	Calendar._TT.DEF_DATE_FORMAT;
  this.ttDateFormat = 	Calendar._TT.TT_DATE_FORMAT;
  this.isPopup = 	true;
  this.weekNumbers = 	true;
  this.firstDayOfWeek = (typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD); // 0 for Sunday, 1 for Monday, etc.
  this.showsOtherMonths = false;
  this.dateStr = 	dateStr;
  this.ar_days = 	null;
  this.showsTime = 	false;
  this.time24 = 	true;
  this.yearStep = 	1;
  this.hiliteToday = 	true;
  this.multiple = 	null;

  // HTML elements
  this.table = 		null;
  this.element = 	null;
  this.tbody = 		null;
  this.firstdayname = 	null;

  // Combo boxes
  this.monthsCombo = 	null;
  this.yearsCombo = 	null;
  this.hilitedMonth = 	null;
  this.activeMonth = 	null;
  this.hilitedYear = 	null;
  this.activeYear = 	null;

  // Information
  this.dateClicked = 	false;
  // one-time initializations
  if (typeof Calendar._SDN == "undefined") {
    // table of short day names
    if (typeof Calendar._SDN_len == "undefined"){
      Calendar._SDN_len = 3;
    }
    var ar = [];
    for (var i = 8; i > 0;) {
      ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
    }
    Calendar._SDN = ar;
    // table of short month names
    if (typeof Calendar._SMN_len == "undefined"){
      Calendar._SMN_len = 3;
    }
    ar = [];
    for (i = 12; i > 0;) {
      ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
    }
    Calendar._SMN = ar;
  }
}

/**
 *  This function "patches" an input field (or other element) to use a calendar
 *  widget for date selection.
 *
 *  The "params" is a single object that can have the following properties:
 *
 *    prop. name   | description
 *  -------------------------------------------------------------------------------------------------
 *   align         | alignment (default: "Br"); if you don't know what's this see the calendar documentation
 *   button        | ID of a button or other element that will trigger the calendar
 *   cache         | if "true" (but default: "false") it will reuse the same calendar object, where possible
 *   daFormat      | the date format that will be used to display the date in displayArea
 *   date          | the date that the calendar will be initially displayed to
 *   disableFunc   | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
 *   displayArea   | the ID of a DIV or other element to show the date
 *   electric      | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close
 *   eventName     | event that will trigger the calendar, without the "on" prefix (default: "click")
 *   firstDay      | numeric: 0 to 6.  "0" means display Sunday first, "1" means display Monday first, etc.
 *   flat          | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
 *   flatCallback  | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
 *   ifFormat      | date format that will be stored in the input field
 *   inputField    | the ID of an input field to store the date
 *   onClose       | function that gets called when the calendar is closed.  [default]
 *   onSelect      | function that gets called when a date is selected.  You don't _have_ to supply this (the default is generally okay)
 *   onUpdate      | function that gets called after the date is updated in the input field.  Receives a reference to the calendar.
 *   position      | configures the calendar absolute position; default: null
 *   range         | array with 2 elements.  Default: [1900, 2999] -- the range of years available
 *   showOthers    | if "true" (but default: "false") it will show days from other months too
 *   showsTime     | default: false; if true the calendar will include a time selector
 *   singleClick   | (true/false) wether the calendar is in single click mode or not (default: true)
 *   step          | configures the step of the years in drop-down boxes; default: 2
 *   timeFormat    | the time format; can be "12" or "24", default is "12"
 *   weekNumbers   | (true/false) if it's true (default) the calendar will display week numbers
 *
 *  None of them is required, they all have default values.  However, if you
 *  pass none of "inputField", "displayArea" or "button" you'll get a warning
 *  saying "nothing to setup".
 */
Calendar.setup = function (params) {
  function param_default(pname, def) {
    if (typeof params[pname] == "undefined") {
      params[pname] = def;
    }
  }
  param_default("disableFunc",		null); // Put first as others may use it

  param_default("align",		"Br");
  param_default("button",		null);
  param_default("cache",		false);
  param_default("daFormat",		"%Y/%m/%d");
  param_default("date",			null);
  param_default("dateStatusFunc",	params.disableFunc);	// takes precedence if both are defined
  param_default("dateText",		null);
  param_default("dateToolTipFunc",	params.disableFunc);	// Added by Martin
  param_default("displayArea",		null);
  param_default("electric",		true);
  param_default("eventName",		"click");
  param_default("firstDay",		null);
  param_default("flat",			null);
  param_default("flatCallback",		null);
  param_default("ifFormat",		"%Y/%m/%d");
  param_default("link_enlarge",		null); 			// Added by M Francis
  param_default("link_enlarge_popup",	null); 			// Added by M Francis
  param_default("link_help",		null); 			// Added by M Francis
  param_default("inputField",		null);
  param_default("multiple",		null);
  param_default("onClose",		null);
  param_default("onSelect",		null);
  param_default("onUpdate",		null);
  param_default("position",		null);
  param_default("range",		[2005, 2030]);
  param_default("showOthers",		false);
  param_default("showsTime",		false);
  param_default("singleClick",		true);
  param_default("step",			1);
  param_default("timeFormat",		"24");
  param_default("weekNumbers",		true);


  var tmp = ["inputField", "displayArea", "button"];
  for (var i in tmp) {
    if (typeof params[tmp[i]] == "string") {
      params[tmp[i]] = document.getElementById(params[tmp[i]]);
    }
  }
  if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
    alert("Calendar.setup:\n  Nothing to setup (no fields found).  Please check your code");
    return false;
  }

  function onSelect(cal) {
    var p = cal.params;
    var update = (cal.dateClicked || p.electric);
    if (update && p.inputField) {
      p.inputField.value = cal.date.print(p.ifFormat);
      if (typeof p.inputField.onchange == "function") {
        p.inputField.onchange();
      }
    }
    if (update && p.displayArea) {
      p.displayArea.innerHTML = cal.date.print(p.daFormat);
    }
    if (update && typeof p.onUpdate == "function") {
      p.onUpdate(cal);
    }
    if (update && p.flat) {
      if (typeof p.flatCallback == "function") {
        p.flatCallback(cal);
      }
    }
    if (update && p.singleClick && cal.dateClicked) {
      cal.callCloseHandler();
    }
  }


  if (params.flat !== null) {
    if (typeof params.flat == "string") {
      params.flat = document.getElementById(params.flat);
    }
    if (!params.flat) {
      alert("Calendar.setup:\n  Flat specified but can't find parent.");
      return false;
    }
    var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
    cal.showsOtherMonths = params.showOthers;
    cal.showsTime = params.showsTime;
    cal.time24 = (params.timeFormat == "24");
    cal.params = params;
    cal.weekNumbers = params.weekNumbers;
    cal.setRange(params.range[0], params.range[1]);
    cal.setDateStatusHandler(params.dateStatusFunc);
    cal.setDateToolTipHandler(params.dateToolTipFunc);
    cal.setLinkEnlarge(params.link_enlarge);
    cal.setLinkEnlargePopup(params.link_enlarge_popup);
    cal.setLinkHelp(params.link_help);
    cal.getDateText = params.dateText;
    if (params.ifFormat) {
      cal.setDateFormat(params.ifFormat);
    }
    if (params.inputField && typeof params.inputField.value == "string") {
      cal.parseDate(params.inputField.value);
    }
    cal.create(params.flat);
    cal.show();
    return cal;
  }

  var triggerEl = params.button || params.displayArea || params.inputField;
  triggerEl["on" + params.eventName] = function() {
    var dateEl = params.inputField || params.displayArea;
    var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
    var mustCreate = false;
    var cal = window.calendar;
    if (dateEl) {
      params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
    }
    if (!(cal && params.cache)) {
      cal = new Calendar(
        params.firstDay,
        params.date,
        params.onSelect || onSelect,
        params.onClose || function(cal) { cal.hide(); }
      );
      window.calendar = cal;
      cal.showsTime = params.showsTime;
      cal.time24 = (params.timeFormat == "24");
      cal.weekNumbers = params.weekNumbers;
      mustCreate = true;
    }
    else {
      if (params.date) {
        cal.setDate(params.date);
      }
      cal.hide();
    }
    if (params.multiple) {
      cal.multiple = {};
      for (var i = params.multiple.length; --i >= 0;) {
        var d = params.multiple[i];
        var ds = d.print("%Y%m%d");
        cal.multiple[ds] = d;
      }
    }
    cal.showsOtherMonths = params.showOthers;
    cal.yearStep = params.step;
    cal.setRange(params.range[0], params.range[1]);
    cal.params = params;
    cal.setDateStatusHandler(params.dateStatusFunc);
    cal.setDateToolTipHandler(params.dateToolTipFunc);
    cal.getDateText = params.dateText;
    cal.setDateFormat(dateFmt);
    if (mustCreate) {
      cal.create();
    }
    cal.refresh();
    if (!params.position) {
      cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
    }
    else {
      cal.showAt(params.position[0], params.position[1]);
    }
    return false;
  };
  return cal;
};

// ** constants

/// "static", needed for event handlers.
Calendar._C = null;

/// detect a special case of "web browser"
Calendar.is_ie = ( /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) );
Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );
Calendar.is_opera = /opera/i.test(navigator.userAgent);
Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);

Calendar.getAbsolutePos = function(el) {
  var SL = 0, ST = 0;
  var is_div = /^div$/i.test(el.tagName);
  if (is_div && el.scrollLeft){
    SL = el.scrollLeft;
  }
  if (is_div && el.scrollTop){
    ST = el.scrollTop;
  }
  var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
  if (el.offsetParent) {
    var tmp = this.getAbsolutePos(el.offsetParent);
    r.x += tmp.x;
    r.y += tmp.y;
  }
  return r;
};

Calendar.isRelated = function (el, evt) {
  var related = evt.relatedTarget;
  if (!related) {
    var type = evt.type;
    if (type == "mouseover") {
      related = evt.fromElement;
    } else if (type == "mouseout") {
      related = evt.toElement;
    }
  }
  while (related) {
    if (related == el) {
      return true;
    }
    related = related.parentNode;
  }
  return false;
};

Calendar.removeClass = function(el, className) {
  if (!(el && el.className)) {
    return;
  }
  var cls = el.className.split(" ");
  var ar = [];
  for (var i = cls.length; i > 0;) {
    if (cls[--i] != className) {
      ar[ar.length] = cls[i];
    }
  }
  el.className = ar.join(" ");
};

Calendar.addClass = function(el, className) {
  Calendar.removeClass(el, className);
  el.className += " " + className;
};

// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
Calendar.getElement = function(ev) {
  var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
  while (f.nodeType != 1 || /^div$/i.test(f.tagName)){
    f = f.parentNode;
  }
  return f;
};

Calendar.getTargetElement = function(ev) {
  var f = Calendar.is_ie ? window.event.srcElement : ev.target;
  while (f.nodeType != 1){
    f = f.parentNode;
  }
  return f;
};

Calendar.stopEvent = function(ev) {
  if (!ev) { ev = window.event; }
  if (Calendar.is_ie) {
    ev.cancelBubble = true;
    ev.returnValue = false;
  }
  else {
    ev.preventDefault();
    ev.stopPropagation();
  }
  return false;
};

Calendar.addEvent = function(el, evname, func) {
  if (el.attachEvent) { // IE
    el.attachEvent("on" + evname, func);
  }
  else if (el.addEventListener) { // Gecko / W3C
    el.addEventListener(evname, func, true);
  }
  else {
    el["on" + evname] = func;
  }
};

Calendar.removeEvent = function(el, evname, func) {
  if (el.detachEvent) { // IE
    el.detachEvent("on" + evname, func);
  }
  else if (el.removeEventListener) { // Gecko / W3C
    el.removeEventListener(evname, func, true);
  }
  else {
    el["on" + evname] = null;
  }
};

Calendar.createElement = function(type, parent) {
  var el = null;
  if (document.createElementNS) {
    // use the XHTML namespace; IE won't normally get here unless
    // _they_ "fix" the DOM2 implementation.
    el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
  } else {
    el = document.createElement(type);
  }
  if (typeof parent != "undefined") {
    parent.appendChild(el);
  }
  return el;
};

// END: UTILITY FUNCTIONS

// BEGIN: CALENDAR STATIC FUNCTIONS

/** Internal -- adds a set of events to make some element behave like a button. */
Calendar._add_evs = function(el) {
  Calendar.addEvent(el, "mouseover", Calendar.dayMouseOver);
  Calendar.addEvent(el, "mousedown", Calendar.dayMouseDown);
  Calendar.addEvent(el, "mouseout", Calendar.dayMouseOut);
  if (Calendar.is_ie) {
    Calendar.addEvent(el, "dblclick", Calendar.dayMouseDblClick);
    el.setAttribute("unselectable", true);
  }
};
Calendar.findMonth = function(el) {
  if (typeof el.month != "undefined") {
    return el;
  }
  else if (typeof el.parentNode.month != "undefined") {
    return el.parentNode;
  }
  return null;
};

Calendar.findYear = function(el) {
  if (typeof el.year != "undefined") {
    return el;
  }
  else if (typeof el.parentNode.year != "undefined") {
    return el.parentNode;
  }
  return null;
};

Calendar.showMonthsCombo = function () {
  var cal = Calendar._C;
  if (!cal) {
    return false;
  }
  var cd = cal.activeDiv;
  var mc = cal.monthsCombo;
  if (cal.hilitedMonth) {
    Calendar.removeClass(cal.hilitedMonth, "hilite");
  }
  if (cal.activeMonth) {
    Calendar.removeClass(cal.activeMonth, "active");
  }
  var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
  Calendar.addClass(mon, "active");
  cal.activeMonth = mon;
  var s = mc.style;
  s.display = "block";
  if (cd.navtype < 0){
    s.left = cd.offsetLeft + "px";
  }
  else {
    var mcw = mc.offsetWidth;
    if (typeof mcw == "undefined"){
      mcw = 50;	// Konqueror brain-dead techniques
    }
    s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
  }
  s.top = (cd.offsetTop + cd.offsetHeight) + "px";
  return true;
};

Calendar.showYearsCombo = function (fwd) {
  var cal = Calendar._C;
  if (!cal) {
    return false;
  }
  var cd = cal.activeDiv;
  var yc = cal.yearsCombo;
  if (cal.hilitedYear) {
    Calendar.removeClass(cal.hilitedYear, "hilite");
  }
  if (cal.activeYear) {
    Calendar.removeClass(cal.activeYear, "active");
  }
  cal.activeYear = null;
  var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
  var yr = yc.firstChild;
  var show = false;
  for (var i = 12; i > 0; --i) {
    if (Y >= cal.minYear && Y <= cal.maxYear) {
      yr.innerHTML = Y;
      yr.year = Y;
      yr.style.display = "block";
      show = true;
    } else {
      yr.style.display = "none";
    }
    yr = yr.nextSibling;
    Y += fwd ? cal.yearStep : -cal.yearStep;
  }
  if (show) {
    var s = yc.style;
    s.display = "block";
    if (cd.navtype < 0){
      s.left = cd.offsetLeft + "px";
    }
    else {
      var ycw = yc.offsetWidth;
      if (typeof ycw == "undefined"){
        ycw = 50; // Konqueror brain-dead techniques
      }
      s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
    }
    s.top = (cd.offsetTop + cd.offsetHeight) + "px";
  }
  return true;
};

// event handlers

Calendar.tableMouseUp = function(ev) {
  if (!ev) { ev = window.event; }
  var cal = Calendar._C;
  if (!cal) {
    return false;
  }
  if (cal.timeout) {
    clearTimeout(cal.timeout);
  }
  var el = cal.activeDiv;
  if (!el) {
    return false;
  }
  var target = Calendar.getTargetElement(ev);
  Calendar.removeClass(el, "active");
  if (target == el || target.parentNode == el) {
    Calendar.cellClick(el, ev);
  }
  var mon = Calendar.findMonth(target);
  var date = null;
  if (mon) {
    date = new Date(cal.date);
    if (mon.month != date.getMonth()) {
      date.setMonth(mon.month);
      cal.setDate(date);
      cal.dateClicked = false;
      cal.callHandler();
    }
  }
  else {
    var year = Calendar.findYear(target);
    if (year) {
      date = new Date(cal.date);
      if (year.year != date.getFullYear()) {
        date.setFullYear(year.year);
        cal.setDate(date);
        cal.dateClicked = false;
        cal.callHandler();
      }
    }
  }
  Calendar.removeEvent(document, "mouseup", Calendar.tableMouseUp);
  Calendar.removeEvent(document, "mouseover", Calendar.tableMouseOver);
  Calendar.removeEvent(document, "mousemove", Calendar.tableMouseOver);
  cal._hideCombos();
  Calendar._C = null;
  return Calendar.stopEvent(ev);
};

Calendar.tableMouseOver = function (ev) {
  if (!ev) { ev = window.event; }
  var cal = Calendar._C;
  if (!cal) {
    return false;
  }
  var el = cal.activeDiv;
  var target = Calendar.getTargetElement(ev);
  if (target == el || target.parentNode == el) {
    Calendar.addClass(el, "hilite active");
    Calendar.addClass(el.parentNode, "rowhilite");
  }
  else {
    if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype === 0 || Math.abs(el.navtype) > 2))) {
      Calendar.removeClass(el, "active");
    }
    Calendar.removeClass(el, "hilite");
    Calendar.removeClass(el.parentNode, "rowhilite");
  }
  if (el.navtype == 50 && target != el) {
    var pos = Calendar.getAbsolutePos(el);
    var w = el.offsetWidth;
    var x = ev.clientX;
    var dx;
    var decrease = true;
    if (x > pos.x + w) {
      dx = x - pos.x - w;
      decrease = false;
    }
    else {
      dx = pos.x - x;
    }
    if (dx < 0) {
      dx = 0;
    }
    var range = el._range;
    var current = el._current;
    var count = Math.floor(dx / 10) % range.length;
    for (var i = range.length; --i >= 0;){
      if (range[i] == current){
        break;
      }
    }
    while (count-- > 0) {
      if (decrease) {
        if (--i < 0) {
          i = range.length - 1;
        }
      }
      else if ( ++i >= range.length ){
        i = 0;
      }
    }
    var newval = range[i];
    el.innerHTML = newval;

    cal.onUpdateTime();
  }
  var mon = Calendar.findMonth(target);
  if (mon) {
    if (mon.month != cal.date.getMonth()) {
      if (cal.hilitedMonth) {
        Calendar.removeClass(cal.hilitedMonth, "hilite");
      }
      Calendar.addClass(mon, "hilite");
      cal.hilitedMonth = mon;
    } else if (cal.hilitedMonth) {
      Calendar.removeClass(cal.hilitedMonth, "hilite");
    }
  } else {
    if (cal.hilitedMonth) {
      Calendar.removeClass(cal.hilitedMonth, "hilite");
    }
    var year = Calendar.findYear(target);
    if (year) {
      if (year.year != cal.date.getFullYear()) {
        if (cal.hilitedYear) {
          Calendar.removeClass(cal.hilitedYear, "hilite");
        }
        Calendar.addClass(year, "hilite");
        cal.hilitedYear = year;
      } else if (cal.hilitedYear) {
        Calendar.removeClass(cal.hilitedYear, "hilite");
      }
    } else if (cal.hilitedYear) {
      Calendar.removeClass(cal.hilitedYear, "hilite");
    }
  }
  return Calendar.stopEvent(ev);
};

Calendar.tableMouseDown = function (ev) {
  if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
    return Calendar.stopEvent(ev);
  }
  return true;
};

Calendar.calDragIt = function (ev) {
  var cal = Calendar._C;
  if (!(cal && cal.dragging)) {
    return false;
  }
  var posX;
  var posY;
  if (Calendar.is_ie) {
    posY = window.event.clientY + document.body.scrollTop;
    posX = window.event.clientX + document.body.scrollLeft;
  } else {
    posX = ev.pageX;
    posY = ev.pageY;
  }
  cal.hideShowCovered();
  var st = cal.element.style;
  st.left = (posX - cal.xOffs) + "px";
  st.top = (posY - cal.yOffs) + "px";
  return Calendar.stopEvent(ev);
};

Calendar.calDragEnd = function (ev) {
  var cal = Calendar._C;
  if (!cal) {
    return false;
  }
  cal.dragging = false;
  Calendar.removeEvent(document, "mousemove", Calendar.calDragIt);
  Calendar.removeEvent(document, "mouseup", Calendar.calDragEnd);
  Calendar.tableMouseUp(ev);
  cal.hideShowCovered();
  return true;
};

Calendar.dayMouseDown = function(ev) {
  var el = Calendar.getElement(ev);
  if (el.disabled) {
    return false;
  }
  var cal = el.calendar;
  cal.activeDiv = el;
  Calendar._C = cal;
  if (el.navtype != 300) {
    if (el.navtype == 50) {
      el._current = el.innerHTML;
      Calendar.addEvent(document, "mousemove", Calendar.tableMouseOver);
    }
    else {
      Calendar.addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", Calendar.tableMouseOver);
    }
    Calendar.addClass(el, "hilite active");
    Calendar.addEvent(document, "mouseup", Calendar.tableMouseUp);
  }
  else if (cal.isPopup) {
    cal._dragStart(ev);
  }
  if (el.navtype == -1 || el.navtype == 1) {
    if (cal.timeout) {
      clearTimeout(cal.timeout);
    }
    cal.timeout = setTimeout(Calendar.showMonthsCombo, 250);
  }
  else if (el.navtype == -2 || el.navtype == 2) {
    if (cal.timeout) {
      clearTimeout(cal.timeout);
    }
    cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
  }
  else {
    cal.timeout = null;
  }
  return Calendar.stopEvent(ev);
};

Calendar.dayMouseDblClick = function(ev) {
  Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
  if (Calendar.is_ie) {
    document.selection.empty();
  }
};

Calendar.dayMouseOver = function(ev) {
  var el = Calendar.getElement(ev);
  if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
    return false;
  }
  if (el.ttip) {
    if (el.ttip.substr(0, 1) == "_") {
      el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
    }
    el.calendar.tooltips.innerHTML = el.ttip;
  }
  if (el.navtype != 300) {
    Calendar.addClass(el, "hilite");
    if (el.caldate) {
      Calendar.addClass(el.parentNode, "rowhilite");
    }
  }
  return Calendar.stopEvent(ev);
};

Calendar.dayMouseOut = function(ev) {
  var el = Calendar.getElement(ev);
  if (Calendar.isRelated(el, ev) || (typeof Calendar._C!='undefined' && Calendar._C) || el.disabled) {
    return false;
  }
  Calendar.removeClass(el, "hilite");
  if (el.caldate) {
    Calendar.removeClass(el.parentNode, "rowhilite");
  }
  if (el.calendar) {
    el.calendar.tooltips.innerHTML = Calendar._TT.SEL_DATE;
  }
  return Calendar.stopEvent(ev);
};

/**
 *  A generic "click" handler :) handles all types of buttons defined in this
 *  calendar.
 */
Calendar.cellClick = function(el, ev) {
  var cal = el.calendar;
  var closing = false;
  var newdate = false;
  var date = null;
  if (typeof el.navtype == "undefined") {
    if (cal.currentDateEl) {
      Calendar.removeClass(cal.currentDateEl, "selected");
      Calendar.addClass(el, "selected");
      closing = (cal.currentDateEl == el);
      if (!closing) {
        cal.currentDateEl = el;
      }
    }
    cal.date.setDateOnly(el.caldate);
    date = cal.date;
    var other_month = !(cal.dateClicked = !el.otherMonth);
    if (!other_month && !cal.currentDateEl) {
      cal._toggleMultipleDate(new Date(date));
    }
    else {
      newdate = !el.disabled;
    }
    // a date was clicked
    if (other_month) {
      cal._init(cal.firstDayOfWeek, date);
    }
  }
  else {
    if (el.navtype == 200) {
      Calendar.removeClass(el, "hilite");
      cal.callCloseHandler();
      return;
    }
    if (el.navtype == 500) {
      popup_help('_help_user_calendar');
      Calendar.removeClass(el, "hilite");
      cal.callCloseHandler();
      return;
    }

    if (el.navtype == 600) {
      if (cal.link_enlarge_popup=='1') {
        var popup_URL = base_url+cal.link_enlarge;
        popup_calendar_large(popup_URL);
      }
      else {
        window.location = base_url+cal.link_enlarge+"?YYYY="+geid_val('YYYY')+"&MM="+geid_val("MM")+"&DD="+geid_val('DD');
      }
      Calendar.removeClass(el, "hilite");
      cal.callCloseHandler();
      return;
    }

    date = new Date(cal.date);
    if (el.navtype === 0){
      date.setDateOnly(new Date()); // TODAY
    }
    // unless "today" was clicked, we assume no date was clicked so
    // the selected handler will know not to close the calenar when
    // in single-click mode.
    // cal.dateClicked = (el.navtype == 0);
    cal.dateClicked = false;
    var year = date.getFullYear();
    var mon = date.getMonth();

    function setMonth(m) {
      var day = date.getDate();
      var max = date.getMonthDays(m);
      if (day > max) {
        date.setDate(max);
      }
      date.setMonth(m);
    }
    switch (el.navtype) {
      case 400:
        Calendar.removeClass(el, "hilite");
        var text = Calendar._TT.ABOUT;
        if (typeof text != "undefined") {
          text += cal.showsTime ? Calendar._TT.ABOUT_TIME : "";
        }
        else {
        // FIXME: this should be removed as soon as lang files get updated!
          text =
            "Help and about box text is not translated into this language.\n" +
            "If you know this language and you feel generous please update\n" +
            "the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
            "and send it back to <mihai_bazon@yahoo.com> to get it into the distribution  ;-)\n\n" +
            "Thank you!\n" +
            "http://dynarch.com/mishoo/calendar.epl\n";
        }
        alert(text);
        return;
      case -2:
        if (year > cal.minYear) {
          date.setFullYear(year - 1);
        }
      break;
      case -1:
        if (mon > 0) {
          setMonth(mon - 1);
        }
        else if (year-- > cal.minYear) {
          date.setFullYear(year);
          setMonth(11);
        }
      break;
      case 1:
        if (mon < 11) {
          setMonth(mon + 1);
        }
        else if (year < cal.maxYear) {
          date.setFullYear(year + 1);
          setMonth(0);
        }
      break;
      case 2:
        if (year < cal.maxYear) {
          date.setFullYear(year + 1);
        }
      break;
      case 100:
        cal.setFirstDayOfWeek(el.fdow);
        return;
      case 50:
        var range = el._range;
        var current = el.innerHTML;
        for (var i = range.length; --i >= 0;) {
          if (range[i] == current) {
            break;
          }
        }
        if (ev && ev.shiftKey) {
          if (--i < 0) {
            i = range.length - 1;
          }
        }
        else if ( ++i >= range.length ){
          i = 0;
        }
        var newval = range[i];
        el.innerHTML = newval;
        cal.onUpdateTime();
        return;
      case 0:
        // TODAY will bring us here
        cal.dateClicked = true;
        if ((typeof cal.getDateStatus == "function") && cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
          return;
        }
      break;
    }
    if (!date.equalsTo(cal.date)) {
      cal.setDate(date);
      newdate = true;
    }
    else if (el.navtype === 0){
      newdate = closing = true;
    }
  }
  if (ev && newdate) {
    cal.callHandler();
  }
  if (ev && closing) {
    Calendar.removeClass(el, "hilite");
    cal.callCloseHandler();
  }
};

// END: CALENDAR STATIC FUNCTIONS

// BEGIN: CALENDAR OBJECT FUNCTIONS

/**
 *  This function creates the calendar inside the given parent.  If _par is
 *  null than it creates a popup calendar inside the BODY element.  If _par is
 *  an element, be it BODY, then it creates a non-popup calendar (still
 *  hidden).  Some properties need to be set before calling this function.
 */
Calendar.prototype.create = function (_par) {
  var parent = null;
  if (! _par) {
    // default parent is the document body, in which case we create
    // a popup calendar.
    parent = document.getElementsByTagName("body")[0];
    this.isPopup = true;
  } else {
    parent = _par;
    this.isPopup = false;
  }
  this.date = this.dateStr ? new Date(this.dateStr) : new Date();

  var table = Calendar.createElement("table");
  this.table = table;
  table.cellSpacing = 0;
  table.cellPadding = 0;
  table.calendar = this;
  Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);

  var div = Calendar.createElement("div");
  this.element = div;
  div.className = "calendar_mini cal_table";
  if (this.isPopup) {
    div.style.position = "absolute";
    div.style.width = "200px";
    div.style.display = "none";
  }
  div.appendChild(table);

  var thead = Calendar.createElement("thead", table);
  var cell = null;
  var row = null;

  var cal = this;
  var hh = function (text, cs, navtype) {
    cell = Calendar.createElement("td", row);
    cell.colSpan = cs;
    cell.className = "button";
    if (navtype !== 0 && Math.abs(navtype) <= 2) {
      cell.className += " cal_nav";
    }
    Calendar._add_evs(cell);
    cell.calendar = cal;
    cell.navtype = navtype;
    cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
    return cell;
  };

  row = Calendar.createElement("tr", thead);
  var title_length = 5;
  if (this.isPopup) {
    --title_length;
  }
  if (this.weekNumbers) {
    ++title_length;
  }

  if (this.link_enlarge) {
    _link_btn = hh("", 1, 600);
    _link_btn.ttip = "Enlarge or print calendar";
    _link_btn.title = "Enlarge";
    _link_btn.className = "title cal_head cal_enlarge";
  }
  else {
    _link_btn = hh("", 1, 300);
    _link_btn.className = "title cal_head";
  }



  this.title = hh("", title_length, 300);
  this.title.className = "title cal_head";
  if (this.isPopup) {
    this.title.ttip = Calendar._TT.DRAG_TO_MOVE;
    this.title.style.cursor = "move";
    _close_btn = hh("&#x00d7;", 1, 200);
    _close_btn.ttip = Calendar._TT.CLOSE;
    _close_btn.className = "title cal_head"
  }
  var _help_btn;
  if (this.link_help=='1') {
    _help_btn = hh("", 1, 500);
    _help_btn.ttip = "View Help for calendar";
    _help_btn.title = "Help";
    _help_btn.className = "title cal_head cal_help";
  }
  else {
    _help_btn = hh("", 1, 300);
    _help_btn.className = "title cal_head";
  }

  row = Calendar.createElement("tr", thead);
  row.className = "headrow";

  this._nav_py = hh("&#x00ab;", 1, -2);
  this._nav_py.title = this._nav_py.ttip = Calendar._TT.PREV_YEAR;

  this._nav_pm = hh("&#x2039;", 1, -1);
  this._nav_pm.title = this._nav_pm.ttip = Calendar._TT.PREV_MONTH;

  this._nav_now = hh(Calendar._TT.TODAY, this.weekNumbers ? 4 : 3, 0);
  this._nav_now.title = this._nav_now.ttip = Calendar._TT.GO_TODAY;
  this._nav_nm = hh("&#x203a;", 1, 1);
  this._nav_nm.title = this._nav_nm.ttip = Calendar._TT.NEXT_MONTH;

  this._nav_ny = hh("&#x00bb;", 1, 2);
  this._nav_ny.title = this._nav_ny.ttip = Calendar._TT.NEXT_YEAR;

  // day names
  row = Calendar.createElement("tr", thead);
  if (this.weekNumbers) {
    cell = Calendar.createElement("td", row);
    cell.className = "name wn";
    cell.innerHTML = Calendar._TT.WK;
  }
  for (var i = 7; i > 0; --i) {
    cell = Calendar.createElement("td", row);
    if (!i) {
      cell.navtype = 100;
      cell.calendar = this;
      Calendar._add_evs(cell);
    }
  }
  this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
  this._displayWeekdays();

  var tbody = Calendar.createElement("tbody", table);
  this.tbody = tbody;

  for (i = 6; i > 0; --i) {
    row = Calendar.createElement("tr", tbody);
    if (this.weekNumbers) {
      cell = Calendar.createElement("td", row);
    }
    for (var j = 7; j > 0; --j) {
      cell = Calendar.createElement("td", row);
      cell.calendar = this;
      Calendar._add_evs(cell);
    }
  }

  if (this.showsTime) {
    row = Calendar.createElement("tr", tbody);
    row.className = "time";

    cell = Calendar.createElement("td", row);
    cell.className = "time";
    cell.colSpan = 2;
    cell.innerHTML = Calendar._TT.TIME || "&nbsp;";

    cell = Calendar.createElement("td", row);
    cell.className = "time";
    cell.colSpan = this.weekNumbers ? 4 : 3;

    (function(){
      function makeTimePart(className, init, range_start, range_end) {
        var part = Calendar.createElement("span", cell);
        part.className = className;
        part.innerHTML = init;
        part.calendar = cal;
        part.ttip = Calendar._TT.TIME_PART;
        part.navtype = 50;
        part._range = [];
        if (typeof range_start != "number") {
          part._range = range_start;
        }
        else {
          for (var i = range_start; i <= range_end; ++i) {
            var txt;
            if (i < 10 && range_end >= 10) {
              txt = '0' + i;
            }
            else {
              txt = '' + i;
            }
            part._range[part._range.length] = txt;
          }
        }
        Calendar._add_evs(part);
        return part;
      }
      var hrs = cal.date.getHours();
      var mins = cal.date.getMinutes();
      var t12 = !cal.time24;
      var pm = (hrs > 12);
      if (t12 && pm) {
        hrs -= 12;
      }
      var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
      var span = Calendar.createElement("span", cell);
      span.innerHTML = ":";
      span.className = "colon";
      var M = makeTimePart("minute", mins, 0, 59);
      var AP = null;
      cell = Calendar.createElement("td", row);
      cell.className = "time";
      cell.colSpan = 2;
      if (t12) {
        AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
      }
      else {
        cell.innerHTML = "&nbsp;";
      }

      cal.onSetTime = function() {
        var pm, hrs = this.date.getHours(), mins = this.date.getMinutes();
        if (t12) {
          pm = (hrs >= 12);
          if (pm) {
            hrs -= 12;
          }
          if (hrs === 0) {
            hrs = 12;
          }
          AP.innerHTML = (pm ? "pm" : "am");
        }
        H.innerHTML = ((hrs < 10) ? ("0" + hrs) : hrs);
        M.innerHTML = ((mins < 10) ? ("0" + mins) : mins);
      };

      cal.onUpdateTime = function() {
        var date = this.date;
        var h = parseInt(H.innerHTML, 10);
        if (t12) {
          if (/pm/i.test(AP.innerHTML) && h < 12) {
            h += 12;
          }
          else if (/am/i.test(AP.innerHTML) && h == 12) {
            h = 0;
          }
        }
        var d = date.getDate();
        var m = date.getMonth();
        var y = date.getFullYear();
        date.setHours(h);
        date.setMinutes(parseInt(M.innerHTML, 10));
        date.setFullYear(y);
        date.setMonth(m);
        date.setDate(d);
        this.dateClicked = false;
        this.callHandler();
      };
    })();
  }
  else {
    this.onSetTime = this.onUpdateTime = function() {};
  }

  var tfoot = Calendar.createElement("tfoot", table);

  row = Calendar.createElement("tr", tfoot);
  row.className = "footrow";

  cell = hh(Calendar._TT.SEL_DATE, this.weekNumbers ? 8 : 7, 300);
  cell.className = "ttip";
  if (this.isPopup) {
    cell.ttip = Calendar._TT.DRAG_TO_MOVE;
    cell.style.cursor = "move";
  }
  this.tooltips = cell;

  div = Calendar.createElement("div", this.element);
  this.monthsCombo = div;
  div.className = "combo";
  for (i = 0; i < Calendar._MN.length; ++i) {
    var mn = Calendar.createElement("div");
    mn.className = (Calendar.is_ie ? "label-IEfix" : "label");
    mn.month = i;
    mn.innerHTML = Calendar._SMN[i];
    div.appendChild(mn);
  }

  div = Calendar.createElement("div", this.element);
  this.yearsCombo = div;
  div.className = "combo";
  for (i = 12; i > 0; --i) {
    var yr = Calendar.createElement("div");
    yr.className = (Calendar.is_ie ? "label-IEfix" : "label");
    div.appendChild(yr);
  }

  this._init(this.firstDayOfWeek, this.date);
  parent.appendChild(this.element);
};

/** keyboard navigation, only for popup calendars */
Calendar._keyEvent =
  function(ev) {
    var cal = window._dynarch_popupCalendar;
    if (!cal || cal.multiple) {
      return false;
    }
    if (Calendar.is_ie) {
      ev = window.event;
    }
    var act = (Calendar.is_ie || ev.type == "keypress"), K = ev.keyCode;
    if (ev.ctrlKey) {
      switch (K) {
        case 37: // KEY left
          if (act) { Calendar.cellClick(cal._nav_pm); }
        break;
        case 38: // KEY up
          if (act) { Calendar.cellClick(cal._nav_py); }
        break;
        case 39: // KEY right
          if (act) { Calendar.cellClick(cal._nav_nm); }
        break;
        case 40: // KEY down
          if (act) { Calendar.cellClick(cal._nav_ny); }
        break;
        default:
          return false;
        }
    }
    else switch (K) {
      case 32: // KEY space (now)
        Calendar.cellClick(cal._nav_now);
      break;
      case 27: // KEY esc
        if (act) { cal.callCloseHandler(); }
      break;
      case 37: // KEY left
      case 38: // KEY up
      case 39: // KEY right
      case 40: // KEY down
        if (act) {
          var prev, x, y, ne, el, step;
          prev = K == 37 || K == 38;
          step = (K == 37 || K == 39) ? 1 : 7;
          function setVars() {
            el = cal.currentDateEl;
            var p = el.pos;
            x = p & 15;
            y = p >> 4;
            ne = cal.ar_days[y][x];
          }
          setVars();
          function prevMonth() {
            var date = new Date(cal.date);
            date.setDate(date.getDate() - step);
            cal.setDate(date);
          }
          function nextMonth() {
            var date = new Date(cal.date);
            date.setDate(date.getDate() + step);
            cal.setDate(date);
          }
          while (1) {
            switch (K) {
              case 37: // KEY left
                if (--x >= 0) {
                  ne = cal.ar_days[y][x];
                }
                else {
                  x = 6;
                  K = 38;
                  continue;
                }
              break;
              case 38: // KEY up
                if (--y >= 0) {
                  ne = cal.ar_days[y][x];
                }
              else {
                prevMonth();
                setVars();
              }
            break;
            case 39: // KEY right
              if (++x < 7){
                ne = cal.ar_days[y][x];
              }
              else {
                x = 0;
                K = 40;
                continue;
              }
            break;
            case 40: // KEY down
              if (++y < cal.ar_days.length) {
                ne = cal.ar_days[y][x];
              }
              else {
                nextMonth();
                setVars();
              }
            break;
          }
        break;
      }
      if (ne) {
        if (!ne.disabled) {
          Calendar.cellClick(ne);
        }
        else if (prev) {
          prevMonth();
        }
        else {
          nextMonth();
        }
      }
    }
    break;
    case 13: // KEY enter
      if (act) {
        Calendar.cellClick(cal.currentDateEl, ev);
      }
    break;
    default:
      return false;
  }
  return Calendar.stopEvent(ev);
};

/**
 *  (RE)Initializes the calendar to the given date and firstDayOfWeek
 */
Calendar.prototype._init = function (firstDayOfWeek, date) {
  var today = new Date(),
    TY = today.getFullYear(),
    TM = today.getMonth(),
    TD = today.getDate();
  this.table.style.visibility = "hidden";
  var year = date.getFullYear();
  if (year < this.minYear) {
    year = this.minYear;
    date.setFullYear(year);
  } else if (year > this.maxYear) {
    year = this.maxYear;
    date.setFullYear(year);
  }
  this.firstDayOfWeek = firstDayOfWeek;
  this.date = new Date(date);
  var month = date.getMonth();
  var mday = date.getDate();
  var no_days = date.getMonthDays();

  // calendar voodoo for computing the first day that would actually be
  // displayed in the calendar, even if it's from the previous month.
  // WARNING: this is magic. ;-)
  date.setDate(1);
  var day1 = (date.getDay() - this.firstDayOfWeek) % 7;

// Changed this line to ensure some datesfrom last month are always shown
//if (day1 < 0){
  if (day1 < 1){
    day1 += 7;
  }
  date.setDate(-day1);
  date.setDate(date.getDate() + 1);

  var row = this.tbody.firstChild;
  var MN = Calendar._SMN[month];
  var ar_days = [];
  this.ar_days = [];
  var weekend = Calendar._TT.WEEKEND;
  var dates = this.multiple ? (this.datesCells = {}) : null;
  for (var i = 0; i < 6; ++i, row = row.nextSibling) {
    var cell = row.firstChild;
    if (this.weekNumbers) {
      cell.className = "day wn";
      cell.innerHTML = date.getWeekNumber();
      cell = cell.nextSibling;
    }
    row.className = "daysrow";
    var hasdays = false, iday, dpos = [];
    ar_days[i] = [];
    for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
      iday = date.getDate();
      var wday = date.getDay();
      cell.className = "cal_current";
      cell.pos = i << 4 | j;
      dpos[j] = cell;
      var current_month = (date.getMonth() == month);
      if (!current_month) {
        if (this.showsOtherMonths) {
          cell.className += " cal_then";
          cell.otherMonth = true;
        } else {
          cell.className = "emptycell";
          cell.innerHTML = "&nbsp;";
          cell.disabled = true;
          continue;
        }
      } else {
        cell.otherMonth = false;
        hasdays = true;
      }
      cell.disabled = false;
      cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
      if (dates) {
        dates[date.print("%Y%m%d")] = cell;
      }
      if (this.getDateStatus) {
        var status = this.getDateStatus(date, year, month, iday);
        if (this.getDateToolTip) {
          var toolTip = this.getDateToolTip(date, year, month, iday);
          if (toolTip) {
            cell.title = toolTip;
          }
        }
        if (status === true) {
          cell.className += " disabled";
          cell.disabled = true;
        }
         else {
          if (/disabled/i.test(status)) {
            cell.disabled = true;
          }
          cell.className += " " + status;
        }
      }
      if (!cell.disabled) {
        cell.caldate = new Date(date);
        cell.ttip = "_";
        if (!this.multiple && current_month && iday == mday && this.hiliteToday) {
          cell.className += " selected";
          this.currentDateEl = cell;
        }
        if (date.getFullYear() == TY && date.getMonth() == TM && iday == TD) {
          cell.className += " cal_today";
          cell.ttip += Calendar._TT.PART_TODAY;
        }
        if (weekend.indexOf(wday.toString()) != -1) {
          cell.className += cell.otherMonth ? " cal_then_we" : " cal_current_we";
        }
      }
    }
    if (!(hasdays || this.showsOtherMonths)) {
      row.className = "emptyrow";
    }
  }
  this.title.innerHTML = Calendar._MN[month] + ", " + year;
  this.onSetTime();
  this.table.style.visibility = "visible";
  this._initMultipleDates();
  // PROFILE
  // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
};

Calendar.prototype._initMultipleDates = function() {
  if (this.multiple) {
    for (var i in this.multiple) {
      var cell = this.datesCells[i];
      var d = this.multiple[i];
      if (!d) {
        continue;
      }
      if (cell) {
        cell.className += " selected";
      }
    }
  }
};

Calendar.prototype._toggleMultipleDate = function(date) {
  if (this.multiple) {
    var ds = date.print("%Y%m%d");
    var cell = this.datesCells[ds];
    if (cell) {
      var d = this.multiple[ds];
      if (!d) {
        Calendar.addClass(cell, "selected");
        this.multiple[ds] = date;
      }
      else {
        Calendar.removeClass(cell, "selected");
        delete this.multiple[ds];
      }
    }
  }
};

Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
  this.getDateToolTip = unaryFunction;
};
Calendar.prototype.setLinkEnlarge = function (link_enlarge) {
  this.link_enlarge = link_enlarge;
};
Calendar.prototype.setLinkEnlargePopup = function (link_enlarge_popup) {
  this.link_enlarge_popup = link_enlarge_popup;
};
Calendar.prototype.setLinkHelp = function (link_help) {
  this.link_help = link_help;
};

/**
 *  Calls _init function above for going to a certain date (but only if the
 *  date is different than the currently selected one).
 */
Calendar.prototype.setDate = function (date) {
  if (!date.equalsTo(this.date)) {
    this._init(this.firstDayOfWeek, date);
  }
};

/**
 *  Refreshes the calendar.  Useful if the "disabledHandler" function is
 *  dynamic, meaning that the list of disabled date can change at runtime.
 *  Just * call this function if you think that the list of disabled dates
 *  should * change.
 */
Calendar.prototype.refresh = function () {
  this._init(this.firstDayOfWeek, this.date);
};

/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
  this._init(firstDayOfWeek, this.date);
  this._displayWeekdays();
};

/**
 *  Allows customization of what dates are enabled.  The "unaryFunction"
 *  parameter must be a function object that receives the date (as a JS Date
 *  object) and returns a boolean value.  If the returned value is true then
 *  the passed date will be marked as disabled.
 */
Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
  this.getDateStatus = unaryFunction;
};

/** Customization of allowed year range for the calendar. */
Calendar.prototype.setRange = function (a, z) {
  this.minYear = a;
  this.maxYear = z;
};

/** Calls the first user handler (selectedHandler). */
Calendar.prototype.callHandler = function () {
  if (this.onSelected) {
    this.onSelected(this, this.date.print(this.dateFormat));
  }
};

/** Calls the second user handler (closeHandler). */
Calendar.prototype.callCloseHandler = function () {
  if (this.onClose) {
    this.onClose(this);
  }
  this.hideShowCovered();
};

/** Removes the calendar object from the DOM tree and destroys it. */
Calendar.prototype.destroy = function () {
  var el = this.element.parentNode;
  el.removeChild(this.element);
  Calendar._C = null;
  window._dynarch_popupCalendar = null;
};

/**
 *  Moves the calendar element to a different section in the DOM tree (changes
 *  its parent).
 */
Calendar.prototype.reparent = function (new_parent) {
  var el = this.element;
  el.parentNode.removeChild(el);
  new_parent.appendChild(el);
};

// This gets called when the user presses a mouse button anywhere in the
// document, if the calendar is shown.  If the click was outside the open
// calendar this function closes it.
Calendar._checkCalendar = function(ev) {
  var calendar = window._dynarch_popupCalendar;
  if (!calendar) {
    return false;
  }
  var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
  for (; el != null && el != calendar.element; el = el.parentNode);
  if (el == null) {
    // calls closeHandler which should hide the calendar.
    window._dynarch_popupCalendar.callCloseHandler();
    return Calendar.stopEvent(ev);
  }
  return true;
};

/** Shows the calendar. */
Calendar.prototype.show = function () {
  var rows = this.table.getElementsByTagName("tr");
  for (var i = rows.length; i > 0;) {
    var row = rows[--i];
    Calendar.removeClass(row, "rowhilite");
    var cells = row.getElementsByTagName("td");
    for (var j = cells.length; j > 0;) {
      var cell = cells[--j];
      Calendar.removeClass(cell, "hilite");
      Calendar.removeClass(cell, "active");
    }
  }
  this.element.style.display = "block";
  this.hidden = false;
  if (this.isPopup) {
    window._dynarch_popupCalendar = this;
    Calendar.addEvent(document, "keydown", Calendar._keyEvent);
    Calendar.addEvent(document, "keypress", Calendar._keyEvent);
    Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
  }
  this.hideShowCovered();
};

/**
 *  Hides the calendar.  Also removes any "hilite" from the class of any TD
 *  element.
 */
Calendar.prototype.hide = function () {
  if (this.isPopup) {
    Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
    Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
    Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
  }
  this.element.style.display = "none";
  this.hidden = true;
  this.hideShowCovered();
};

/**
 *  Shows the calendar at a given absolute position (beware that, depending on
 *  the calendar element style -- position property -- this might be relative
 *  to the parent's containing rectangle).
 */
Calendar.prototype.showAt = function (x, y) {
  var s = this.element.style;
  s.left = x + "px";
  s.top = y + "px";
  this.show();
};

/** Shows the calendar near a given element. */
Calendar.prototype.showAtElement = function (el, opts) {
  var self = this;
  var p = Calendar.getAbsolutePos(el);
  if (!opts || typeof opts != "string") {
    this.showAt(p.x, p.y + el.offsetHeight);
    return true;
  }
  function fixPosition(box) {
    if (box.x < 0) {
      box.x = 0;
    }
    if (box.y < 0) {
      box.y = 0;
    }
    var cp = document.createElement("div");
    var s = cp.style;
    s.position = "absolute";
    s.right = s.bottom = s.width = s.height = "0px";
    document.body.appendChild(cp);
    var br = Calendar.getAbsolutePos(cp);
    document.body.removeChild(cp);
    if (Calendar.is_ie) {
      br.y += document.body.scrollTop;
      br.x += document.body.scrollLeft;
    }
    else {
      br.y += window.scrollY;
      br.x += window.scrollX;
    }
    var tmp = box.x + box.width - br.x;
    if (tmp > 0) {
      box.x -= tmp;
    }
    tmp = box.y + box.height - br.y;
    if (tmp > 0) {
      box.y -= tmp;
    }
  }
  this.element.style.display = "block";
  Calendar.continuation_for_the_khtml_browser = function() {
    var w = self.element.offsetWidth;
    var h = self.element.offsetHeight;
    self.element.style.display = "none";
    var valign = opts.substr(0, 1);
    var halign = "l";
    if (opts.length > 1) {
      halign = opts.substr(1, 1);
    }
    // vertical alignment
    switch (valign) {
      case "T": p.y -= h; break;
      case "B": p.y += el.offsetHeight; break;
      case "C": p.y += (el.offsetHeight - h) / 2; break;
      case "t": p.y += el.offsetHeight - h; break;
      case "b": break; // already there
    }
    // horizontal alignment
    switch (halign) {
      case "L": p.x -= w; break;
      case "R": p.x += el.offsetWidth; break;
      case "C": p.x += (el.offsetWidth - w) / 2; break;
      case "l": p.x += el.offsetWidth - w; break;
      case "r": break; // already there
    }
    p.width = w;
    p.height = h + 40;
    self.monthsCombo.style.display = "none";
    fixPosition(p);
    self.showAt(p.x, p.y);
  };
  if (Calendar.is_khtml) {
    setTimeout(Calendar.continuation_for_the_khtml_browser, 10);
  }
  else {
    Calendar.continuation_for_the_khtml_browser();
  }
  return false;
};

/** Customizes the date format. */
Calendar.prototype.setDateFormat = function (str) {
  this.dateFormat = str;
};

/** Customizes the tooltip date format. */
Calendar.prototype.setTtDateFormat = function (str) {
  this.ttDateFormat = str;
};

/**
 *  Tries to identify the date represented in a string.  If successful it also
 *  calls this.setDate which moves the calendar to the given date.
 */
Calendar.prototype.parseDate = function(str, fmt) {
  if (!fmt) {
    fmt = this.dateFormat;
  }
  this.setDate(Date.parseDate(str, fmt));
};

Calendar.prototype.hideShowCovered = function () {
  if (!Calendar.is_ie && !Calendar.is_opera) {
    return;
  }
  if (!isIE_lt8){
    return;
  }
  function getVisib(obj){
    var value = obj.style.visibility;
    if (!value) {
      if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
        if (!Calendar.is_khtml) {
          value = document.defaultView.
            getComputedStyle(obj, "").getPropertyValue("visibility");
        }
        else {
          value = '';
        }
      }
      else if (obj.currentStyle) { // IE
        value = obj.currentStyle.visibility;
      }
      else {
        value = '';
      }
    }
    return value;
  }
  var tags = ["applet", "iframe", "select"];
  var el = this.element;

  var p = Calendar.getAbsolutePos(el);
  var EX1 = p.x;
  var EX2 = el.offsetWidth + EX1;
  var EY1 = p.y;
  var EY2 = el.offsetHeight + EY1;

  for (var k = tags.length; k > 0; ) {
    var ar = document.getElementsByTagName(tags[--k]);
    var cc = null;

    for (var i = ar.length; i > 0;) {
      cc = ar[--i];

      p = Calendar.getAbsolutePos(cc);
      var CX1 = p.x;
      var CX2 = cc.offsetWidth + CX1;
      var CY1 = p.y;
      var CY2 = cc.offsetHeight + CY1;

      if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
        if (!cc.__msh_save_visibility) {
          cc.__msh_save_visibility = getVisib(cc);
        }
        cc.style.visibility = cc.__msh_save_visibility;
      }
      else {
        if (!cc.__msh_save_visibility) {
          cc.__msh_save_visibility = getVisib(cc);
        }
        cc.style.visibility = "hidden";
      }
    }
  }
};

/** Internal function; it displays the bar with the names of the weekday. */
Calendar.prototype._displayWeekdays = function () {
  var fdow = this.firstDayOfWeek;
  var cell = this.firstdayname;
  var weekend = Calendar._TT.WEEKEND;
  for (var i = 0; i < 7; ++i) {
    cell.className = "cal_days";
    if (i==6) { cell.className += " cal_days_s"; }
    var realday = (i + fdow) % 7;
    if (i) {
      cell.ttip = Calendar._TT.DAY_FIRST.replace("%s", Calendar._DN[realday]);
      cell.navtype = 100;
      cell.calendar = this;
      cell.fdow = realday;
//      Calendar._add_evs(cell); // Changed by M Francis - removes ability to change start day for each week
    }
    if (weekend.indexOf(realday.toString()) != -1) {
      Calendar.addClass(cell, "weekend");
    }
    cell.innerHTML = Calendar._SDN[(i + fdow) % 7].substr(0,1);
    cell = cell.nextSibling;
  }
};

/** Internal function.  Hides all combo boxes that might be displayed. */
Calendar.prototype._hideCombos = function () {
  this.monthsCombo.style.display = "none";
  this.yearsCombo.style.display = "none";
};

/** Internal function.  Starts dragging the element. */
Calendar.prototype._dragStart = function (ev) {
  if (this.dragging) {
    return;
  }
  this.dragging = true;
  var posX;
  var posY;
  if (Calendar.is_ie) {
    posY = window.event.clientY + document.body.scrollTop;
    posX = window.event.clientX + document.body.scrollLeft;
  } else {
    posY = ev.clientY + window.scrollY;
    posX = ev.clientX + window.scrollX;
  }
  var st = this.element.style;
  this.xOffs = posX - parseInt(st.left);
  this.yOffs = posY - parseInt(st.top);
  Calendar.addEvent(document, "mousemove", Calendar.calDragIt);
  Calendar.addEvent(document, "mouseup", Calendar.calDragEnd);
};

Calendar._DN =   ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
Calendar._SDN =  ["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
Calendar._FD =   0;
Calendar._MN =   ["January","February","March","April","May","June","July","August","September","October","November","December"];
Calendar._SMN =  ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
Calendar._TT =   {};
Calendar._TT.INFO = "About the calendar";
Calendar._TT.ABOUT =
  "DHTML Date/Time Selector\n" +
  "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
  "For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
  "Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details." +
  "\n\n" +
  "Date selection:\n" +
  "- Use the \xab, \xbb buttons to select year\n" +
  "- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" +
  "- Hold mouse button on any of the above buttons for faster selection.";
  Calendar._TT["ABOUT_TIME"] = "\n\n" +
  "Time selection:\n" +
  "- Click on any of the time parts to increase it\n" +
  "- or Shift-click to decrease it\n" +
  "- or click and drag for faster selection.";
Calendar._TT.PREV_YEAR =       "Prev. year (hold for menu)";
Calendar._TT.PREV_MONTH =      "Prev. month (hold for menu)";
Calendar._TT.GO_TODAY =        "Go to Today";
Calendar._TT.NEXT_MONTH =      "Next month (hold for menu)";
Calendar._TT.NEXT_YEAR =       "Next year (hold for menu)";
Calendar._TT.SEL_DATE =        "Select date";
Calendar._TT.DRAG_TO_MOVE =    "Drag to move";
Calendar._TT.PART_TODAY =      " (today)";
Calendar._TT.DAY_FIRST =       "Display %s first";
Calendar._TT.WEEKEND =         "0,6";
Calendar._TT.CLOSE =           "Close";
Calendar._TT.TODAY =           "Today";
Calendar._TT.TIME_PART =       "(Shift-)Click or drag to change value";
Calendar._TT.DEF_DATE_FORMAT = "%Y-%m-%d";
Calendar._TT.TT_DATE_FORMAT =  "%a, %b %e";
Calendar._TT.WK =              "wk";
Calendar._TT.TIME =            "Time:";



// BEGIN: DATE OBJECT PATCHES

/** Adds the number of days array to the Date object. */
Date._MD = [31,28,31,30,31,30,31,31,30,31,30,31];

/** Constants used for time computations */
Date.SECOND = 1000 /* milliseconds */;
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR   = 60 * Date.MINUTE;
Date.DAY    = 24 * Date.HOUR;
Date.WEEK   =  7 * Date.DAY;

Date.parseDate = function(str, fmt) {
  var today = new Date();
  var y = 0;
  var m = -1;
  var d = 0;
  var a = str.split(/\W+/);
  var b = fmt.match(/%./g);
  var i = 0, j = 0;
  var hr = 0;
  var min = 0;
  for (i = 0; i < a.length; ++i) {
    if (!a[i]) {
      continue;
    }
    switch (b[i]) {
      case "%d":
      case "%e":
        d = parseInt(a[i], 10);
      break;
      case "%m":
        m = parseInt(a[i], 10) - 1;
      break;
      case "%Y":
      case "%y":
        y = parseInt(a[i], 10);
        if (y < 100) {
          (y += (y > 29) ? 1900 : 2000);
        }
      break;
      case "%b":
      case "%B":
        for (j = 0; j < 12; ++j) {
          if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
        }
      break;
      case "%H":
      case "%I":
      case "%k":
      case "%l":
        hr = parseInt(a[i], 10);
      break;
      case "%P":
      case "%p":
        if (/pm/i.test(a[i]) && hr < 12) {
          hr += 12;
        }
        else if (/am/i.test(a[i]) && hr >= 12) {
          hr -= 12;
        }
      break;
      case "%M":
        min = parseInt(a[i], 10);
      break;
    }
  }
  if (isNaN(y)) {
    y = today.getFullYear();
  }
  if (isNaN(m)) {
    m = today.getMonth();
  }
  if (isNaN(d)) {
    d = today.getDate();
  }
  if (isNaN(hr)) {
    hr = today.getHours();
  }
  if (isNaN(min)) {
    min = today.getMinutes();
  }
  if (y != 0 && m != -1 && d != 0) {
    return new Date(y, m, d, hr, min, 0);
  }
  y = 0;
  m = -1;
  d = 0;
  for (i = 0; i < a.length; ++i) {
    if (a[i].search(/[a-zA-Z]+/) != -1) {
      var t = -1;
      for (j = 0; j < 12; ++j) {
        if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) {
          t = j;
          break;
        }
      }
      if (t != -1) {
        if (m != -1) {
          d = m+1;
        }
        m = t;
      }
    }
    else if (parseInt(a[i], 10) <= 12 && m == -1) {
      m = a[i]-1;
    }
    else if (parseInt(a[i], 10) > 31 && y == 0) {
      y = parseInt(a[i], 10);
      if (y < 100) {
        (y += (y > 29) ? 1900 : 2000);
      }
    }
    else if (d == 0) {
      d = a[i];
    }
  }
  if (y == 0) {
    y = today.getFullYear();
  }
  if (m != -1 && d != 0) {
    return new Date(y, m, d, hr, min, 0);
  }
  return today;
};

/** Returns the number of days in the current month */
Date.prototype.getMonthDays = function(month) {
  var year = this.getFullYear();
  if (typeof month == "undefined") {
    month = this.getMonth();
  }
  if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
    return 29;
  }
  else {
    return Date._MD[month];
  }
};

/** Returns the number of day in the year. */
Date.prototype.getDayOfYear = function() {
  var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
  var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
  var time = now - then;
  return Math.floor(time / Date.DAY);
};

/** Returns the number of the week in year, as defined in ISO 8601. */
Date.prototype.getWeekNumber = function() {
  var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
  var DoW = d.getDay();
  d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
  var ms = d.valueOf(); // GMT
  d.setMonth(0);
  d.setDate(4); // Thu in Week 1
  return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};

/** Checks date and time equality */
Date.prototype.equalsTo = function(date) {
  return ((this.getFullYear() == date.getFullYear()) &&
    (this.getMonth() == date.getMonth()) &&
    (this.getDate() == date.getDate()) &&
    (this.getHours() == date.getHours()) &&
    (this.getMinutes() == date.getMinutes()));
};

Date.prototype.toISO = function(date) {
  var yyyy, mm, dd;
  yyyy = this.getFullYear();
  mm = this.getMonth()+1;
  dd = this.getDate();
  return yyyy+'-'+(mm.toString().length==2 ? mm : '0'+mm) + '-' + (dd.toString().length==2 ? dd : '0'+dd);
}

/** Set only the year, month, date parts (keep existing time) */
Date.prototype.setDateOnly = function(date) {
  var tmp = new Date(date);
  this.setDate(1);
  this.setFullYear(tmp.getFullYear());
  this.setMonth(tmp.getMonth());
  this.setDate(tmp.getDate());
};

/** Prints the date in a string according to the given format. */
Date.prototype.print = function (str) {
  var m = this.getMonth();
  var d = this.getDate();
  var y = this.getFullYear();
  var wn = this.getWeekNumber();
  var w = this.getDay();
  var s = {};
  var hr = this.getHours();
  var pm = (hr >= 12);
  var ir = (pm) ? (hr - 12) : hr;
  var dy = this.getDayOfYear();
  if (ir == 0) {
    ir = 12;
  }
  var min = this.getMinutes();
  var sec = this.getSeconds();
  s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
  s["%A"] = Calendar._DN[w]; // full weekday name
  s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
  s["%B"] = Calendar._MN[m]; // full month name
  // FIXME: %c : preferred date and time representation for the current locale
  s["%C"] = 1 + Math.floor(y / 100); // the century number
  s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
  s["%e"] = d; // the day of the month (range 1 to 31)
  // FIXME: %D : american date style: %m/%d/%y
  // FIXME: %E, %F, %G, %g, %h (man strftime)
  s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
  s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
  s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
  s["%k"] = hr;    // hour, range 0 to 23 (24h format)
  s["%l"] = ir;    // hour, range 1 to 12 (12h format)
  s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
  s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
  s["%n"] = "\n";    // a newline character
  s["%p"] = pm ? "PM" : "AM";
  s["%P"] = pm ? "pm" : "am";
  // FIXME: %r : the time in am/pm notation %I:%M:%S %p
  // FIXME: %R : the time in 24-hour notation %H:%M
  s["%s"] = Math.floor(this.getTime() / 1000);
  s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
  s["%t"] = "\t";    // a tab character
  // FIXME: %T : the time in 24-hour notation (%H:%M:%S)
  s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
  s["%u"] = w + 1;  // the day of the week (range 1 to 7, 1 = MON)
  s["%w"] = w;    // the day of the week (range 0 to 6, 0 = SUN)
  // FIXME: %x : preferred date representation for the current locale without the time
  // FIXME: %X : preferred time representation for the current locale without the date
  s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
  s["%Y"] = y;    // year with the century
  s["%%"] = "%";    // a literal '%' character

  var re = /%./g;
  if (!Calendar.is_ie5 && !Calendar.is_khtml) {
    return str.replace(re, function (par) { return s[par] || par; });
  }
  var a = str.match(re);
  for (var i = 0; i < a.length; i++) {
    var tmp = s[a[i]];
    if (tmp) {
      re = new RegExp(a[i], 'g');
      str = str.replace(re, tmp);
    }
  }

  return str;
};

Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
Date.prototype.setFullYear = function(y) {
  var d = new Date(this);
  d.__msh_oldSetFullYear(y);
  if (d.getMonth() != this.getMonth()) {
    this.setDate(28);
  }
  this.__msh_oldSetFullYear(y);
};

// END: DATE OBJECT PATCHES

function popup_calendar(id) {
  function popup_calendar_close(cal) {
    cal.destroy();                        // hide the calendar
  }
  function popup_calendar_selected(cal, date) {
    cal.sel.value = date;
    if (cal.dateClicked) {
      popup_calendar_close(cal);
    }
  }
  var el = document.getElementById(id);
  var cal = new Calendar(1, null, popup_calendar_selected, popup_calendar_close);
  cal.weekNumbers = false;
  cal.showsOtherMonths = true;
  cal.setRange(1900, 2070);        // min/max year allowed.
  cal.create();
  cal.setDateFormat('%Y-%m-%d');    // set the specified date format
  cal.parseDate(el.value);      // try to parse the text in field
  cal.sel = el;                 // inform it what input field we use
  cal.showAtElement(el.nextSibling, "Br");        // show the calendar
  return false;
}

function cal_goto(int_val) {
  var obj_mm, obj_yyyy, M;
  obj_form =	geid('form');
  obj_mm =	geid('MM');
  obj_yyyy =	geid('YYYY');
  var M =	parseFloat(obj_mm.value);
  switch(int_val) {
    case -120:
      obj_yyyy.value = parseInt(obj_yyyy.value)-10;
    break;
    case -12:
      obj_yyyy.value = parseInt(obj_yyyy.value)-1;
    break;
    case -1:
      M=M-1;
      if (M < 1) {
        M = 12;
        obj_yyyy.value = parseInt(obj_yyyy.value)-1;
      }
    break;
    case 1:
      M=M+1;
      if (M > 12) {
        M = 1;
        obj_yyyy.value = parseInt(obj_yyyy.value)+1;
      }
    break;
    case 12:
      obj_yyyy.value = parseInt(obj_yyyy.value)+1;
    break;
    case 120:
      obj_yyyy.value = parseInt(obj_yyyy.value)+10;
    break;
  }
  obj_mm.value = (M.length==1 ? "0"+M : ""+M);
  obj_form.submit();
}

function calendar_large_setup() {
  var i, id, id_arr;
  id_arr = ['cal_control_last_year','cal_control_last_month','cal_control_today','cal_control_next_month','cal_control_next_year'];
  for (i=0; i<id_arr.length; i++){
    calendar_large_setup_button(id_arr[i]);
  }
}
function calendar_large_setup_button(id){
  addEvent(geid(id), "mouseover", function(e){ geid(id).className='cal_control_over';}); 
  addEvent(geid(id), "mousedown", function(e){ geid(id).className='cal_control_down';}); 
  addEvent(geid(id), "mouseout",  function(e){ geid(id).className='cal_control';}); 
}
function calendar_large_set(operation) {
  var MM = parseFloat(geid_val('MM'));
  switch (operation){
    case "last_year":
      geid_set('YYYY',parseFloat(geid_val('YYYY'))-1);
    break;
    case "last_month":
      if (MM==1){
        geid_set('MM','12');
        geid_set('YYYY',parseFloat(geid_val('YYYY'))-1);
      }
      else {
        geid_set('MM',parseFloat(geid_val('MM'))-1);
      }
    break;
    case "today":
      var today = new Date();
      geid_set('DD',lead_zero(today.getDate().toString(),2));
      geid_set('MM',lead_zero((today.getMonth()+1).toString(),2));
      geid_set('YYYY',today.getFullYear());
    break;
    case "next_month":
      if (MM==12){
        geid_set('MM','01');
        geid_set('YYYY',parseFloat(geid_val('YYYY'))+1);
      }
      else {
        geid_set('MM',parseFloat(geid_val('MM'))+1);
      }
    break;
    case "next_year":
      geid_set('YYYY',parseFloat(geid_val('YYYY'))+1);
    break;
  }
  geid('form').submit()
}

function flowplayer_popup(page,ID){
  popWin(base_url+page+'?ID='+ID,'video_player_'+ID,'location=0,status=0,scrollbars=0,resizable=1',470,385,1);
}

function flowplayer_video(div,title,thumbnail,video_id,video,preroll_id,preroll,trigger_category,trigger_person){
  var site = window.location.protocol+'//'+window.location.host+'/';
  var playlist = [];
  if (thumbnail) {
    playlist.push({ url: site+thumbnail, autoPlay: true });
  }
  if (typeof preroll!="undefined" && preroll!='') {
    playlist.push({
      url: site+preroll,
      autoPlay: false,
      title: 'Preroll',
      onBeforeSeek:
        function(clip){
          return false;
        },
      onBeforeFinish:
        function(clip){
          new Ajax.Request(
            document.location.pathname, {
              method:
                'post',
              parameters:
                'player_event=preroll_finished&ID='+encodeURIComponent(video_id)+'&prerollID='+encodeURIComponent(preroll_id)
               +(typeof trigger_category!="undefined" && trigger_category!='' ? '&category='+encodeURIComponent(trigger_category) : '')
               +(typeof trigger_person!="undefined" && trigger_person!='' ? '&personID='+encodeURIComponent(trigger_person) : '')
            }
          );
        }
    })
    playlist.push({url: site+video, autoPlay: true, title: title});
  }
  else {
    playlist.push({url: site+video, autoPlay: false, title: title});
  }
  flowplayer(
    div,
    { src: site+'flowplayer-3.1.5.swf', wmode: 'opaque' },
    {
      plugins: { apache_pseudostream: {url:site+'flowplayer.pseudostreaming-3.1.3.swf'}},
      clip:    { baseUrl:site+'uploads/processed',  provider: 'apache_pseudostream' },
      playlist: playlist
    }
  );
  flowplayer(div).load();
  return false;
}


