function Combos(sep) {
   if (!sep) {
      sep = '|';
   }
   this.sep = sep;
   this.combos = new Array();
   this.add = comboAdd;
   this.clear = comboClear;
   this.init = comboInit;
   this.hidden = comboHidden;
   this.remove = comboRemove;
   this.reset = comboReset;
   this.search = comboSearch;
   this.toggle = comboToggle;
}

function comboAdd(sform, source, tform, target, hidden) {
   // init combo
   this.init(sform, source, tform, target);

   var sf = document.forms[sform];
   var sfield = eval('sf.'+source);
   var tf = document.forms[tform];
   var tfield = eval('tf.'+target);
   var remove = new Array();
   var c = tfield.options.length;
   for (var i=0;i < sfield.options.length;i++) {
      if (sfield.options[i].selected) {
         tfield.options[c] = new Option(sfield.options[i].text,
                                        sfield.options[i].value);
         c++;
         this.toggle(sform, source,
                     sfield.options[i].text, sfield.options[i].value, 2);
      }
   }
   this.reset(sform, source);
   this.hidden(tform, target, hidden);
}

function comboClear(query, sform, source, tform, target) {
   var sf = document.forms[sform];
   var qfield = eval('sf.'+query);
   qfield.value = '';
   this.search(query, sform, source, tform, target);
}

function comboHidden(form, target, hidden) {
   var tf = document.forms[form];
   var tfield = eval('tf.'+target);
   var hfield = eval('tf.'+hidden);
   hfield.value = '';
   for (var i=0;i < tfield.options.length;i++) {
      if (hfield.value != '') {
         hfield.value += this.sep;
      }
      hfield.value += tfield.options[i].value;
   }
}

function comboInit(sform, source, tform, target) {
   var key = sform + '_' + source;
   if (this.combos[key]) {
      return;
   }
   this.combos[key] = new Array();
   var sf = document.forms[sform];
   var sfield = eval('sf.'+source);
   var tf = document.forms[tform];
   var tfield = eval('tf.'+target);
   for (var i=0;i < sfield.options.length;i++) {
      this.combos[key][i] = new Combo(sfield.options[i].text,
                                      sfield.options[i].value,
                                      0);
   }
   var k = sfield.options.length;
   for (var i=0;i < tfield.options.length;i++) {
      this.combos[key][i+k] = new Combo(tfield.options[i].text,
                                        tfield.options[i].value,
                                        2);
   }
}

function comboRemove(sform, source, tform, target, hidden) {
   // init combo
   this.init(sform, source, tform, target);

   var sf = document.forms[sform];
   var sfield = eval('sf.'+source);
   var tf = document.forms[tform];
   var tfield = eval('tf.'+target);
   var del = new Array();
   for (var i=0;i < tfield.options.length;i++) {
      if (tfield.options[i].selected) {
         del.push(i);
         this.toggle(sform, source,
                     tfield.options[i].text, tfield.options[i].value, 0);
      }
   }
   var c = 0;
   for (var i=0;i < del.length;i++) {
      tfield.options[del[i]-c] = null;
      c++;
   }
   this.reset(sform, source);
   this.hidden(tform, target, hidden);
}

function comboReset(form, source) {
   var key = form + '_' + source;
   var combo = this.combos[key];
   var sf = document.forms[form];
   var sfield = eval('sf.'+source);
   sfield.options.length = 0;
   var c = 0;
   for (var i=0;i < combo.length;i++) {
      if (combo[i].deleted == 0) {
         sfield.options[c] = new Option(combo[i].text, combo[i].value);
         c++;
      }
   }
}

function comboSearch(query, sform, source, tform, target) {
   // init combo
   this.init(sform, source, tform, target);

   // search for matching entries
   var sf = document.forms[sform];
   var qfield = eval('sf.'+query);
   var q = qfield.value.toLowerCase();
   var l = q.length;
   var d = new Array();
   var key = sform + '_' + source;
   var combo = this.combos[key];
   var a = 0;
   for (var i=0;i < combo.length;i++) {
      if (combo[i].deleted < 2) {
         var s = combo[i].text.substring(0, l).toLowerCase();
         combo[i].deleted = 0;
         if (s != q) {
            combo[i].deleted = 1;
         }
      }
   }

   // reset combo
   this.reset(sform, source);
}

function comboToggle(form, source, t, v, d) {
   var key = form + '_' + source;
   var combo = this.combos[key];
   for (var i=0;i < combo.length;i++) {
      if (combo[i].text == t && combo[i].value == v) {
         combo[i].deleted = d;
      }
   }
}

function Combo(text, value, deleted) {
   this.text = text;
   this.value = value;
   this.deleted = deleted;
}
