// Global variable to be used inside of call handlers.
// Note that this mirrors the property in the options object, but is
// here so that it can be used in onChange handlers written
// directly into the element declaration.
var pulldown_call_level = 0;

function popup(url,windowname,width,height,features,doblur) {
  if (window.name == windowname) {
    window.location.href = url;
    window.resizeTo(width, height);
  } else {
    var ix = 0;
    var iy = 0;
    if (screen.width)  // Object guarding - is it supported?
      ix = screen.width/2 - width/2;
    if (screen.height)  // Object guarding - is it supported?
      if (features == "all") {
      	iy = 10  //to account for all the vertical space added by address bar, etc.
      } else {
        iy = screen.height/2 - height/2;
      }
    var strFeatures = "";
    if (typeof(features) == "undefined"){
      strFeatures = ",resizable=1,scrollbars=1,left=" + ix + ",top=" + iy;
    } else if (features == "all"){
      strFeatures = ",resizable=1,scrollbars=1,toolbar=1,menubar=1,location=1,status=1,left=" + ix + ",top=" + iy;
    } else if (features == "none"){
      strFeatures = ",left=" + ix + ",top=" + iy;
    } else {
      strFeatures = "," + features;
    }
    var handle = window.open(url, windowname, 'width=' + width + ',height=' + height + strFeatures);
    if (!handle.opener) handle.opener = self;
    if(doblur){
       handle.blur();
    } else {
       handle.focus();
    }
  }
}

function closeFrameAndGo(URL) {
	if (parent.window.opener){
		parent.window.opener.location=URL;
		parent.window.close();
	} else {
		parent.window.location=URL;
	}
}

function targetparent_and_close(url) {
  self.opener.location.href=url;
  window.close();
}

function doFocus(){
  window.focus();
}

// From: http://tech.irt.org/articles/js016/
function Get_Cookie(name) {
  var start = document.cookie.indexOf(name + '=');
  var len = start + name.length + 1;
  if ((!start) && (name != document.cookie.substring(0,name.length)))
    return null;
  if (start == -1)
    return null;
  var end = document.cookie.indexOf(';',len);
  if (end == -1) end = document.cookie.length;
  return unescape(document.cookie.substring(len,end));
}

//
// Takes the name of a text form element and the name of a pulldown.
// Add actions to both that causes setting the pulldown to set the
// text element, and typing into the text element to scroll through
// the pulldown.
//
function mirror_text_pulldown (text_name, pulldown_name) {

  var text_handler = find_form_element(text_name).onkeyup;
  var pulldown_handler = find_form_element(pulldown_name).onchange;
  var pulldown_rewrite = find_form_element(pulldown_name).on_rewrite;

  // Variables used to communicate data privately between handlers
  var name_index = {};
  var outside_onkeyup = true;

  // Handlers.
  find_form_element(pulldown_name).onchange = function (event, options) {
    if (outside_onkeyup) {
      var selected = find_form_element(pulldown_name).options[find_form_element(pulldown_name).selectedIndex];
      find_form_element(text_name).value = selected.text;
    }
    if (null != pulldown_handler)
      pulldown_handler(event, options);
  };

  find_form_element(pulldown_name).on_rewrite = function (event, options) {
    name_index = {};

    find_form_element(pulldown_name).index_elements(0);
    if (null != pulldown_rewrite)
      pulldown_rewrite(event, options);
  };

  // This is broken out here in chunks of 50 because it
  // massively improves interactivity on IE on Windows.
  // On Mozilla you can run through a few thousand in a
  // fraction of a second but...
  find_form_element(pulldown_name).index_elements = function (i) {
    var limit = i + 50;
    var pulldown_element = find_form_element(pulldown_name);
    if (pulldown_element.options.length < limit)
      limit = pulldown_element.options.length;
    for (var j = i; j < limit; j++) {
      var name = pulldown_element.options[j].text.toLowerCase();
      for (var len = 0; len <= name.length; len++) {
        var substring = name.substr(0, len);
        if (null == name_index[substring])
          name_index[substring] = j;
      }
    }

    // And try to fill in the pulldown if you can right now.
    if (find_form_element(text_name).value.length)
      find_form_element(text_name).onkeyup();

    if (j < pulldown_element.options.length)
      top.setTimeout(
        "find_form_element('" + pulldown_name + "').index_elements(1+" + j + ")",
        0
      );
  }



  find_form_element(text_name).onkeyup = function (event, options) {
    var i = name_index[find_form_element(text_name).value.toLowerCase()];
    if (null != i && find_form_element(pulldown_name).selectedIndex != i) {
      find_form_element(pulldown_name).selectedIndex = i;
      // This strategy is because the onchange handler that I set
      // might not be the current onchange handler!  I don't want
      // the one that I set to do anything because then you get
      // into deep recursion.
      outside_onkeyup = false;
      find_form_element(pulldown_name).onchange(event, options);
      outside_onkeyup = true;
    }
    if (null != text_handler)
      text_handler(event, options);
  };

  // This makes the rewrite run in the background on Windows to speed the
  // page load.

  top.setTimeout("find_form_element('" + pulldown_name + "').on_rewrite()", 5);
}


//
// Takes an anonymous array of names of pulldown elements and
// a nested_options (see "create_option_tree" for a description of
// what that looks like) and then sets appropriate handlers to
// create a cascading set of pulldown menus.  Does NOT handle
// multiple selections.  It does properly wrap any existing
// handlers.  It expects the relevant form elements to already
// exist.
//
function make_pulldown_group (pulldowns, nested_options) {
  var first_pulldown = find_form_element(pulldowns[0]);

  // Populate the first
  var option_tree = create_option_tree(pulldowns.length, nested_options);
  if ("string" == typeof option_tree) {
    alert(option_tree);
    return;
  }
  set_options(first_pulldown, option_tree);

  // Set on change handlers
  for (var i = 1; i < pulldowns.length; i++) {
    set_nested_pulldown_handler(pulldowns[i-1], pulldowns[i]);
  }

  // Make the last call work
  var last_pulldown = find_form_element(pulldowns[pulldowns.length - 1]);
  var last_handler = last_pulldown.onchange;
  last_pulldown.onchange = function (event, options) {
    if (null != last_handler) {
      if (null == options)
        options = {}
      if (null == options.pulldown_call_level)
        options.pulldown_call_level = 0;
      pulldown_call_level = options.pulldown_call_level;
      last_handler(event, options);
      pulldown_call_level = 0;
    }
  };

  // Populate the rest.
  first_pulldown.onchange();
}

// The depth is how many more levels the tree has.
// The tree is just an array of objects as below
//
//   [
//     {
//       value: "foo",
//       text: "bar",     // defaults to value
//       selected: true,  // defaults to false
//       sub_tree: [      // omit on the last level
//         ...
//       ],
//     },
//     { ... },
//     ...
//   ]
//
//
// If the tree is as expected it returns an array of Options
// with the subtrees embedded in the Options.
//
function create_option_tree (depth, nested_options) {
  depth--;
  if ((null == nested_options)
    || (null == nested_options.length)
  ) return("(expected another level)");
  var option_tree = [];
  for (var i = 0; i < nested_options.length; i++) {
    var info = nested_options[i];
    if (null == info)          // Happens on IE from picky commas
      break;

    var value = info["value"];
    if (null == value)
      return("(Option " + i + " is missing the value)");

    var text = info.value;
    if (null == text)
      text = value;

    var selected = info.selected;
    if (null == selected)
      selected = false;
    else if (false == selected)
      selected = false;
    else
      selected = true;


    var this_option = new Option(text, value, selected);
    if (0 < depth) {
      var sub_choices = create_option_tree(depth, info.nested_options);
      if ("string" == typeof sub_choices)
        return("[ " + value + " ]" + sub_choices);
      this_option.sub_tree = sub_choices;
    } else if (null != info.nested_options)
      return("[ " + value + " ](extra depth here)");

    option_tree.push(this_option);
  }
  return option_tree;
}

// Takes the name of a form element.  Searches all forms in the top
// page for form elements named that.  Returns the first form element
// object with that element.
function find_form_element (name) {
  var forms_array = top.document.forms;
  for (var i = 0; i < forms_array.length; ++i)
    if (null != forms_array[i][name])
      return forms_array[i][name];
  alert("Cannot find form with " + name + " in it");
}

//
// Used by make_multiple_pulldown to set the handlers.
// BUG ALERT: It is important the the closure is created in a
//  function!  "Lexical" variables in JavaScript are closed
//  over the scope of the innermost function call, and (unlike
//  in other languages) not over loops etc.
//
function set_nested_pulldown_handler (parent_name, child_name) {
  var parent_handler = find_form_element(parent_name).onchange;
  find_form_element(parent_name).onchange = function (event, options) {
    var parent = find_form_element(parent_name);
    var child = find_form_element(child_name);
    if (null == options)
      options = {};
    if (null == options.pulldown_call_level)
      options.pulldown_call_level = 0;
    if (null != parent_handler) {
      pulldown_call_level = options.pulldown_call_level;
      parent_handler(event, options);
    }
    var sub_tree = [];
    if (0 < parent.options.length) {
      var selection = parent.selectedIndex;
      if (-1 == selection)
        selection = 0;
      sub_tree = parent.options[selection].sub_tree;
    }

    options.pulldown_call_level++;
    pulldown_call_level = options.pulldown_call_level;
    set_options(child, sub_tree, event, options);
    child.onchange(event, options);
    pulldown_call_level = 0;
  };
}

//
// Takes a pulldown element and an array of Option objects.
// Sets the list of pulldowns in the element to that array.
// Yes, we need the actual objects, not names/values.
//
function set_options (form_element, option_list, event, options) {
  var opts = form_element.options;
  opts.length = 0;
  // An IE bug does not set Option.selected if defaultSelected is set,
  // and you cannot set selected directly on the Option (even though
  // JavaScript 1.1 says that you should be able to).  Therefore we have
  // to track both what is selected and what should be selected by
  // default.
  var selected_index = -1;
  var default_selected_index = 0;
  // Known bug causes "floating element bug" on Debian Mozilla
  // only if the pulldown has been used.  Not planning to fix.
  if ((0 == option_list.length))
    form_element.setAttribute("disabled", true);
  else {
    for (var i in option_list) {
      opts[i] = option_list[i];
      if (option_list[i].selected)
        selected_index = i;
      if (option_list[i].defaultSelected)
        default_selected_index = i;
    }
    form_element.removeAttribute("disabled");
    if (-1 == selected_index)
      selected_index = default_selected_index;
    form_element.selectedIndex = selected_index;
    // alert("Setting " + form_element.name + " to entry " + selected_index);
  }
  if (null != form_element.on_rewrite)
    form_element.on_rewrite(event, options);
}

///////////////////////////////////////////////////////////

function jsFFTextFieldFocus(inFFFormName, inFFFieldName, inFFDefaultValue){
  var oField;
  var strFieldValue;

  oField = document.forms[inFFFormName].elements[inFFFieldName];
  strFieldValue = oField.value;

  if (strFieldValue == inFFDefaultValue ){
    oField.value = "";
  }
}

function jsFFTextFieldBlur(inFFFormName, inFFFieldName, inFFDefaultValue){
  var oField;
  var strFieldValue;

  oField = document.forms[inFFFormName].elements[inFFFieldName];
  strFieldValue = oField.value;

  if (strFieldValue == ""){
    oField.value = inFFDefaultValue;
  }
}

