/* Copyright Eventful, Inc. All rights reserved except where otherwise noted. */
if (typeof window.JS == "undefined") var JS = {};
JS.defineGlobal = function(sVar, xVal)
{
    if (xVal === undefined)
    {
        xVal = {};
    }
    if (typeof window[sVar] == "undefined")
    {
        window[sVar] = xVal;
        return xVal;
    }
    return window[sVar];
}

JS.defineGlobal("Eventful");
JS.defineGlobal("DOM");
JS.defineGlobal("CSS");
Eventful.Autoclose = {};

/* no-op console functions for non-Firebug browsers */
var nop = function() { return true; };
Eventful._console = {error:nop, info:nop, debug:nop, warn:nop, log:nop};
Eventful.console = Eventful._console;
if (window.console && window.console.firebug)
{
  Eventful.console = window.console;
}
/* end no-op console functions */

Eventful.helpWindow = function(elLink)
{
    return window.open(elLink.href, elLink.target,
        'width=300,height=350,resizable=1,scrollbars=1');
}

Eventful.showLargeImage = function(elLink, nWidth, nHeight)
{
    // make sure we have numbers
    nWidth = (nWidth * 1) || 300;
    nHeight = (nHeight * 1) || 300;

    // open the window and inject HTML
    var elWin = window.open('', elLink.target,
        'width='+ nWidth +',height='+ nHeight +
        ',resizable=1,scrollbars=1');
    if (elWin)
    {
        elWin.document.open("text/html");
        elWin.document.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML'+
        ' 4.01//EN"\n   "http://www.w3.org/TR/html4/strict.dtd">\n' +
        '<html><head>\n<title>Eventful Image Viewer</title>'+
        '<style type="text/css">\n' +
        'html,body{margin:0; padding:0; overflow:hidden; width:100%;' +
        'height:100%;}\n' +
        'img,div{margin:0;padding:0;}\n' +
        'p{margin:0;padding:0.5em;text-align:center;}\n' +
        '</style><body><div><img src="'+ elLink.href +'" alt="Full image" ' +
        'title="Click to close" onclick="self.close()" />' +
        '</div></body></html>');
        elWin.document.close();

        return true;
    }
    return false;
}

/* Begin Progress Stuff */
Eventful.showProgress = function(idEl, sMsg)
{
  var elParent = DOM.get(idEl);
  var elProgress = document.createElement("div");
  elProgress.className = "eventful-progress";

  var elImg = document.createElement("img");
  elImg.src = "/images/throbber.gif";
  elProgress.appendChild(elImg);

  var elProgressText = document.createElement("span");
  elProgress.appendChild(elProgressText);

  elParent.appendChild(elProgress);
  elProgressText.innerHTML = sMsg;

  return true;
}

Eventful.hideProgress = function(idEl)
{
  var elProgress = DOM.getByClass("div", "eventful-progress", DOM.get(idEl))[0];
  elProgress.parentNode.removeChild(elProgress);
}
/* End Progress Stuff */

/* Box Architecture */
Eventful.Boxes = {
  _store: {}
};

Eventful.Boxes.add = function(idBox)
{
  // if we've already added the box, just reload it
  if (Eventful.Boxes._store[idBox])
  {
    Eventful.Boxes.load(idBox);
  }
  // else we're adding a new box
  else
  {
    // remember that we added this box
    Eventful.Boxes._store[idBox] = true;

    // if the page has already loaded, just load the box
    if (Events.pageLoaded == true)
    {
      Eventful.Boxes.load(idBox);
    }
    // else this is before the page has loaded, so queue the load
    else
    {
      Events.addHandler(window, "load", function()
      {
        Eventful.Boxes.load(idBox);
      });
    }
  }
}

Eventful.Boxes.load = function(idBox, sMsgLoading)
{
  var elBox = DOM.get(idBox);
  var elPlaceholder = DOM.get("insert-"+ idBox);
  var idBoxCore = idBox.replace(/^box-(.*?)(-\d+)?$/, "$1");

  // if we have a place to put the box
  if (elBox || elPlaceholder)
  {
    // load the box HTML
    Net.get({
      url: "/boxes/"+ idBoxCore,
      vars: {time: new Date().getTime()},
      onsuccess: Eventful.Boxes._getLoadHandler(idBox),
      onerror: Eventful.Boxes._getErrorHandler(idBox)
    });
  }
  // else we can't deal with this box
  else
  {
    Eventful.console.warn("Eventful.Boxes.load: No box with id: "+ idBox);
  }
  return true;
}

Eventful.Boxes.remove = function(idBox)
{
  // replace the box with a placeholder element
  var sHTML = '<div id="insert-'+ idBox +'" class="box-placeholder"></div>';
  Eventful.Boxes._replace(idBox, sHTML);
  return true;
}

// Private Box Methods
Eventful.Boxes._replace = function(idBox, htmlContent)
{
  var elBoxOld = DOM.get(idBox) || DOM.get("insert-"+ idBox);

  if (elBoxOld)
  {
    var elNew = document.createElement("div");
    elNew.innerHTML = htmlContent;
    elBoxOld.parentNode.replaceChild(elNew.firstChild, elBoxOld);
    elNew = null;
  }
  else
  {
    Eventful.console.error("No box to use!");
  }
  return true;
}

Eventful.Boxes._getLoadHandler = function(idBox)
{
  return function(R)
  {
    Eventful.Boxes._replace(idBox, R.responseText);
    return true;
  }
}

Eventful.Boxes._getErrorHandler = function(idBox)
{
  return function(sType, R)
  {
    var sHTML = '<div id="error-'+ idBox +'" class="box-error">'+
      'Error loading ('+ sType +'). '+
      '<span onclick="Eventful.Boxes.load(\''+ idBox +'\')"'+
        ' class="fakelink">Retry?</span>'+
      '</div>';
    var elBox = DOM.get(idBox);
    var elPlaceholder = DOM.get("insert-"+ idBox);

    // use the box if it's there, otherwise the placeholder
    var elToUse = elBox || elPlaceholder || null;
    if (elToUse)
    {
      // show the error to the user
      elToUse.innerHTML = sHTML;
    }
    else
    {
      Eventful.console.warn("Eventful.Boxes [error]: No box to put error in.");
    }
  }
}

/* End Box Architecture */

/** Events - bfults@gmail.com - 2006-09-22                                   **
 ** Code licensed under Creative Commons Attribution-ShareAlike License      **
 ** http://creativecommons.org/licenses/by-sa/2.5/                           **/
var Events = {};
Events.pageLoaded = false;
Events.eventStack = [];
Events.unloadStack = [];
Events.loadStack = [];
Events.addHandler = function(xEl, sEvt, fnCB)
{
  var Events = window.Events;
  var bCap = false;
  if (xEl == window)
  {
    if (sEvt == "load")
    {
      if (!Events.pageLoaded) Events.loadStack.push(fnCB);
      else fnCB();
      return true;
    }
    else if (sEvt == "unload")
    {
      Events.unloadStack.push(fnCB);
      return true;
    }
  }

  Events.eventStack.push([!Events.pageLoaded, xEl, sEvt, fnCB, bCap]);

  if (Events.pageLoaded)
  {
    return Events._xbEventAddHandler(xEl, sEvt, fnCB, bCap);
  }
  return true;
}
Events.removeHandler = function(xEl, sEvt, fnCB)
{
  var Events = window.Events;
  var oEl = (typeof (xEl) == "string") ? document.getElementById(xEl) : xEl;
  var bCap = false;
  for (var i=0, el=null; i < Events.eventStack.length; i++)
  {
    el = Events.eventStack[i];
    if (el[1] == oEl && el[2] == sEvt && el[3] == fnCB && el[4] == bCap)
    {
      Events.eventStack.splice(i, 1);
      return _xbEventRemoveHandler(oEl, sEvt, fnCB, bCap);
    }
  }
  return false;
}
Events.getTargetElement = function(evt)
{
  if (!evt && window.event) evt = window.event;
  if (!evt) return null;
  return evt.target || evt.srcElement;
}
Events.stopPropagation = function(evt)
{
  if (!evt && window.event) evt = window.event;
  if (!evt) return false;
  if (evt.stopPropagation) evt.stopPropagation();
  evt.cancelBubble = true;
  return true;
}
Events.preventDefault = function(evt)
{
  if (!evt && window.event) evt = window.event;
  if (!evt) return false;
  if (evt.preventDefault) evt.preventDefault();
  evt.returnValue = false;
  return true;
}
// Private Functions
Events._setup = function()
{
  var Events = window.Events;
  var el = null;
  Events.pageLoaded = true;

  try
  {
    if (Events.loadStack && Events.loadStack.length)
    {
      for (var i = Events.loadStack.length - 1; i >= 0; i--)
      {
        if (typeof Events.loadStack[i] == "function") Events.loadStack[i]();
        delete Events.loadStack[i];
      }
    }
  } catch(e) {
    Eventful.console.error("%1.o", e);
  }

  try
  {
    if (Events.eventStack && Events.eventStack.length)
    {
      for (i=0; i < Events.eventStack.length; i++)
      {
        el = Events.eventStack[i];
        if (el[0] == true)
        Events._xbEventAddHandler(el[1], el[2], el[3], el[4]);
      }
    }
  } catch(e) {}
  return true;
}
Events._cleanup = function()
{
  var Events = window.Events;
  var el = null;
  try
  {
    if (Events.unloadStack && Events.unloadStack.length)
    {
      while (el = Events.unloadStack.pop())
      {
        if (typeof el == "function") el();
      }
    }
    if (Events.eventStack && Events.eventStack.length)
    {
      while (el = Events.eventStack.pop())
      Events._xbEventRemoveHandler(el[1], el[2], el[3], el[4]);
    }
    for (var i in Events) delete Events[i];
    delete window.Events;
  } catch (e) {}
  return true;
}
Events._xbEventRemoveHandler = function(oEl, sEvt, fnCB, bCap)
{
  if (oEl)
  {
    if (!bCap) bCap = false;
    if (oEl.removeEventListener)
    {
      oEl.removeEventListener(sEvt, fnCB, bCap);
      return true;
    }
    else if (oEl.detachEvent)
    {
      return oEl.detachEvent("on"+ sEvt, fnCB);
    }
  }
  return false;
}
Events._xbEventAddHandler = function(xEl, sEvt, fnCB, bCap)
{
  var oEl = (typeof (xEl) == "string") ? document.getElementById(xEl) : xEl;
  if (xEl === window && sEvt == "load")
  {
    // KHTML / WebKit
    if (/KHTML/i.test(navigator.userAgent))
    {
      window._load_timer = setInterval(function() {
        if (/loaded|complete/.test(document.readyState)) {
          clearInterval(window._load_timer);
          fnCB();
        }
      }, 10);
      return true;
    }
    // Gecko
    else if (document.addEventListener)
    {
      document.addEventListener("DOMContentLoaded", fnCB, false);
      return true;
    }
    else
    {
      // IE
      /*@cc_on @*/
      /*@if (@_win32)
      document.write("<script id='__ie_onload' defer src='javascript:void(0)'><\/script>");
      var ie_script = document.getElementById("__ie_onload");
      ie_script.onreadystatechange = function() {
        if (this.readyState == "complete") {
          fnCB();
        }
      };
      return true;
      /*@end @*/
    }
  }
  if (oEl)
  {
    if (!bCap) bCap = false;
    if (oEl.addEventListener)
    {
      oEl.addEventListener(sEvt, fnCB, bCap);
      return true;
    }
    else if (oEl.attachEvent)
    {
      return oEl.attachEvent("on"+ sEvt, fnCB);
    }
  }
  return false;
}
Events._xbEventAddHandler(window, "load", Events._setup, false);
Events._xbEventAddHandler(window, "unload", Events._cleanup, false);
/* End Events */

/** DOM Class Manipulation - bfults@gmail.com - 2006-04-17                   **
 ** Code licensed under Creative Commons Attribution-ShareAlike License      **
 ** http://creativecommons.org/licenses/by-sa/2.5/                           **/
CSS.hasClass = function (el, sClass)
{
  if (el && el.className !== undefined)
  {
    return new RegExp("(^|\\s+)"+sClass+"(\\s+|$)").test(el.className);
  }

  return false;
}
CSS.addClass = function (el, sClass)
{
  if (el && el.className !== undefined)
  {
    CSS.remClass(el, sClass);
    el.className += ((el.className.length > 0) ? " " : '')+ sClass;
    return true;
  }

  return false;
}
CSS.remClass = function (el, sClass)
{
  if (el && el.className !== undefined)
  {
    el.className = el.className.replace(
      new RegExp("^"+sClass+"$|^"+sClass+"\\s+|\\s+"+sClass+
      "(?=\\s|$)",'g'), '');
    return true;
  }

  return false;
}
/* End DOM Class Manipulation */

/** Eventful.Autoclose **/
Eventful.Autoclose.num_elements = 0;
Eventful.Autoclose.element_id = null;

// Called on all clicks (which are inside the body) to close autoclose element
Eventful.Autoclose.body_click = function(evt)
{
  if (evt)
  {
    var elTarget = Events.getTargetElement(evt);
    if (elTarget)
    {
      // if we're clicking on an autoclose or autoclose-click element
      if (CSS.hasClass(elTarget, "autoclose") ||
        CSS.hasClass(elTarget, "autoclose-click") ||
        DOM.findAncestor(elTarget, {className: "autoclose"}))
      {
        // bail out early before closing the block
        return true;
      }
    }
  }
  Eventful.Autoclose.close_block();
  return true;
}

// Called to close the current autoclose block
Eventful.Autoclose.close_block = function()
{
  var id = Eventful.Autoclose.element_id;
  if (id && id.length)
  {
    var elAutoclose = document.getElementById(id);
    if (elAutoclose)
    {
      elAutoclose.style.display = 'none';
      Eventful.Autoclose.element_id = null;
    }
  }
  return true;
}

Events.addHandler(window, "load", function() {
    if (window.Eventful && Eventful.Autoclose && Eventful.Autoclose.body_click)
    {
        Events.addHandler(document.body, "click",
            Eventful.Autoclose.body_click);
    }
});

// Called when the *click* elements are clicked to show the autoclose elements
Eventful.Autoclose.set_id = function(idEl)
{
  // if we're setting a new id, close an old block (if it's open)
  Eventful.Autoclose.close_block();
  Eventful.Autoclose.element_id = idEl;
  return true;
}
/** End Eventful.Autoclose **/

/** DOM.findAncestor(elChild, {att: val[, att2: val2]})
 ** If elChild has an ancestor with specified attributes attn with values valn
 ** Return the ancestor element (or null if none found)
 **/
DOM.findAncestor = function(elChild, hAtts)
{
  var el = elChild, att = '', bMatch = true, ct = 0;
  if (elChild && hAtts)
  {
    // traverse upward as long as the parentNode is valid
    while(el = el.parentNode)
    {
      bMatch = true;

      // for each specified attribute
      ct = 0;
      for (att in hAtts)
      {
        if (el[att] !== undefined)
        {
          switch (att)
          {
            case 'className':
            bMatch = (CSS.hasClass(el, hAtts[att]));
            break;

            default:
            bMatch = (el[att] == hAtts[att]);
          }
          ct++;
        }
      }

      // this el has passed all tests, return it!
      if (ct > 0 && bMatch)
      {
        return el;
      }
    }
  }
  return null;
}


/** DOM.get(idOrEl, idOrEl2, idOrEl3, ...) -- getElement(s)ById
 ** Returns DOM elements based on their string IDs.
 ** Will return a single element given a single argument, otherwise an array.
 ** Originally from Sam Stephenson <sam@conio.net>. Much better now.
 **/
DOM.get = function()
{
  var els = [], el = null;
  for (var i = 0; i < arguments.length; i++)
  {
    el = arguments[i];
    if (typeof el == "string")
    {
      el = document.getElementById(el);
    }
    if (arguments.length == 1)
    {
      return el;
    }
    els[els.length] = el;
  }
  return els;
}
$ = DOM.get;

/** DOM.getByClass(sTagName, sClassName[, elRoot]) -- getElementsByClassName
 ** Returns all elements of a given tag name (* for all) with the given class
 ** name, optionally restricted to the subtree of a specific element, elRoot.
 **/
DOM.getByClass = function(sTagName, sClassName, elRoot)
{
  var elsMatch = [];
  var elsAll = $tag(sTagName, elRoot);

  try {
    for (var i=0; i < elsAll.length; i++)
    {
        if (CSS.hasClass(elsAll[i], sClassName))
        {
          elsMatch[elsMatch.length] = elsAll[i];
        }
    }
  }
  catch (e) {}
  return elsMatch;
}
getElementsByClass = getElementsByClassName = $class = DOM.getByClass;

/** DOM.getByTag(sTagName[, elRoot]) -- getElementsByTagName
 ** Returns all elements of a given tag name (* for all) , optionally restricted
 ** to the subtree of a specific element, elRoot.
 **/
DOM.getByTag = function(sTagName, elRoot)
{
  if (!elRoot)
  {
    elRoot = document;
  }

  return elRoot.getElementsByTagName(sTagName);
}
$tag = DOM.getByTag;

/** Array.arrayize(el1[, el2, ...])
 ** Returns a single array containing all elements within arguments or the
 ** argument itself if it is not iterable.
 ** Note: it only "collapses" one level of arrays.
 **/
Array.arrayize = function()
{
    if (arguments.length > 0)
    {
        var aRet = [], cur, j=0;
        for (var i=0; i < arguments.length; i++)
        {
            if (arguments[i] !== undefined)
            {
                cur = arguments[i];
                // custom objects with toArray()
                if (cur.toArray)
                {
                    aRet = aRet.concat(cur.toArray());
                }
                // arrays
                else if (cur instanceof Array)
                {
                    aRet = aRet.concat(cur);
                }
                // other iterables
                else if (typeof cur != "string" && cur.length !== undefined)
                {
                    for (j=0; j < cur.length; j++)
                    {
                        aRet.push(cur[j]);
                    }
                }
                // non-iterables
                else
                {
                    aRet.push(cur);
                }
            }
        }
        return aRet;
    }
    return [];
}
$A = Array.arrayize;


Eventful.Cats = {};
/* Eventful.Cats.addCount
 *
 * Handles setting category count for a single category.
 */
Eventful.Cats.addCount = function(elem)
{
  // append a count_only=1 to the url
  var url = elem.href + ((/\?/.test(elem.href)) ? '&' : '?') + "count_only=1";
  Net.get({url: url, onsuccess: Eventful.Cats.getInsertCount(elem)});
}

/* Eventful.Cats.getInsertCount
 *
 * Returns a callback handler for the URL request.  Stuffs the returned
 * count into the DOM after the <a> we started with, formatted like this:
 *   " (23)".
 */
Eventful.Cats.getInsertCount = function(elem)
{
  return function(R)
  {
    if (R)
    {
      // we need a number
      var text  = R.responseText;
      if (/^\d+$/.test(text))
      {
        elem.parentNode.appendChild(document.createTextNode(" (" + text + ")"));
      }
    }
  }
}

/******************************************************************************/
function toggle_all_enabled_checkboxes() {
  Eventful.console.warn("FIXME: Refactor, rename, modularize. [toggle_all_enabled_checkboxes()]");
  var main = document.getElementById('check_all');
  var new_val = main.checked;
  var inputs = document.getElementsByTagName('input');
  for (i=0; i<inputs.length; i++) {
    if (inputs[i].type == 'checkbox' && !inputs[i].disabled && inputs[i] != main) {
      inputs[i].checked = new_val;
    }
  }

  var text = document.getElementById('check_all_text');
  if (new_val) {
    text.innerHTML = "Uncheck all";
  } else {
    text.innerHTML = "Check all";
  }
}

/* height_adjust
 *
 * Used with the "grow" arrows in new_event and elsewhere.
 */
function height_adjust(item, size) {
  Eventful.console.warn("FIXME: Refactor, rename, modularize. [height_adjust()]")
  var elem = document.getElementById(item);
  if(!elem.style.height) {
    elem.style.height = elem.offsetHeight+'px';
  }
  var height = parseInt(elem.style.height.substr(0,
    elem.style.height.length-2));
  height += size;
  elem.style.height = height+'px';
}

/* set_focus
 *
 * Given a form name and an element name, sets the focus on the
 * element.
 */
function set_focus(fname,ename) {
  Eventful.console.warn("FIXME: Refactor, rename, modularize. [set_focus()]");
  if(fname && ename && document.forms[fname] && document.forms[fname].elements[ename]) {
    var element = document.forms[fname].elements[ename];
    if(element != null) {
      element.focus();
      element.select();
    }
  }
}

/* toggle_visibility
 *
 * Given an item ID, toggles the visibility of the item.  If an
 * optional select_item ID is given, after making item visible,
 * the input focus is sent to select_item.
 * Returns the new display state of the element.
 */
function toggle_visibility(item,select_item)
{
  Eventful.console.warn("FIXME: Refactor, rename, modularize. [toggle_visibility()]");
  var theItem = document.getElementById(item);
  if (theItem && theItem != undefined)
  {
    if(theItem.style.display == "block")
    {
      theItem.style.display = "none";
    }
    else
    {
      theItem.style.display = "block";
      if(select_item)
      {
        var selectItem = document.getElementById(select_item);
        selectItem.focus();
        selectItem.select();
      }
    }
  }
}

/* toggle_exclusive_visibility
 *
 * Works like toggle_visibilty, except it can be used where only one
 * of two possibilities should be visible at any one time.  You can use
 * this to switch between one of the following three states:
 *   Item A is visible
 *   Item B is visible
 *   Item A and B are invisible
 * If you wish to have only the first two states, see swap_visibility().
 */
function toggle_exclusive_visibility(item,noitem,select_item) {
  Eventful.console.warn("FIXME: Refactor, rename, modularize. [toggle_exclusive_visibility()]");
  var theItem = document.getElementById(item);
  var theNoItem = document.getElementById(noitem);
  if (theItem && theItem != undefined) {
    if(theItem.style.display == "block") {
      theItem.style.display = "none";
    } else {
      theItem.style.display = "block";
      if (theNoItem && theNoItem != undefined) theNoItem.style.display = "none";
    }
    if(select_item) {
      var selectItem = document.getElementById(select_item);
      selectItem.focus();
      selectItem.select();
    }
  }
}

/* swap_visibility
 *
 * Swaps the visibility property between two items.  This means that one
 * of the two items (the first one) is always visible.  See
 * toggle_exclusive_visibility if you wish to be able to hide both items.
 *
 * This works by making item1 visible and hiding item2.  It does NOT blindly
 * swap the visibility of the two items.
 */
function swap_visibility(item1,item2,toFocus) {
  Eventful.console.warn("FIXME: Refactor, rename, modularize. [swap_visibility()]");
  var i1 = document.getElementById(item1);
  var i2 = document.getElementById(item2);
  i1.style.display = "block";
  i2.style.display = "none";
  if(toFocus) {
    i3 = document.getElementById(toFocus);
    if (i3) {
      i3.focus();
      i3.select();
    }
  }
}

/* Show
 *
 * Given an item ID, makes the item visible.  If an
 * optional select_item ID is given, after making item visible,
 * the input focus is sent to select_item.
 */
function Show(item,select_item)
{
  var theItem = document.getElementById(item);
  theItem.style.display = "block";
  if(select_item)
  {
    var selectItem = document.getElementById(select_item);
    selectItem.focus();
    selectItem.select();
  }
}

/* Hide
 *
 * Given an item ID, makes the item invisible.  If an
 * optional select_item ID is given, after making item invisible,
 * the input focus is sent to select_item. (hint: don't make the select_item
 * something within the now-hidden item, as it'll be invisible now)
 */
function Hide(item,select_item)
{
  var theItem = document.getElementById(item);
  theItem.style.display = "none";
  if(select_item)
  {
    var selectItem = document.getElementById(select_item);
    selectItem.focus();
    selectItem.select();
  }
}


/* help
 *
 * Encapsulates the popup window behavior necessary to get contextual help
 * that does not interfere with process flow.
 */
function help(topic) {
  Eventful.console.warn("Use of deprecated help() function.");
  var url = "/help/" + topic;
  window.open(url,"EVDB_Help",'width=300,height=350,resizable,scrollbars');
}

/* Function to show the large version of an image on a detail page.
 */
function show_image(url,width,height) {
  Eventful.console.warn("Use of deprecated show_image() function.");
  window.open(url,"image_viewer", 'width='+(width+20)+',height='+(height+20)+',resizeable=1,scrollbars=0');
}


/* addEventToCalendar
 *
 * Add an event to a user's calendar.
 */
function addEventToCalendar(user,calendar,seid,icon_state) {

  /* Change the add image to the "added" version.
   */
  var obj = document.getElementById("b_" + seid);
  obj.src = "/images/" + icon_state + ".gif";

  /* Change the add event popup contents to "Updating..."
   */
  popup = document.getElementById("ap_" + seid);
  popup.innerHTML = "Updating<p />Please wait...";
  Show("ap_" + seid);

  /* Add the event to the calendar.
   */
  var url = "/users/" + user + "/calendars/events/add?calendar_id="
    + calendar + "&event_id=" + seid;
  callbackGET(url, refresh_popup_callback(seid, false));

  /* Get new contents for the add event popup that reflects the new
   * state.
   */
/*
  var url = "/parts/add_groupcal_box_contents.php?id=" + event;
  replaceContentsWithURL("ap_"+event,url);
*/
}

/* removeEventFromCalendar
 *
 * Add an event to a user's calendar.
 */
function removeEventFromCalendar(user,calendar,event,icon_state,refresh_page) {

/*  alert("user: " + user + ", calendar: " + calendar + ", event: " + event);*/

  /* Change the add image to the "not added" version.
   */
  var obj = document.getElementById("b_" + event);
  obj.src = "/images/" + icon_state + ".gif";

  /* Change the add event popup contents to "Updating..."
   */
  popup = document.getElementById("ap_" + event);
  popup.innerHTML = "Updating<p />Please wait...";
  Show("ap_" + event);

  /* Remove the event from the calendar.
   */
  var url = "/users/" + user + "/calendars/events/remove?calendar_id="
    + calendar + "&event_id=" + event;
  callbackGET(url, refresh_popup_callback(event, refresh_page));

  /* Get new contents for the add event popup that reflects the new
   * state.
   */
/*
  var url = "/parts/add_groupcal_box_contents.php?id=" + event;
  replaceContentsWithURL("ap_"+event,url);
*/
}

/* addEventToGroup
 *
 * Add an event to a user's group.
 */
function addEventToGroup(user,group,event,icon_state) {

  /* Change the add image to the "added" version.
   */
  var obj = document.getElementById("b_" + event);
  obj.src = "/images/" + icon_state + ".gif";

  /* Change the add event popup contents to "Updating..."
   */
  popup = document.getElementById("ap_" + event);
  popup.innerHTML = "Updating<p />Please wait...";
  Show("ap_" + event);

  /* Add the event to the group's calendar.
   */
  var url = "/users/" + user + "/groups/events/add?group_id="
    + group + "&event_id=" + event;
  callbackGET(url, refresh_popup_callback(event, false));

  /* Get new contents for the add event popup that reflects the new
   * state.
   */
/*
  var url = "/parts/add_groupcal_box_contents.php?id=" + event;
  replaceContentsWithURL("ap_"+event,url);
*/
}

/* removeEventFromGroup
 *
 * Add an event to a user's group.
 */
function removeEventFromGroup(user,group,event,icon_state,refresh_page) {

  /* Change the add image to the "not added" version.
   */
  var obj = document.getElementById("b_" + event);
  obj.src = "/images/" + icon_state + ".gif";

  /* Change the add event popup contents to "Updating..." */
  popup = document.getElementById("ap_" + event);
  popup.innerHTML = "Updating<p />Please wait...";
  Show("ap_" + event);

  /* Remove the event from the group's calendar.
   */
  var url = "/users/" + user + "/groups/events/remove?group_id="
    + group + "&event_id=" + event;
  callbackGET(url, refresh_popup_callback(event, refresh_page));
}

function refresh_popup_callback(seid,refresh_page) {
  if (refresh_page) {
    return function() {
      window.location.reload();
    }
  } else {
    return function() {
      Hide("ap_" + seid);
      var url = "/parts/add_groupcal_box_contents.php?id=" + seid;
      replaceContentsWithURL("ap_" + seid, url);
      if (document.getElementById('my-eventful-calendar-box')) {
        replaceContentsWithURL('my-eventful-calendar-box', url);
      }
    }
  }
}

/* add_favorite
 *
 * Add an item to a user's list of favorites.
 */
function add_favorite(user, type, item_id, label) {
  var label = label || false;

  if (label) {
    var imFav = document.getElementById("f_"+item_id);
    imFav.src = "/images/star-on.gif";
    replaceContentsWithText('fav_label', "<a href=\"javascript:remove_favorite('" + user + "','" + type + "','" + item_id + "',true)\">Remove from favorites list</a>");
  }
  else {
    var elFav = document.getElementById("f_"+item_id);
    elFav.style.backgroundImage = "url('/images/star-on.gif')";
  }

  // Remove the favorite.
  var url = "/users/" + user + "/favorites/add?item_id=" + item_id +
    "&type=" + type + "&time="+(new Date().valueOf());
  callbackGET(url,refresh_favorite_callback(type, item_id, false, label));
}

/* remove_favorite
 *
 * Remove an item from a user's list of favorites.
 */
function remove_favorite(user, type, item_id, label) {
  var label = label || false;

  if (label) {
    var imFav = document.getElementById("f_"+item_id);
    imFav.src = "/images/star-off.gif";
    replaceContentsWithText('fav_label', "<a href=\"javascript:add_favorite('" + user + "','" + type + "','" + item_id + "',true)\">Add to favorites list</a>");
  }
  else {
    var elFav = document.getElementById("f_"+item_id);
    elFav.style.backgroundImage = "url('/images/star-off.gif')";
  }

  // Remove the favorite.
  var url = "/users/" + user + "/favorites/remove?item_id=" + item_id +
    "&type=" + type + "&time="+(new Date().valueOf());
  callbackGET(url,refresh_favorite_callback(type, item_id, false, label));
}


function refresh_favorite_callback(type, item_id, refresh_page, label) {
  label = label || false;
  return function() {
    var url = "/parts/favorite_contents.php?item_id=" + item_id + "&type=" + type + "&time="+(new Date().valueOf());
    if (label) {
      url += "&label=true";
    }
    replaceContentsWithURL("af_"+item_id, url);
    if(refresh_page) {
      window.location.reload();
    }
  }
}

/* List style favorites */

/* Show the "calendar add" popup. */
function show_calendar_add(event)
{
    var obj = DOM.get("ap_" + event);
    if (obj)
    {
        obj.style.display = "block";
        Eventful.Autoclose.set_id("ap_" + event);
    }
}

function locale_controller(evt) {
}

// The following code is Copyright (C) Simon Willison 2004.
//
// document.getElementsBySelector(selector)
// - returns an array of element objects from the current document
//   matching the CSS selector. Selectors can contain element names,
//   class names and ids and can be nested. For example:
//     elements = document.getElementsBySelect('div#main p a.external')
// Version 0.4 - Simon Willison, March 25th 2003

function getAllChildren(e) {
  // Returns all children of element. Workaround required for IE5/Windows. Ugh.
  return e.all ? e.all : e.getElementsByTagName('*');
}

document.getElementsBySelector = function(selector) {
  Eventful.console.warn("Use of deprecated document.getElementsBySelector() function.");
  // Attempt to fail gracefully in lesser browsers
  if (!this.getElementsByTagName) {
    return new Array();
  }
  // Split selector in to tokens
  var tokens = selector.split(' ');
  var currentContext = new Array(this);
  for (var i = 0; i < tokens.length; i++) {
    token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
    if (token.indexOf('#') > -1) {
      // Token is an ID selector
      var bits = token.split('#');
      var tagName = bits[0];
      var id = bits[1];
      var element = this.getElementById(id);
      if (tagName && element.nodeName.toLowerCase() != tagName) {
        // tag with that ID not found, return false
        return new Array();
      }
      // Set currentContext to contain just this element
      currentContext = new Array(element);
      continue; // Skip to next token
    }
    if (token.indexOf('.') > -1) {
      // Token contains a class selector
      var bits = token.split('.');
      var tagName = bits[0];
      var className = bits[1];
      if (!tagName) {
        tagName = '*';
      }
      // Get elements matching tag, filter them for class selector
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b'))) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      continue; // Skip to next token
    }
    // Code to deal with attribute selectors
    if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) { // "
      var tagName = RegExp.$1;
      var attrName = RegExp.$2;
      var attrOperator = RegExp.$3;
      var attrValue = RegExp.$4;
      if (!tagName) {
        tagName = '*';
      }
      // Grab all of the tagName elements within current context
      var found = new Array;
      var foundCount = 0;
      for (var h = 0; h < currentContext.length; h++) {
        var elements;
        if (tagName == '*') {
            elements = getAllChildren(currentContext[h]);
        } else {
            elements = currentContext[h].getElementsByTagName(tagName);
        }
        for (var j = 0; j < elements.length; j++) {
          found[foundCount++] = elements[j];
        }
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      var checkFunction; // This function will be used to filter the elements
      switch (attrOperator) {
        case '=': // Equality
          checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
          break;
        case '~': // Match one of space seperated words
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b'))); };
          break;
        case '|': // Match start with value followed by optional hyphen
          checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))); };
          break;
        case '^': // Match starts with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0); };
          break;
        case '$': // Match ends with value - fails with "Warning" in Opera 7
          checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length); };
          break;
        case '*': // Match ends with value
          checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1); };
          break;
        default :
          // Just test for existence of attribute
          checkFunction = function(e) { return e.getAttribute(attrName); };
      }
      currentContext = new Array;
      var currentContextIndex = 0;
      for (var k = 0; k < found.length; k++) {
        if (checkFunction(found[k])) {
          currentContext[currentContextIndex++] = found[k];
        }
      }
      // alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
      continue; // Skip to next token
    }

    if (!currentContext[0]){
      return;
    }

    // If we get here, token is JUST an element (not a class or ID selector)
    tagName = token;
    var found = new Array;
    var foundCount = 0;
    for (var h = 0; h < currentContext.length; h++) {
      var elements = currentContext[h].getElementsByTagName(tagName);
      for (var j = 0; j < elements.length; j++) {
        found[foundCount++] = elements[j];
      }
    }
    currentContext = found;
  }
  return currentContext;
}

/* That revolting regular expression explained
/^(\w+)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/
  \---/  \---/\-------------/    \-------/
    |      |         |               |
    |      |         |           The value
    |      |    ~,|,^,$,* or =
    |   Attribute
   Tag
"*/

// END Simon Willison code
/* focus the primary search box if there is one. */
var focusElement = "fhqwgads";

function setInitialFocus() {
  try {
    var e = DOM.get(focusElement);
    if (e && e.focus) {
      e.focus();
    }
  }
  catch (e) {
    return false;
  }
}

Events.addHandler(window, 'load', setInitialFocus);

/*
 * Select a text box (or similar) and move its selection caret to the end
 */
function selectAtEnd(object)
{
    if(object.focus) {
        object.focus();
    }
    if(object.setSelectionRange) {
        object.setSelectionRange(object.value.length, object.value.length);
    }
}
/*
 * Select a text box (or similar) and move its selection caret to the beginning
 */
function selectAtBeginning(object)
{
    if(object.focus) {
        object.focus();
    }
    if(object.setSelectionRange) {
        object.setSelectionRange(0, 0);
    }
}
