
/*---- onload and unload ----*/

var app_w_url = "";
var onload_handlers = [];
var unload_handlers = [];

function handle_unload() {
  foreach (unload_handlers, function (handler) {
    handler();
  });
}

function handle_onload () {
  foreach (onload_handlers, function (handler) {
    handler ();
  });
  warn('finished onload');
}

function later (thunk) {
  setTimeout (thunk, 0);
}

/*---- warnings ----*/

var user_agent = navigator.userAgent.toLowerCase();
var firefox = user_agent.match (/firefox/);
var ie = navigator.appName == "Microsoft Internet Explorer" ? true : false; 
var once = true;

function alert_once(msg) {
  if (once) {
    alert(msg);
  }
  once = false;
}

function console_warn (msg) {
  if (typeof console != 'undefined') {
    try {
      console.warn (msg);
    }
    catch (e) {}
  }
}

function console_time(str) {
  if (typeof console != 'undefined') {
    try { console.time(str);}
    catch (e) {}
  }
}
function console_timeEnd(str) {
  if (typeof console != 'undefined') {
    try { console.timeEnd(str); }
    catch (e) {}
  }
}
var warn = firefox ? console_warn : function () {};
var starttime = firefox ? console_time : function () {};
var stoptime = firefox ? console_timeEnd : function () {};

function image_swap( elt, newimage ) {
  elt.src = app_w_url + "/images/" + newimage;
}


/*---- list utils ----*/

function foreach (array, consumer) {
  for (var i = 0, j = array.length; i < j; i++) {
    consumer (array[i]);
  }
}

function foreachi (array, consumer) {
  for (var i = 0, j = array.length; i < j; i++) {
    consumer (i, array[i]);
  }
}

function array_append () {
  var out = [];
  for (var i = 0, j = arguments.length; i < j; i++) {
    var a = arguments[i];
    out = out.concat (a);
  }
  return out;
}

function array_map (array, f) {
  var out = [];
  for (var i = 0, j = array.length; i < j; i++) {
    out.push (f (array[i]));
  }
  return out;
}

function array_filter_map (array, f) {
  var out = [];
  for (var i = 0, j = array.length; i < j; i++) {
    var val = f (array[i]);
    if (val)
      out.push (val);
  }
  return out;
}

function or_map (array, f) {
  for (var i = 0, j = array.length; i < j; i++) {
    if (f (array[i])) {
      return true;
    }
  }
  return false;
}
function array_index_of (a, elt) {
  if (firefox) {
    return a.indexOf(elt);
  }
  else {
    for (var i = 0, j = a.length; i < j; i++) {
      if (a[i] == elt) return i;
    }
    return false;
  }  
}  

function array_remove (a, elt) {
  // the ELT is looked for using strict equality (===)
  var i = array_index_of(a, elt);
  if (i >= 0) {
    a.splice (i, 1);
    return true;
  }
  return false;
}

function array_difference (a, b, eq) {
  var out = [];
  for (var i = 0, j = a.length; i < j; i++) {
    var elt = a[i];
    if (!array_member (b, elt, eq))
      out.push (elt);
  }
  return out;
}

function array_member (a, elt, eq) {
  if (!eq) {
    eq = function (x, y) { return x === y };
  }
  for (var i = 0, j = a.length; i < j; i++) {
    if (eq (a[i], elt))
      return true;
  }
  return false;
}

function array_swap (a, i, j) {
  var tmp = a[i];
  a[i] = a[j];
  a[j] = tmp;
}

function array_move_up (a, elt) {
  var i = array_index_of(a, elt);
  if (i >= 0) {
    if (i > 0) {
      array_swap (a, i, i - 1);
    }
  }
}

function array_move_down (a, elt) {
  var i = array_index_of(a, elt);
  if (i >= 0) {
    if (i < a.length - 1) {
      array_swap (a, i, i + 1);
    }
  }
}

        
/*---- objects as hashes ----*/

function hash_keys (o) {
  var keys = [];
  for (p in o) { keys.push (p); }
  return keys;
}

function hash_contains (h, key) {
  return h.hasOwnProperty (key);
}

function hash_values (o) {
  var values = [];
  for (p in o) { values.push (o[p]); }
  return values;
}


function elt_byid_maybe (idname) {
  return document.getElementById (idname);
}

function elt_byid (idname) {
  var elt = elt_byid_maybe (idname);
  if (!elt) {
    throw new Error ("no document element with id '" + idname + "'");
  }
  return elt;
}

// toggle the visibility of an elt
// TODO: ADD OPTIONAL ARGUMENT TO CHANGE LINK INNERHTML
function hide (idname) {
  hide_elt (elt_byid(idname));
}
function show (idname) {
  show_elt (elt_byid(idname));
}

function show_elt (e) {
  e.style.display = "";
}
function hide_elt (e) {
  e.style.display = "none";
}

function showhide (idname) {
  var elt = elt_byid_maybe (idname);
  if (elt) {
    var disp = (elt.style.display == "") ? "none" : "";
    elt.style.display = disp;

    // if theres a triangle image, toggle it
    var tri_id = idname + "_tri";
    var tri_elt = elt_byid_maybe (tri_id);
    if (tri_elt) {
      var tri_url = app_w_url + "/images/";
      tri_elt.src = (disp == "") ? (tri_url + "triDown.png") : (tri_url + "tri.png");
    }
  }
}

function show_many(idarray) {
  foreach( idarray, function (id) { show(id); })
}
function showhide_many(idarray) {
  foreach( idarray, function (id) { showhide(id); })
}

function toggle_text(elt, txt1, txt2) {
  warn(elt.firstChild.nodeValue);
  elt.firstChild.nodeValue = (elt.firstChild.nodeValue == txt1) ? txt2 : txt1;
  setTimeout( function () {set_focus("uber");}, 100);
}

/*---- on* stuff ----*/
function select_onclick(thiss, test_str, todo) {
  /* really innerHTML? */
  if ((thiss[thiss.selectedIndex].innerHTML) == test_str) {
    todo();
  }  
}

/*---- dom handlers ----*/

// store handlers here, and call them from the closures
// returned by make_pendant
var dom_handlers = [];

// make a function that will invoke the _i_th dom handler
// (called a "pendant" because you will hang it on the dom tree)
function make_pendant (i) {
  // the only data referred to by this closure should be _i_
  // and the global object
  return function () {
    return (dom_handlers ? dom_handlers[i].apply (this, arguments) : null);
  }
}

// make all pendants do nothing; this should also remove their
// links to the dom
function clear_dom_handlers () {
  dom_handlers = null;
  warn ("cleared dom handlers");
}

// make an "indirect" (cleanup-able) dom handler
function dom_handler_indirect (h) {
  var i = dom_handlers.length;
  dom_handlers.push (h);

  return make_pendant (i);
}

// make a "direct" (normal, non-cleanup-able) dom handler
function dom_handler_direct (h) {
  return h;
}

// choose how you want "dom_handler" to behave
var dom_handler = dom_handler_indirect;

unload_handlers.push (clear_dom_handlers);


/*---- dom node constructors ---*/

function make_text (str) {
  return document.createTextNode (str);
}

var text = make_text;  // deprecated

function make_elt (tagname, classname) {
  var elt = document.createElement (tagname);
  if (classname) {
    elt.className = classname;
  }
  for (var i = 2, iLim = arguments.length; i < iLim; i++) {
    var child = arguments[i];
    if (child) {
      if (is_array (child))
        foreach (child, function (ch) { elt.appendChild (ch) })
      else
        elt.appendChild (child)
    }
  }
  return elt;
}

function is_array (o) {
  return (typeof o == 'object' && o.constructor === Array);
}

function make_handler_link (classname, contents, handler) {
  var a = make_elt ("a", classname, contents);
  a.href = "#";
  a.onclick = dom_handler (function () { handler (); return false });
  return a;
}

function make_handler_img (classname, src, ro_src, handler) {
  var img = make_elt ("img", classname, null);
  img.src = app_w_url + "/images/" + src;
  if (ro_src) {
    add_event( img, "mouseover", function () { image_swap( img, ro_src) } );
    add_event( img, "mouseout", function () { image_swap( img, src) } );
  }
  img.onclick = dom_handler (function () { handler (); return false });
  img.style.cursor = "pointer";
  return img;
}

function make_opt (value, body, selected) {
  var e = make_elt ("option", null, make_text (body));
  e.value = value;
  if (selected)
    e.selected = true;
  return e;
}

/*---- should be built in ----*/

var months = new Array(
  'January','February','March','April','May',
  'June','July','August','September','October',
  'November','December');

/*---- preload images ----*/

var images = [];
var img_objects = [];

function preload_images() {
  //warn('preloading ' + images.length + ' images:');
  for (var i = 0, j = images.length; i < j; i++) {
    img_objects[i] = new Image();
    img_objects[i].src = images[i];
    //warn('loaded ' + images[i]);
  }
}
onload_handlers.push(preload_images);

/*---- IE IS SUCH BULLSHIT ----*/
// doesnt support addEventListener

function add_event( elt, evt, func ) {
  if (window.addEventListener) { 
    elt.addEventListener(evt, dom_handler(func), false);
  } 
  else { 
    elt.attachEvent("on" + evt, dom_handler( func)); 
  }
}

/*---- lang ----*/

function negate (pred) {
  return function (val) {
    return !pred(val);
  }
}

function identity (x) {
  return x;
}

/*--- onkeypress ---*/
// test to see if enter key was pressed

function enter_pressed(e) { 
  var chr = ie ? window.event.keyCode : e.which;
  if (chr == 13) {
    return true;
  } 
  else { 
    return false;
  }
}

/*---- prettier way to set focus ----*/

var default_focus = "uber";
function set_focus(tofocus) { 
  if (!tofocus) {
    tofocus = default_focus;
  }
  var tf = elt_byid_maybe(tofocus);
  if (tf) tf.focus();
}
onload_handlers.push(set_focus);

/*---- popup ----*/

function pop( url, windowname, rest ) {
  window.open(url,windowname,rest);
}

