
var textbox = function(spec, my) {
   var IDLE    = 0;
   var EDITING = 1;

   // object I'll return
   var that = {};

   var edit_state = IDLE;

   my   = my   || {};
   spec = spec || {};

   spec.max_cols    = spec.max_cols || 50;
   spec.min_cols    = spec.min_cols || 20;
   spec.min_rows    = spec.min_rows || 1;
   spec.max_rows    = spec.max_rows || 20;
   spec.onsave      = spec.onsave       || null;
   spec.oneditstart = spec.oneditstart  || null;
   spec.oneditend   = spec.oneditend    || null;

   var div = document.createElement('DIV');
   var el = document.createElement('TEXTAREA');

   if (spec.float_to) {
      div.style.cssFloat   = spec.float_to;
      div.style.styleFloat = spec.float_to; // IE sucks

      el.style.cssFloat   = spec.float_to;
      el.style.styleFloat = spec.float_to; // IE sucks
   }
   el.className = "text_box";
   div.appendChild(el);

   div.appendChild(document.createElement('BR'));

   // link bar for the save and cancel links - makes show / hide neater
   var link_bar = document.createElement('DIV');
   link_bar.style.display = "none";
   div.appendChild(link_bar);

   // save link
   if (spec.onsave) {
      var save_link = document.createElement('A');
      save_link.setAttribute('href', "javascript:void(0)");
      save_link.appendChild(document.createTextNode("Save"));
      save_link.onclick = function() { 
      // when we save, we let the client decide what to do!
         spec.onsave(that);
      }
      link_bar.appendChild(save_link);
      link_bar.appendChild(document.createTextNode("\u00a0\u00a0"));
   }

   // cancel link
   if (spec.oneditend) {
      var cancel_link = document.createElement('A');
      cancel_link.setAttribute('href', "javascript:void(0)");
      cancel_link.appendChild(document.createTextNode("Cancel"));
      cancel_link.onclick = function() { 
         edit_state = IDLE;
         link_bar.style.display = "none";
         spec.oneditend(that);
      }
      link_bar.appendChild(cancel_link);
      link_bar.appendChild(document.createTextNode("\u00a0\u00a0"));
   }

   // Text tricks link
   var text_tricks_link = document.createElement('A');
   text_tricks_link.setAttribute('href', "javascript:void(0)");
   text_tricks_link.appendChild(document.createTextNode("Formatting Tricks"));
   text_tricks_link.onclick = function() {window.open("/formatting_tricks.php", '_blank', 'toolbar=0,location=0,menubar=0');}

   link_bar.appendChild(text_tricks_link);

   var adjust_size = function() { 
      if (edit_state == IDLE) {
         if (spec.oneditstart) {
            spec.oneditstart(that);
         }
      }
      link_bar.style.display = "inline";
      edit_state = EDITING;
      var str = el.value.replace(/\r/g,'');
      var lines = str.split('\n');
      var line_count = lines.length;
      var col_count = 20;
      var extra_rows = 0;
      for (var i = 0; i < line_count; i++) {
         col_count = Math.max(col_count, lines[i].length);
      // convert to int
         extra_rows += Math.floor(lines[i].length/ spec.max_cols);
      }
      col_count = Math.max(col_count, spec.min_cols);
      el.cols = Math.min(col_count, spec.max_cols);
      el.rows = Math.max(line_count + extra_rows, spec.min_rows);
      if (spec.max_rows) {
         el.rows = Math.min(el.rows, spec.max_rows);
      }
   }

   that.select = function() {
      el.focus();
      adjust_size();
   }

   el.onmousedown = adjust_size;
   el.onkeyup   = adjust_size;
   el.onkeydown = adjust_size;

   that.adjust_size = function() { adjust_size(); }
   that.el        = function()  { return div; }
   that.get_value = function()  { return el.value; }
   that.set_value = function(s) { el.value = s; }
   that.clear     = function()  { 
      edit_state = IDLE;
      el.value = ""; 
      link_bar.style.display = "none";
      spec.oneditend(that);
   }
      

   that.get_line_count = function countLines() { 

/*
    // trim trailing return char if exists 
      var text = el.value;
//      var text = el.value.replace(/\s+$/g,"");
      var split = text.split("\n");
      return split.length;
*/
   } 

   return that;
}

