<!--
var superDebug = false;
// document.writeln("<script language=\"JavaScript\" src=\"Clone.js\"></script>");

  function BeefySelect(list) {
    if(typeof(list.beefyBethods) == "undefined" || typeof(list.beefyProps) == "undefined") {
      list.beefyMethods = new Array();

      list.beefyMethods["load_options"] = BeefySelect_load_options;
      list.load_options = BeefySelect_load_options;
      list.beefyMethods["copy_options"] = BeefySelect_copy_options;
      list.copy_options = BeefySelect_copy_options;
      list.beefyMethods["clear_options"] = BeefySelect_clear_options;
      list.clear_options = BeefySelect_clear_options;

      list.beefyMethods["add_select_var"] = BeefySelect_add_select_var;
      list.add_select_var = BeefySelect_add_select_var;
      list.beefyMethods["get_select_var"] = BeefySelect_get_select_var;
      list.get_select_var = BeefySelect_get_select_var;
      list.beefyMethods["set_select_var"] = BeefySelect_set_select_var;
      list.set_select_var = BeefySelect_set_select_var;
      list.beefyMethods["drop_select_var"] = BeefySelect_drop_select_var;
      list.drop_select_var = BeefySelect_drop_select_var;

      list.beefyMethods["add_opset_var"] = BeefySelect_add_opset_var;
      list.add_opset_var = BeefySelect_add_opset_var;
      list.beefyMethods["get_opset_var"] = BeefySelect_get_opset_var;
      list.get_opset_var = BeefySelect_get_opset_var;
      list.beefyMethods["set_opset_var"] = BeefySelect_set_opset_var;
      list.set_opset_var = BeefySelect_set_opset_var;
      list.beefyMethods["drop_opset_var"] = BeefySelect_drop_opset_var;
      list.drop_opset_var = BeefySelect_drop_opset_var;

      list.beefyMethods["add_option_var"] = BeefySelect_add_option_var;
      list.add_option_var = BeefySelect_add_option_var;
      list.beefyMethods["get_option_var"] = BeefySelect_get_option_var;
      list.get_option_var = BeefySelect_get_option_var;
      list.beefyMethods["set_option_var"] = BeefySelect_set_option_var;
      list.set_option_var = BeefySelect_set_option_var;
      list.beefyMethods["drop_option_var"] = BeefySelect_drop_option_var;
      list.drop_option_var = BeefySelect_drop_option_var;

      list.beefyMethods["add_opset"] = BeefySelect_add_opset;
      list.add_opset = BeefySelect_add_opset;
      list.beefyMethods["get_opset"] = BeefySelect_get_opset;
      list.get_opset = BeefySelect_get_opset;
      list.beefyMethods["drop_opset"] = BeefySelect_drop_opset;
      list.drop_opset = BeefySelect_drop_opset;
      list.beefyMethods["list_opsets"] = BeefySelect_list_opsets;
      list.list_opsets = BeefySelect_list_opsets;
      list.beefyMethods["activate_opset"] = BeefySelect_activate_opset;
      list.activate_opset = BeefySelect_activate_opset;

      list.beefyMethods["add_option"] = BeefySelect_add_option;
      list.add_option = BeefySelect_add_option;
      list.beefyMethods["get_option"] = BeefySelect_get_option;
      list.get_option = BeefySelect_get_option;
      list.beefyMethods["set_option"] = BeefySelect_set_option;
      list.set_option = BeefySelect_set_option;
      list.beefyMethods["move_option"] = BeefySelect_move_option;
      list.move_option = BeefySelect_move_option;
      list.beefyMethods["select_option"] = BeefySelect_select_option;
      list.select_option = BeefySelect_select_option;
      list.beefyMethods["drop_option"] = BeefySelect_drop_option;
      list.drop_option = BeefySelect_drop_option;
      list.beefyMethods["copy_option"] = BeefySelect_copy_option;
      list.copy_option = BeefySelect_copy_option;

      list.beefyMethods["add_dependant"] = BeefySelect_add_dependant;
      list.add_dependant = BeefySelect_add_dependant;
      list.beefyMethods["get_dependant"] = BeefySelect_get_dependant;
      list.get_dependant = BeefySelect_get_dependant;
      list.beefyMethods["drop_dependant"] = BeefySelect_drop_dependant;
      list.drop_dependant = BeefySelect_drop_dependant;

      list.beefyMethods["value_search"] = BeefySelect_value_search;
      list.value_search = BeefySelect_value_search;
      list.beefyMethods["text_search"] = BeefySelect_text_search;
      list.text_search = BeefySelect_text_search;
      list.beefyMethods["value_regsearch"] = BeefySelect_value_search;
      list.value_regsearch = BeefySelect_value_search;
      list.beefyMethods["text_regsearch"] = BeefySelect_text_search;
      list.text_regsearch = BeefySelect_text_search;

      list.beefyMethods["schematic"] = schematic;
      list.schematic = schematic;

//      for (var i in list.beefyMethods) {
//        eval("list." + i + " = " + list.beefyMethods[i]);
//      }

      BeefyOptionSet(list.options);

      list.beefyProps = new Array();
      list.beefyProps["option_sets"] = [list.options];
      list.beefyProps["active_option_set"] = 0;
      list.beefyProps["dependants"] = [];
    }
  }

  function BeefyOptionSet(list) {
    if(typeof(list.beefyProps) == "undefined") {
      for(var i = 0; i < list.length; i++) {
        BeefyOption(list[i])
      }

      // properties
      if(!list.beefyProps) {
        list.beefyProps = new Array();
      }
    }
  }

  function BeefyOption(opt) {
    if(typeof(opt.beefyProps) == "undefined") {
      opt.beefyProps = new Array();
      opt.beefyProps["dependants"] = new Array();
    }
  }

  function BeefyOption_copy(opt) {
    if(!opt) return null;
    var newOption = new Option(opt.text, opt.value);
    BeefyOption(newOption);

    for(var j in opt.beefyProps)
      if(typeof(opt.beefyProps[j]) == "object")
        newOption.beefyProps[j] = new Clone(opt.beefyProps[j]);
      else
        newOption.beefyProps[j] = opt.beefyProps[j];

    return newOption;
  }

  function schematic() {
    var output = "BeefySelect " + this.name + " {\n";
    output += "    selectedIndex: " + this.selectedIndex + "\n";
    for(var sel_prop in this.beefyProps) {
      if(sel_prop == "option_sets") {
        output += "    option_sets:\n";
        for(var opset in this.beefyProps[sel_prop]) {
          output += "        opset[" + opset + "]:\n";
          for(var opt = 0; opt < this.beefyProps[sel_prop][opset].length; opt++) {
            output += "            option[" + opt + "] (";
            output += this.beefyProps[sel_prop][opset][opt].text + ", " + this.beefyProps[sel_prop][opset][opt].value + "):\n";
            for(var opt_prop in this.beefyProps[sel_prop][opset][opt].beefyProps) {
              if(opt_prop == "dependants") {
                output += "                dependants:\n";
                for(var dep in this.beefyProps[sel_prop][opset][opt].beefyProps[opt_prop]) {
                  output += "                    " + dep + ": " + this.beefyProps[sel_prop][opset][opt].beefyProps[opt_prop][dep] + "\n";
                }
              }
              else {
                output += "                " + opt_prop + ": " + this.beefyProps[sel_prop][opset][opt].beefyProps[opt_prop] + "\n";
              }
            }
          }
        }
      }
      else if(sel_prop == "dependants") {
        output += "    dependants:\n";
        for(var dep in this.beefyProps[sel_prop]) {
          output += "        " + dep + ": " + this.beefyProps[sel_prop][dep] + "\n";
        }
      }
      else {
        output += "    " + sel_prop + ": " + this.beefyProps[sel_prop] + "\n";
      }
    }
    return output + "}";
  }

  function BeefySelect_load_options(list, opset) {
    var option_sets = this.get_select_var("option_sets");
    if(typeof(opset) == "undefined")
      opset = this.get_select_var("active_option_set");
    if(superDebug) alert("loading options into opset " + opset + " of " + this.name + "\n\n" + this.schematic());

    if(typeof(option_sets[opset]) == "undefined")
      return;

    var sel_dependants = this.get_select_var("dependants");
    for(var i = 0; i < option_sets[opset].length; i++) {
      var op_dependants = this.get_option_var("dependants", i, opset)
      for(var j in sel_dependants)
        dependants[j].clear_options(op_dependants[j]);
      option_sets[opset][i] = null;
    }
    for(var i = 0; list && i < list.length; i++) {
      option_sets[opset][i] = list[i];
      BeefyOption(option_sets[opset][i]);
    }
    if(superDebug) alert("options loaded into " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_copy_options(opset) {
    opset = this.get_opset(opset);
    if(opset) {
      var newOptions = new Array();

      for(var i = 0; i < opset.length; i++) {
        var oldOption = opset[i];
        var newOption = new Option(oldOption.text, oldOption.value);
        BeefyOption(newOption);

        for(var j in oldOption.beefyProps)
          if(typeof(oldOption.beefyProps[j]) == "object")
            newOption.beefyProps[j] = new Clone(oldOption.beefyProps[j]);
          else
            newOption.beefyProps[j] = oldOption.beefyProps[j];

        newOptions[i] = newOption;
      }

      return newOptions;
    }
  }

  function BeefySelect_clear_options(opset) {
    if(superDebug) alert("clearing options from opset " + opset + " of " + this.name + "\n\n" + this.schematic());
    this.load_options([], opset);
    if(superDebug) alert("options cleared from " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_add_select_var(key, value) {
    if(typeof(this.beefyProps[key]) != "undefined") return;
    this.beefyProps[key] = value;
  }

  function BeefySelect_get_select_var(key) {
    return this.beefyProps[key];
  }

  function BeefySelect_set_select_var(key, value) {
    if(typeof(this.beefyProps[key]) == "undefined") return;
    this.beefyProps[key] = value;
  }

  function BeefySelect_drop_select_var(key) {
    if(typeof(this.beefyProps[key]) != "undefined") return;
    delete this.beefyProps[key];
  }

  function BeefySelect_add_opset_var(key, value, opset) {
    opset = this.get_opset(opset);
    if(opset) {
      if(typeof(option_sets[opset].beefyProps[key]) != "undefined") return;
      opset.beefyProps[key] = value;
    }
  }

  function BeefySelect_get_opset_var(key, opset) {
    opset = this.get_opset(opset);
    if(opset)
      return opset.beefyProps[key];
  }

  function BeefySelect_set_opset_var(key, value, opset) {
    opset = this.get_opset(opset);
    if(opset) {
      if(typeof(opset.beefyProps[key]) == "undefined") return;
      opset.beefyProps[key] = value;
    }
  }

  function BeefySelect_drop_opset_var(key, opset) {
    opset = this.get_opset(opset);
    if(opset)
      delete opset.beefyProps[key];
  }

  function BeefySelect_list_opsets() {
    var opsets = this.get_select_var("option_sets");
    var oplist = [];
    for(var i in opsets)
      if(i != "beefyProps")
        oplist[i] = opsets[i];
    return oplist;
  }

  function BeefySelect_add_option_var(key, value, option, opset) {
    option = this.get_option(option, opset)
    if(option) {
      if(typeof(option.beefyProps[key]) != "undefined") return;
      option.beefyProps[key] = value;
    }
  }

  function BeefySelect_get_option_var(key, option, opset) {
    option = this.get_option(option, opset);
    if(option)
      return option.beefyProps[key];
  }

  function BeefySelect_set_option_var(key, value, option, opset) {
    option = this.get_option(option, opset)
    if(option) {
      if(typeof(option.beefyProps[key]) == "undefined") return;
      option.beefyProps[key] = value;
    }
  }

  function BeefySelect_drop_option_var(key, option, opset) {
    option = this.get_option(option, opset)
    if(option)
      delete option.beefyProps[key];
  }

  function BeefySelect_add_opset(list, key) {
    if(superDebug) alert("adding option set to " + this.name + "\n\n" + this.schematic());
    var option_sets = this.get_select_var("option_sets");
    if(typeof(option_sets[key]) != "undefined") return;
    if(typeof(key) == "undefined") key = option_sets.length;

    option_sets[key] = [];
    BeefyOptionSet(option_sets[key]);
    this.load_options(list, key);

    if(superDebug) alert("option set added to " + this.name + "\n\n" + this.schematic());
    return key;
  }

  function BeefySelect_get_opset(key) {
    var option_sets = this.get_select_var("option_sets");
    if(typeof(key) == "undefined")
      key = this.get_select_var("active_option_set");

    return option_sets[key];
  }

  function BeefySelect_drop_opset(key) {
    if(superDebug) alert("dropping option set " + key + " from " + this.name + "\n\n" + this.schematic());
    var option_sets = this.get_select_var("option_sets");
    if(typeof(key) == "undefined")
      key = this.get_select_var("active_option_set");

    if(key == null) return;

    var option_sets = this.get_select_var("option_sets");
    var sel_dependants = this.get_select_var("dependants");

    for(var i = option_sets[key].length - 1; i >= 0; i--) {
      var op_dependants = this.get_option_var("dependants", i, key)
      for(var j in sel_dependants)
        sel_dependants[j].drop_opset(op_dependants[j]);
      option_sets[key][i] = null;
    }

    delete option_sets[key];
    this.set_select_var("active_option_set", null)
    if(superDebug) alert("option set dropped from " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_activate_opset(key) {
    if(superDebug) alert("activating option set " + key + " in " + this.name + "\n\n" + this.schematic());
    var option_sets = this.get_select_var("option_sets");
    var active_opset = this.get_select_var("active_option_set");

    if(key == null && active_opset != null) {
      option_sets[active_opset] = this.copy_options(active_opset);

      while(this.options.length)
        this.options[0] = null;

      this.set_select_var("active_option_set", key);
      this.select_option(0);
    }
    else if(typeof(option_sets[key]) != "undefined") {
      if(active_opset != null)
        option_sets[active_opset] = this.copy_options(active_opset);

      while(this.options.length)
        this.options[0] = null;
      for(var i = 0; i < option_sets[key].length; i++)
        this.options[i] = BeefyOption_copy(option_sets[key][i]);

      option_sets[key] = this.options;
      this.set_select_var("active_option_set", key);
      this.select_option(0);
    }
    if(superDebug) alert("option set activated in " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_add_option(text, value, index, opset) {
    if(superDebug) alert("adding option to opset " + opset + " of " + this.name + "\n\n" + this.schematic());
    opset = this.get_opset(opset);
    if(opset) {
      if(index < 0 || index > opset.length || typeof(index) == "undefined")
        if(typeof(opset.selectedIndex) == "number" && opset.selectedIndex > -1)
          index = opset.selectedIndex;
        else
          index = opset.length;

      for(var i = opset.length; i >= index; i--) {
        opset[i] = i == index ? new Option(text, value) : BeefyOption_copy(opset[i - 1]);}
      BeefyOption(opset[index]);

      var dependants = this.get_select_var("dependants");
      for(var i in dependants) {
        var key = dependants[i].add_opset();
        opset[index].beefyProps ["dependants"][i] = key;
      }

      if(typeof(this.selectedIndex) == "number")
        this.select_option(index);
    }
    if(superDebug) alert("option added to " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_get_option(option, opset) {
    opset = this.get_opset(opset);

    if(opset) {
      if(typeof(option) == "undefined")
        if(typeof(opset.selectedIndex) == "number")
          if(opset.selectedIndex >= 0)
            option = opset.selectedIndex;
          else
            return;
        else
          return

      return opset[option];
    }
  }

  function BeefySelect_set_option(text, value, option, opset) {
    option = this.get_option(option, opset)
    if(option) {
      option.text = text;
      option.value = value;
    }
  }

  function BeefySelect_move_option(n, option, opset) {
    opset = this.get_opset(opset);
    if(opset) {
      if(typeof(option) == "undefined")
        if(typeof(opset.selectedIndex) == "number" && opset.selectedIndex > -1)
          option = opset.selectedIndex;
        else
          return;

      if(option >= 0 && option < opset.length &&
         option + n >= 0 && option + n < opset.length &&
         n != 0)
      {
        var op = BeefyOption_copy(opset[option]);
        opset[option] = BeefyOption_copy(opset[option + n]);
        opset[option + n] = op;

        if(typeof(opset.selectedIndex) == "number")
          opset.selectedIndex = option + n;
      }
    }
  }

  function BeefySelect_select_option(n) {
    if(superDebug) alert("selecting option " + n + " in " + this.name + "\n\n" + this.schematic());
    var opset = this.get_opset();
    if(!opset) {
      this.selectedIndex = -1;

      var dependants = this.get_select_var("dependants");
      for(var i in dependants) {
        dependants[i].activate_opset(null)
      }
    }
    else if(n >= 0 && n < opset.length) {
      opset.selectedIndex = n;

      var dependants = this.get_select_var("dependants");
      for(var i in dependants) {
        dependants[i].activate_opset(this.get_option_var("dependants", n)[i])
      }
    }
    else if(n == 0 && (opset.length == 0 || this.get_select_var("active_option_set") == null)) {
      opset.selectedIndex = -1;

      var dependants = this.get_select_var("dependants");
      for(var i in dependants) {
        dependants[i].activate_opset(null)
      }
    }
    if(superDebug) alert("option selected in " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_drop_option(option, opset) {
    if(superDebug) alert("dropping option " + option + " from opset " + opset + " of " + this.name + "\n\n" + this.schematic());
    opset = this.get_opset(opset);
    if(opset) {
      if(typeof(option) == "undefined")
        if(typeof(opset.selectedIndex) == "number" && opset.selectedIndex > -1)
          option = opset.selectedIndex;
        else
          return;

      var savedSelectedIndex = opset.selectedIndex;

      var sel_dependants = this.get_select_var("dependants");
      var op_dependants = opset[option].beefyProps["dependants"];
      for(var j in sel_dependants)
        sel_dependants[j].drop_opset(op_dependants[j]);

      for(var i = option; i < opset.length; i++)
        opset[i] = BeefyOption_copy(opset[i + 1]);

      if(typeof(opset.selectedIndex) == "number") {
        this.select_option(savedSelectedIndex);
        if(savedSelectedIndex == option)
          this.select_option(option >= opset.length ? opset.length - 1 : option);
      }
    }
    if(superDebug) alert("option dropped from " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_copy_option(option, opset) {
    if(superDebug) alert("copying option " + option + " from opset " + opset + " of " + this.name + "\n\n" + this.schematic());
    option = this.get_option(option, opset)
    if(option) {
      var newOption = new Option(option.text, option.value);
      BeefyOption(newOption);

      for(var j in option.beefyProps)
        if(typeof(option.beefyProps[j]) == "object")
          newOption.beefyProps[j] = new Clone(option.beefyProps[j]);
        else
          newOption.beefyProps[j] = option.beefyProps[j];

      return newOption;
    }
  }

  function BeefySelect_add_dependant(select, key) {
    if(superDebug) alert("adding dependant to " + this.name + "\n\n" + this.schematic());
    var dependants = this.get_select_var("dependants");
    if(typeof(dependants[key]) != "undefined") return;
    if(typeof(key) == "undefined") key = dependants.length;
    dependants[key] = select;

    var opsets = dependants[key].list_opsets();
    for(var i in opsets)
      dependants[key].drop_opset(i);

    opsets = this.list_opsets();
    for(var i in opsets) {
      for(var j = 0; j < opsets[i].length; j++) {
        var opset_key = dependants[key].add_opset();
        this.get_option_var("dependants", j, i)[key] = opset_key;
      }
    }

    if(this.get_option_var("dependants"))
      select.activate_opset(this.get_option_var("dependants")[key]);

    if(superDebug) alert("dependant added to " + this.name + "\n\n" + this.schematic());
    return key;
  }

  function BeefySelect_get_dependant(key) {
    var dependants = this.get_select_var("dependants");
    return dependants[key];
  }

  function BeefySelect_drop_dependant(key) {
    if(superDebug) alert("dropping dependant " + key + " from " + this.name + "\n\n" + this.schematic());
    var dependants = this.get_select_var("dependants");
    if(typeof(dependants[key]) == "undefined") return;
    if(typeof(key) == "undefined") return;

    var opsets = dependants[key].list_opsets();
    for(var i in opsets)
      dependants[key].drop_opset(i);

    opsets = this.list_opsets();
    for(var i in opsets) {
      for(var j = 0; j < opsets[i].length; j++){
        var dep = this.get_option_var("dependants", j, i);
        delete dep[i];
      }
    }

    var new_opset = dependants[key].add_opset();
    dependants[key].activate_opset(new_opset);
    delete dependants[key];
    if(superDebug) alert("dependant dropped from " + this.name + "\n\n" + this.schematic());
  }

  function BeefySelect_value_search(value, opset) {
    opset = this.get_opset(opset);
    if(opset)
      for(var i = 0; i < opset.length; i++)
        if(opset[i].value == value)
          return i;
  }

  function BeefySelect_text_search(text, opset) {
    opset = this.get_opset(opset);
    if(opset)
      for(var i = 0; i < opset.length; i++)
        if(opset[i].text == text)
          return i;
  }

  function BeefySelect_prop_search(prop, text, opset) {
    opset = this.get_opset(opset);
    if(opset)
      for(var i = 0; i < opset.length; i++)
        if(this.get_option_var(prop, i, arguments[2]) == text)
          return i;
  }

  function BeefySelect_value_regsearch(value, opset) {
    opset = this.get_opset(opset);
    if(opset)
      for(var i = 0; i < opset.length; i++)
        if(new String(opset[i].value).search(value) != -1)
          return i;
  }

  function BeefySelect_text_regsearch(text, opset) {
    opset = this.get_opset(opset);
    if(opset)
      for(var i = 0; i < opset.length; i++)
        if(new String(opset[i].text).search(text) != -1)
          return i;
  }

  function BeefySelect_prop_regsearch(prop, text, opset) {
    opset = this.get_opset(opset);
    if(opset)
      for(var i = 0; i < opset.length; i++)
        if(new String(this.get_option_var(prop, i, arguments[2])).search(text) != -1)
          return i;
  }

//-->
