



var fwContextPath = "";



var fwIsNav = false;
var fwIsIE = false;
if (parseInt(navigator.appVersion) >= 4) 
{
    if (navigator.appName == "Netscape") 
    {
      fwIsNav = true;
    }
    else 
    {
      fwIsIE = true;
    }
}


function fw_widgets() {}



function hierbrowser(parent_window, setup_url, callback) {
  // In some cases the calling function may have already put on the callback
  // parameter, so we don't have to add it.  These situations are signified
  // by not passing in the callback param.
  if (typeof callback == "undefined")
  {
    alert("no callback passed in");
    return;
  } 
  else if(typeof callback == "function") 
  {
  } 
  else if(typeof callback == "string")
  {
    callback = new Function("ok","file_name",callback+"(ok, file_name)");
  }
  else
  {
    alert("unhandled type for callback "+(typeof callback));
    return;
  }
  // If the URL already has some parameters on it, we don't want to add
  // another "?" to it.  So, only add the ? if there is not one already.

  var child_window = parent_window.open(setup_url, 
                                      "filebrowser",
                                      "width=480,height=268,resizable=1",
                                      false);
  child_window.opener = parent_window;
  child_window.opener.hierbrowser_callback = callback;
  child_window.focus();
  return child_window;
}



function fwInsertSpinner() 
{
    var min = 0;
    var max = 10;
    var step = 1;
    var title = null;
    var doc = document;
    var name = null;

    var argv = arguments;
    var argc = argv.length;
    for (var i = 0; i < argc; i++) 
    {
        if (i + 1 >= argc) 
        {
            break;
        }

        switch(argv[i].toLowerCase()) 
        {
            case "-document":
                doc = argv[++i];
                break;
            case "-from":
                min = argv[++i];
                break;
            case "-name":
                name = argv[++i];
                break;
            case "-step":
                step = Math.abs(argv[++i]);
                break;
            case "-title":
                title = argv[++i];
                break;
            case "-to":
                max = argv[++i];
                break;
        }
    }

    if (name == null) 
    {
        alert("You must specify a name for the spinner element!");
        return;
    }

    var spinnerHtml = "";

    // Create the spinner name from the input element name. 
    var spinnerName = name.substr(name.lastIndexOf('.') + 1);
    var mapname = spinnerName + "-map";
    var imagename = spinnerName + "-image";

    // Because people tend to click spinners rapidly in succession,
    // the event handlers sees double clicks and things are lost - use
    // onmouseup; of course, NN doesn't support that, use href instead.

    var handler = (fwIsIE ? "onmouseup=\"" :"href=\"javascript:") + name + ".";

    // Insert a <MAP> element that invokes spin() on mouseup.
    var pos = step;
    var neg = step * -1;
    spinnerHtml =  "<MAP NAME=\"" + mapname + "\">\n";
    spinnerHtml += "    <AREA SHAPE=\"RECT\" COORDS=\"0,0,18,10\"  " 
        + handler + "fwSpin(" + name + "," + pos + ")\" >\n";
    spinnerHtml += "    <AREA SHAPE=\"RECT\" COORDS=\"0,12,18,23\" " 
        + handler + "fwSpin(" + name + "," + neg + ")\" >\n";
    spinnerHtml += "</MAP>\n";

    // Insert the <IMG> image element.
    // Netscape form elements have wacky sizes, and our spin controls won't
    // show up centered unless we use the absmiddle.

    spinnerHtml += "<IMG name=\"" + imagename + "\" src=\""
        + fwContextPath + "/base/widget/spinner/images/arrow.gif\" " 
        + "align=absmiddle border=0 width=19 height=24 usemap=\"#" + mapname
        + "\">";
    doc.writeln(spinnerHtml);

    // Add the maxlength, min and max properties to the specified input
    // element. We store min and max in the element itself so validation has
    // access to them.

    eval ("var element = " + name);
    element.min = min;
    element.max = max;
    element.maxlength = Number.toString().length;
    element.fwSpin = fwSpin;

    // Add validate if not already specified.
    // (Page may have its own validation routine for the spinner).

    if (element.validate == null) 
    {
        element.validate = "boundedInt";
    }

    // Add title property if it was specified. This really has nothing
    // to do with spinners, but it is related to validation and it's
    // convenient to let the caller specify in the insertSpinner()
    // call.
    
    if (title != null) 
    {
        element.title = title;
    }

    // Make sure the fwSpin handler exists in the document containing the
    // spinner.  If the spinner is created in the document that sourced this
    // JavaScript file, it will already be there.  But if the spinner is
    // created in another window, we have to put the handler there.

    return;
}



function fwSpin(element, delta) 
{

    // Activate the commit button for this page (unless flagged off).
    
    // Update the value. 

    element.value = parseInt(element.value) + delta;

    // Check for overflow/underflow/bogosity.

    if (element.value > element.max) 
    {
        element.value = element.max;
    }
    else if (element.value < element.min) 
    {
        element.value = element.min;
    }
    else if (isNaN(element.value)) 
    {
        element.value = delta > 0 ? element.min : element.max;
    }

    return;
}



function fwCreateJSConsole(doc)
{
    doc.writeln("<form name=fwJSConsole>");
    doc.writeln("<table border=0>");
    doc.writeln("<tr>");
    doc.writeln("<td><B>JavaScript code:</B></td>");
    doc.writeln("<td align=\"right\">");
    doc.writeln("<b><a href='javascript:fwJSConsoleEval()'>Evaluate</a></b>");
    doc.writeln("</td>");
    doc.writeln("</tr>\n<tr>");
    doc.writeln("<td colspan=2>");
    doc.writeln("<textarea name=code rows=8 cols=60 wrap=off></textarea>");
    doc.writeln("</td>");
    doc.writeln("</tr>");
    doc.writeln("</table>");
    doc.writeln("</form>");
}



function fwJSConsoleEval()
{
    var code = document.forms["fwJSConsole"].elements["code"].value;
    eval(code);
}


fw_widgets.disable_shift_click_hook = function(e) 
{
  if (fwIsNav && (e.modifiers & Event.SHIFT_MASK) && (e.which == 1)) 
  {
    return false;
  } 
  else if (fwIsIE && self.event.shiftKey) 
  {
    return false;
  }
  
  return true;
}


fw_widgets.disable_shift_click = function() 
{
  document.onmousedown = fw_widgets.disable_shift_click_hook;
  document.onclick = fw_widgets.disable_shift_click_hook;
  if (document.layers) 
  {
    window.captureEvents(Event.MOUSEDOWN);
  }
  window.onmousedown = fw_widgets.disable_shift_click_hook;
  window.onclick = fw_widgets.disable_shift_click_hook;
}



fw_widgets.strip_px = function(pos)
{
  return new Number(pos.substring(0, pos.length - 2));
}


fw_widgets.get_scroll_position = function(win)
{
  var win = win || window;
  return ({
    x: (fwIsNav ? win.pageXOffset : win.document.body.scrollLeft),
    y: (fwIsNav ? win.pageYOffset : win.document.body.scrollTop)
  });
}


fw_widgets.set_scroll_position = function(window, scroll_position) 
{
  if (scroll_position.x && scroll_position.y) 
  {
    window.scrollTo(scroll_position.x, scroll_position.y);
  }
}


fw_widgets.get_window_dimensions = function(win)
{
  var win = win || window;
  return ({
    width: (fwIsNav ? win.innerWidth : win.document.body.clientWidth),
    height: (fwIsNav ? win.innerHeight : win.document.body.clientHeight)
  });
}


fw_widgets.get_window_visible_dimensions = function(win)
{
  var win = win || window;
  return ({
    width: (fwIsNav ? win.innerWidth : win.document.body.offsetWidth),
    height: (fwIsNav ? win.innerHeight : win.document.body.offsetHeight)
  });
}


fw_widgets.get_window_visible_rect = function(win)
{
  //for NS clientWidth and clientHeight include some mystery amount, always subtract 14
  //for IE clientWidth and clientHeight don't include scrollbars

  var win = win || window;
  return ({
    left: (fwIsNav ? win.pageXOffset : win.document.body.scrollLeft),
    top: (fwIsNav ? win.pageYOffset : win.document.body.scrollTop),
    right: (fwIsNav ? win.pageXOffset + win.document.body.clientWidth - 14
                    : win.document.body.scrollLeft + win.document.body.clientWidth),
    bottom: (fwIsNav ? win.pageYOffset + win.document.body.clientHeight - 14
                     : win.document.body.scrollTop + win.document.body.clientHeight)
  });
}


fw_widgets.get_window_screen_rect = function(win)
{
  var win = win || window;

  return ({
    left: (fwIsNav ? win.screenX : win.screenLeft),
    top: (fwIsNav ? win.screenY : win.screenTop),
    right: (fwIsNav ? win.screenX + win.innerWidth
                    : win.screenLeft + win.document.body.clientWidth),
    bottom: (fwIsNav ? win.screenY + win.innerHeight
                     : win.screenTop + win.document.body.clientHeight)
  });
}



fw_widgets.get_obj_left = function(el) 
{
    var ol=el.offsetLeft;
    while ((el=el.offsetParent) != null) 
    {
        ol += el.offsetLeft;
    }
    return ol;
}



fw_widgets.get_obj_top = function(el) 
{
    var ot=el.offsetTop;
    while((el = el.offsetParent) != null) 
    {
        ot += el.offsetTop;
    }

    return ot;
}



fw_widgets.get_obj_dimensions = function(obj)
{
  return ({
    width: (fwIsNav ? obj.offsetWidth : obj.offsetWidth),
    height: (fwIsNav ? obj.offsetHeight : obj.offsetHeight)
  });
}



fw_widgets.get_obj_visible_left = function(el) 
{
    var ol = fw_widgets.get_obj_left(el);

    ol-=el.scrollLeft;//don't use offsetParent, it doesn't work in NS
    while ((el=el.parentNode) != null && el.tagName!="BODY")//don't include body scroll, it's accounted for in offset
    {
        ol -= el.scrollLeft;
    }
    return ol;
}



fw_widgets.get_obj_visible_top = function(el) 
{
    var ot = fw_widgets.get_obj_top(el);

    ot-=el.scrollTop;//don't use offsetParent, it doesn't work in NS
    while((el = el.parentNode) != null && el.tagName!="BODY")//don't include body scroll, it's accounted for in offset
    {
        ot -= el.scrollTop;
    }

    return ot;
}



fw_widgets.get_obj_rect = function(obj)
{
  var left = fw_widgets.get_obj_left(obj);
  var top = fw_widgets.get_obj_top(obj);
  var dims = fw_widgets.get_obj_dimensions(obj);

  return ({
    left: left,
    top: top,
    right: left + dims.width,
    bottom: top + dims.height 
  });
}



fw_widgets.do_elements_overlap = function(obj1, obj2)
{
    var     rect1 = fw_widgets.get_obj_rect(obj1);
    var     rect2 = fw_widgets.get_obj_rect(obj2);

    return fw_widgets.do_recs_overlap(rect1, rect2);
}



fw_widgets.do_recs_overlap = function(rect1, rect2)
{
    var     leftIntersect = Math.max(rect1.left, rect2.left);
    var     topIntersect = Math.max(rect1.top, rect2.top);
    var     rightIntersect = Math.min(rect1.right, rect2.right);
    var     bottomIntersect = Math.min(rect1.bottom, rect2.bottom);

    return leftIntersect < rightIntersect && topIntersect < bottomIntersect; 
}


fw_widgets.validate_by_regex = function(obj, regex)
{
    if (obj.value.match(regex)) 
    {
        fw_widgets.set_form_error(obj.name, false);
    }
    else
    {
        fw_widgets.set_form_error(obj.name, true, "value " + obj.value + " doesnt match " + regex);
    }
}


fw_widgets.update_form_element = function(obj, form, elem)
{
    fw_widgets.update_form_element_value(obj.value, form, elem);
}


fw_widgets.update_form_element_value = function(value, form, elem)
{
    // Not using this, seems to think the element exists even though it doesn't
    // var delem = document.forms[form].elements[elem];
    var delem = fw_widgets.get_form_element(document.forms[form], elem);

    if (delem != null) 
    {
        delem.value = value;
    }
    else 
    {
        // Create the form element if it does not exist.
        //alert("creating new hidden element " + elem + "(" + value + ")");
        fw_widgets.add_form_element_by_value( value, form, elem);
    }
}

fw_widgets.get_form_element = function(form, elem) 
{
    for (var i = 0; i < form.elements.length; i++) 
    {
        if (form.elements[i].name == elem) 
        {
            return form.elements[i];
        }
    }
    return null;
}




fw_widgets.does_form_contain_element_value = function(value, form, elem)
{
    var formObj = document.forms[form];

    for (var i = 0; i < formObj.elements.length; i++) 
    {
        if (formObj.elements[i].name == elem && formObj.elements[i].value == value)
        {
            return true;
        }
    }

    return false;
}



fw_widgets.remove_element = function(form, elem)
{
    var formObj = document.forms[form];

    for (var i = formObj.elements.length - 1; i >= 0; i--) 
    {
        var obj = formObj.elements[i];
        if (obj.name == elem)
        {
            if (fwIsIE)
            {
                obj.removeNode(true);
            }
            else
            {
                try {
                    formObj.removeChild(obj); // for elements added to DOM
                } catch (e) {
                    document.body.removeChild(obj); // for elements rendered
                }
            }
        }
    }
}



fw_widgets.remove_element_value = function(value, form, elem)
{
    var formObj = document.forms[form];

    for (var i = 0; i < formObj.elements.length; i++) 
    {
        if (formObj.elements[i].name == elem && formObj.elements[i].value == value)
        {
            formObj.removeChild(formObj.elements[i]);
        }
    }
}



fw_widgets.add_form_element_by_value = function(value, form, elem) 
{
    // Create the form element.
    var mynewelement = document.createElement("INPUT");
    mynewelement.type = "HIDDEN";
    mynewelement.name = elem;
    mynewelement.value = value;
    document.forms[form].appendChild(mynewelement);
}



fw_widgets.add_form_element_by_id = function(value, form, elem) 
{
    // Create the form element.
    var mynewelement = document.createElement("INPUT");
    mynewelement.type = "HIDDEN";
    mynewelement.id = elem;
    mynewelement.value = value;
    document.forms[form].appendChild(mynewelement);
}



fw_widgets.update_element_values = function(obj, form, elem, addAll)
{
    var delem;

    for (var i = 0; i < document.forms[form].elements.length; i++) 
    {
        do 
        {
            delem = document.forms[form].elements[i];
            
            if (delem.name == elem) 
            {
                document.forms[form].removeChild(delem);
                
            }
        }
        while (delem.name == elem && i < document.forms[form].elements.length);
    }

    for (i=0; i < obj.length; i++) 
    {
        var element = obj.options[i];
        if (element.selected || addAll) 
        {
            fw_widgets.add_form_element_by_value( element.value, form, elem);
        }
    }
}


fw_widgets.clear_browser_list = function(form_name, element_name)
{
  var length = document.forms[form_name].elements[element_name].length;

  for (i = 0; i < length; i++)
  {
    document.forms[form_name].elements[element_name].options[i] = null;
  }
}


fw_widgets.add_to_browser_list = function(form_name, element_name, name, value)
{
  document.forms[form_name].elements[element_name].options[document.forms[form_name].elements[element_name].length] = new Option(name, value);
}

fw_widgets.set_form_error = function(name, isError, text) 
{
    var outerDiv = document.getElementById(name + "_bbox");
    var textDiv = document.getElementById(name + "_errorText");

    if (isError) 
    {
        outerDiv.style.background="#ff3333";
        textDiv.innerHTML=text;
    }
    else
    {
        outerDiv.style.background="#ffffff";
        textDiv.innerHTML="";
    }
}


fw_widgets.addEventListener = function(to_object, type, function_pointer)
{
  if (fwIsIE)
  {
    to_object.attachEvent("on" + type, function_pointer);
  }
  else
  {
    if (type != "unload")
    {
      to_object.addEventListener("unload", 
                                 function() { 
                                    to_object.removeEventListener(type, function_pointer, true); 
                                 },
                                 true);
    }
    to_object.addEventListener(type, function_pointer, false);
  }
}

fw_widgets.removeEventListener = function(to_object, type, function_pointer)
{
  if (fwIsIE)
  {
    to_object.detachEvent("on"+type, function_pointer);
  }
  else
  {
    to_object.removeEventListener(type, function_pointer, false);
  }
}


fw_widgets.process_wf = function(wf)
{
    if (!wf)
    {
      return ({
                wf: null,
                doModal: false
              });
    }

    //parse wf string
    var mapOfFeatures = new Array();
    var features = wf.split(',');

    for (var feature in features)
    {
        var x = features[feature].split('=');
        mapOfFeatures[x[0]] = x[1];
    } 

    //check for special features

    //modal
    var doModal = mapOfFeatures["modal"] == "true" || mapOfFeatures["dependent"] == "true" || mapOfFeatures["dependent"] == "yes" || mapOfFeatures["dependent"] == "1";

    //relative positioning
    var relativeLeft = 0;
    var relativeTop = 0;
    var relativeWidth = window.screen.availWidth;
    var relativeHeight = window.screen.availHeight;

    var relativeToWindow = mapOfFeatures["relative"] == "true";

    if (relativeToWindow)
    {
        var winDims = fw_widgets.get_window_screen_rect(top);

        relativeLeft = winDims.left;
        relativeTop = winDims.top;
        relativeWidth = winDims.right - winDims.left;
        relativeHeight = winDims.bottom - winDims.top;
    }

    //center
    if (mapOfFeatures["center"] == "true")
    {
        var width = mapOfFeatures["width"];
        var height = mapOfFeatures["height"];

        mapOfFeatures["left"] = relativeLeft + (relativeWidth - width) / 2;
        mapOfFeatures["top"] = relativeTop + (relativeHeight - height) / 2;
    }
    else
    if (relativeToWindow)
    {
        if (!mapOfFeatures["left"])
        {
            mapOfFeatures["left"] = 0;
        }

        if (!mapOfFeatures["top"])
        {
            mapOfFeatures["top"] = 0;
        }

        mapOfFeatures["left"] = relativeLeft + mapOfFeatures["left"];
        mapOfFeatures["top"] = relativeTop + mapOfFeatures["top"];
    }

    //put together a new string
    features = new Array();
    for (var feature in mapOfFeatures)
    {
        if (feature != "modal" && feature != "center" && feature != "relative")
        {
            features[features.length] = [feature, mapOfFeatures[feature]].join('=');
        }
    }

    wf = features.join(',');

    return ({
            wf: wf,
            doModal: doModal
            });
}


fw_widgets.open_new_window = function(anchor, href, usePost)
{
  //allow overriding the href
  href = href || anchor.href;
  var   wf = anchor.getAttribute("iw_wf");
  return fw_widgets.open_new_window_from_params(href, wf, anchor.target, usePost);
}


fw_widgets.open_new_window_from_form = function(form, wf)
{
    var href = new fw_url_bean( form);
    var target = form.target;
    if ( !target )
        target = "_self";
    var usePost = true;
    if ( form.method == "get" || form.method == "GET" )
        usePost = false;
    return fw_widgets.open_new_window_from_params(href, wf, target, usePost)
}


fw_widgets.open_new_window_from_params = function(href, wf, window_name, usePost)
{
  var   wfProcessed = fw_widgets.process_wf(wf);

  window_name = (window_name == "_blank" 
                     ? (new Date()).getTime().toString() 
                     : window_name);

  wf = wfProcessed.wf

  //if no window attributes are passed in, don't use them, this way
  //the opened window will have the same properties as the current window.

  var result = null;

  if ( usePost )
  {
    if ( typeof href == 'string' )
      href = new fw_url_bean( href);
    result = href.do_post( window_name, wf);
  }
  else
  {
    if ( href.get_url )
      href = href.get_url();
    result = wf ? window.open(href, window_name, wf) : window.open(href, window_name);
  }

  if (wfProcessed.doModal)
  {
    fw_widgets.do_modal(result);
  }

  return result;
}



var fwWinModalWindow = null;

fw_widgets.do_modal = function(win)
{
    if (fwWinModalWindow == null)
    {
        fwWinModalWindow = win;

        fw_widgets.addEventListener(window, "focus", fw_widgets.do_modal_handle_focus);
        fw_widgets.addEventListener(window, "click", fw_widgets.do_modal_ignore_click);
        fw_widgets.addEventListener(window, "dblclick", fw_widgets.do_modal_ignore_click);

        fwWinModalWindow.focus()
    }
}

fw_widgets.do_modal_ignore_click = function(win)
{
    return false
}
 
fw_widgets.do_modal_handle_focus = function(win)
{
    if (fwWinModalWindow)
    {
        if (!fwWinModalWindow.closed)
        {
            fwWinModalWindow.focus()
        }
        else
        {
            fw_widgets.removeEventListener(window, "focus", fw_widgets.do_modal_handle_focus);
            fw_widgets.removeEventListener(window, "click", fw_widgets.do_modal_ignore_click);
            fw_widgets.removeEventListener(window, "dblclick", fw_widgets.do_modal_ignore_click);

            fwWinModalWindow = null;
        }
    }

  return false
}

function fw_vlayout( sizing)
{
  this.sizing = sizing.replace( /px$/, "");
  this.needs_footer_resize = false;
  this.footers = new Array();
  this.headers = new Array();
  this.body = null;
  // myObj needed here to pass this pointer to layout
  var myObj = this;
  this.layout_call = function()
  {
    myObj.layout();
  }
  fw_widgets.addEventListener(window, "resize", this.layout_call, false);
  fw_widgets.addEventListener(window, "load", this.layout_call, false);
}

fw_vlayout.prototype.set_needs_footer_resize = function( nfr)
{
    this.needs_footer_resize = nfr;
}

fw_vlayout.prototype.add_footer = function(footer)
{
  this.footers[ this.footers.length] = footer;
}

fw_vlayout.prototype.add_header = function(header)
{
  this.headers[ this.headers.length] = header;
}

fw_vlayout.prototype.set_body = function(body)
{
  this.body = body;
  if ( this.body != null )
  {
    // if the body is contained in a table, we need to use the 
    // parent as the sizer
    for ( var el = this.body.parentNode; el != null && el.tagName != "BODY"; el = el.parentNode)
    {
      if ( el.tagName == "TABLE" )
      {
        if ( fwIsIE )
        {
          fw_widgets.removeEventListener(window, "resize", this.layout_call);
          fw_widgets.addEventListener(this.body.parentNode, "resize", this.layout_call);
        }
        this.sizing = "parent";
        break;
      }
    }
  }
}

fw_vlayout.prototype.get_element_for_sizing = function()
{
  if ( this.headers.length > 0 )
    return this.headers[0];
  else if ( this.body != null )
    return this.body;
  else if ( this.footers.length > 0 )
    return this.footers[0];
  else
    return null;
}

fw_vlayout.prototype.get_bottom = function()
{
  if ( this.sizing == "100%" )
  {
    return fw_widgets.get_window_dimensions().height;
  }
  else if ( this.sizing == "parent" )
  {
    var el = this.get_element_for_sizing();
    if ( el != null )
      return fw_widgets.get_obj_top( el.parentNode) + el.parentNode.offsetHeight;
    else
      return fw_widgets.get_window_dimensions().height;
  }
  else if ( this.sizing.match( /%$/) )
  {
    return (fw_widgets.get_window_dimensions().height) *
             eval( this.sizing.replace( /%$/, "")) / 100;
  }
  else
  {
    var el = this.get_element_for_sizing();
    return fw_widgets.get_obj_top( el) + eval( this.sizing);
  }
}

fw_vlayout.prototype.get_top = function()
{
  var topElement = this.get_element_for_sizing();
  if ( topElement != null )
    return fw_widgets.get_obj_top( topElement);
  else
    return fwIsNav ? 0 : document.body.clientTop;
}

fw_vlayout.prototype.get_body_height = function()
{
  var top = this.get_top();
  var bottom = this.get_bottom();
  for ( obj in this.headers )
    top += this.headers[obj].offsetHeight;
  for ( obj in this.footers )
    bottom -= this.footers[obj].offsetHeight;
  return bottom - top;
}

fw_vlayout.prototype.layout = function()
{
  var top = this.get_top();
  var bottom = this.get_bottom();

  for ( obj in this.headers )
    top += this.headers[obj].offsetHeight;

  if ( this.footers.length > 0 )
  {
    for ( var i = this.footers.length - 1; i >= 0; i--)
    {
      var footer = this.footers[i];
      bottom -= footer.offsetHeight;
      footer.style.top = bottom;
    }
  }

  if ( this.body != null )
  {
    var diff = bottom - top;
    if ( diff < 20 )
        diff = 20;
    this.body.style.height = diff;

    // workaround for bug in Netscape where the footers are sized too wide
    // and tables don't size at all unless its forced
    if ( fwIsNav && this.needs_footer_resize )
    {
      for ( obj in this.footers )
      {
        this.footers[obj].style.width = this.body.offsetWidth;
        fw_vlayout.size_tables( this.footers[obj], this.body.offsetWidth);
      }
    }
  }
}

fw_vlayout.size_tables = function( el, size_to_set)
{
  if ( el.tagName == "TABLE" )
  {
    if ( el.width == "100%" )
    {
      el.style.position = "absolute";
      el.style.width = size_to_set;
      el.style.position = "relative";
    }
  }
  else if ( el.tagName == "DIV" )
  {
    for ( var i = 0; i < el.childNodes.length; i++)
      if ( el.childNodes[i].nodeType == 1 )
        fw_vlayout.size_tables( el.childNodes[i], size_to_set);
  }
}


function fw_event(event)
{
  this.event = event;
}

fw_event.prototype.get_client_mouse_position = function()
{
  if (this.event.clientX || this.event.clientY)
  {
    return new fw_point(this.event.clientX, this.event.clientY);
  }
  else if (this.event.pageX || this.event.pageY)
  {
    return new fw_point(this.event.pageX, this.event.pageY);
  }
  else
  {
    //barf
  }
}

fw_event.prototype.get_visible_mouse_position = function()
{
  var result = this.get_client_mouse_position();
  result.x += window.document.body.scrollLeft;
  result.y += window.document.body.scrollTop;
  return result;
}


function fw_point(x, y)
{
  this.x = x;
  this.y = y;
}

fw_point.prototype.toString = function()
{
  return "{x:" + this.x + ";y:" + this.y + "}";
} 


function fw_dimensions(width, height)
{
  this.width = width;
  this.height = height;
}

fw_dimensions.prototype.toString = function()
{
  return "{with:" + this.width + ";height:" + this.height + "}";
} 


function fw_rect(left, top, right, bottom)
{
  this.left = left;
  this.top = top;
  this.right = right;
  this.bottom = bottom;
}

fw_rect.create_from_element = function(element)
{
  var left = fw_widgets.get_obj_visible_left(element);
  var top = fw_widgets.get_obj_visible_top(element);
  var dims = fw_widgets.get_obj_dimensions(element);
  return new fw_rect(left, top, left + dims.width, top  + dims.height);
}

fw_rect.prototype.contains_point = function(point)
{
  return (this.left <= point.x && 
          this.top <= point.y  && 
          this.right >= point.x &&
          this.bottom >= point.y);
}

fw_rect.prototype.get_dimensions = function()
{
  return new fw_dimensions(this.width, this.height);
}

fw_rect.prototype.toString = function()
{
  return ("{left:" + this.left + ";top:" + this.top + 
          "right:" + this.right + ";bottom:" + this.bottom + "}");
}

var fw_hover;
if ( fwIsIE )
{
  fw_hover = function( caller)
  {
    if ( caller.scrollWidth != caller.clientWidth )
      caller.title = caller.innerText;
    else
      caller.title="";
  }
}
else
{
  function fw_hover_get_text(node,text)
  {
    for ( var i = 0; i < node.childNodes.length; i++)
    {
      if ( node.childNodes[i].nodeType == 3 )
        text += node.childNodes[i].nodeValue;
      else if ( node.childNodes[i].nodeType == 1 )
        text = fw_hover_get_text( node.childNodes[i],text);
    }
    return text;
  }
  var fw_hover_regex = new RegExp();
  fw_hover_regex.compile(/\s+/g)
  fw_hover = function( caller)
  {
    if ( !caller.title )
    {
      var text = fw_hover_get_text(caller,"");
      text = text.replace( fw_hover_regex, " ");
      caller.title = text;
    }
  }
}

fw_widgets.animateVerticalDisappear = function(obj, increment, incrementIncrement)
{
    if (!fw_widgets.getIsAnimating(obj))
    {
        fw_widgets.setIsAnimating(obj, true);
        fw_widgets.ensureHeightIsRecorded(obj);
        obj.style.overflow="hidden";
        fw_widgets.ensureObjectHasAnID(obj);
        fw_widgets.animateVerticalDisappearInternal(obj.id, increment, incrementIncrement);
    }
}

fw_widgets.animateVerticalDisappearInternal = function(objID, increment, incrementIncrement)
{
    var obj = document.getElementById(objID);

    var realHeight = obj.getAttribute("_iw_height");
    var newHeight = obj.offsetHeight + increment;

    if (newHeight < 0)
    {
        obj.style.display="none";
        obj.style.overflow="";
        obj.style.height="";

        fw_widgets.setIsAnimating(obj, false);
    }
    else
    {
        obj.style.height=newHeight;

        setTimeout("fw_widgets.animateVerticalDisappearInternal(\'" + obj.id + "\', " + (increment + incrementIncrement) + ", " + incrementIncrement + ")", 10);
    }
}

fw_widgets.animateVerticalAppear = function(obj, increment, incrementIncrement)
{
    if (!fw_widgets.getIsAnimating(obj))
    {
        fw_widgets.setIsAnimating(obj, true);
        fw_widgets.ensureHeightIsRecorded(obj);
        obj.style.overflow="hidden";
        obj.style.height = "1";
        obj.style.display="";
        obj.style.visibility = "visible";
        fw_widgets.ensureObjectHasAnID(obj);
        fw_widgets.animateVerticalAppearInternal(obj.id, increment, incrementIncrement);
    }
}

fw_widgets.animateVerticalAppearInternal = function(objID, increment, incrementIncrement)
{
    var obj = document.getElementById(objID);

    var realHeight = obj.getAttribute("_iw_height");
    var newHeight = obj.offsetHeight + increment;

    if (newHeight >= realHeight)
    {
        obj.style.overflow="";
        obj.style.height="";

        fw_widgets.setIsAnimating(obj, false);
    }
    else
    {
        obj.style.height=newHeight;

        setTimeout("fw_widgets.animateVerticalAppearInternal(\'" + obj.id + "\', " + (increment + incrementIncrement) + ", " + incrementIncrement + ")", 10);
    }
}

fw_widgets.ensureHeightIsRecorded = function(obj)
{
    var realHeight = obj.getAttribute("_iw_height");

    if (!eval(realHeight))
    {
        obj.setAttribute("_iw_height", obj.offsetHeight);
    }
}

fw_widgets.setIsAnimating = function(obj, isAnimating)
{
    obj.setAttribute("_iw_is_animating", isAnimating);
}

fw_widgets.getIsAnimating = function(obj)
{
    return eval(obj.getAttribute("_iw_is_animating"));
}

var uniqueIDCount = 0;

fw_widgets.ensureObjectHasAnID = function(obj)
{
    if (!obj.id)
    {
        obj.id = "_iw_temp_id_" + uniqueIDCount++;
    }
}
