window.onload = js01_init;

// Define some global variables
var z_isCSS, z_isW3C, z_isIE4, z_isNN4, z_isIE6;

function js01_init() {
  z_isCSS = (document.body && document.body.style)     ? true : false;
  z_isW3C = (z_isCSS && document.getElementById)       ? true : false;
  z_isIE4 = (z_isCSS && document.all)                  ? true : false;
  z_isNN4 = (document.layers)                          ? true : false;
  z_isIE6 = (document.compatMode && 
             document.compatMode.indexOf("CSS1") >= 0) ? true : false;
}

function js01_get_element(x_id) {
  if (typeof x_id != 'string') return x_id;
  if (document.getElementById)
    return document.getElementById(x_id);
  if (document.all)
    return document.all[x_id];
  return null;
}

/*
    find_position:
    returns the page position of any element on the screen
    thanks to webreference.com for info about tables, etc.
*/
function js01_find_position(x_element) {

  // No parent, just return the coordinates
  if (! x_element.offsetParent)
    return [x_element.x, x_element.y];

  // Scan backwards through the parents
  for( var f_x = 0, f_y = 0; x_element.offsetParent; x_element = x_element.offsetParent ) {
    // If IE...
    if (z_isIE4 || z_isIE6) {
      // If element is not a table or body tag, append the cell border info
      if (x_element.tagName != 'TABLE' && x_element.tagName != 'BODY') {
        f_x += x_element.clientLeft
        f_x += x_element.clientTop
      }

    // Gecko?
    } else {
      // We need to take the table border into consideration
      if (x_element.tagName == 'TABLE') {
        var f_border = parseInt(x_element.border);
        // No visible border, check for a frame attribute
        if (isNaN(f_border)) {
          var f_frame = x_element.getAttribute('frame');
          // Found a frame attribute, but only add one pixel for it.
          if (f_frame != null) {
            f_x++;
            f_y++;
          }

        // Visible border, add it to the calculation, too
        } else if (f_border > 0) {
          f_x += f_border;
          f_y += f_border;
        }
      }
    }

    // Don't forget the actual location of the element
    f_x += x_element.offsetLeft;
    f_y += x_element.offsetTop;
  }
  return [f_x, f_y];
}

/*
    for some reason, this doesn't seem to work properly in IE when scrolled down the page a bit...
    I'm open to suggestions for fixing it.
*/

var z_lastshown = null;
var z_timeout   = null;    // global timeout id
var z_name      = null;    // global name to "show"
var z_parent    = null;    // global name to "show"
var z_x_offset  = 0;
var z_y_offset  = 5;
var z_show      = false;
    
function js01_popup_toggle(x_id) {
  var f_name = x_id + '_popup';
  if ( f_name == z_lastshown && z_show == true ) {
    js01_popup_hide();
    z_show=false;
  } else {
    js01_popup_show(x_id);
    z_show=true;
  }
}
    
function js01_popup_show(x_id, x_popup_id, x_x, x_y) {
  // store data in global var
  if (x_popup_id && x_popup_id.length > 0)
    z_name = x_popup_id + '_popup';
  else
    z_name = x_id + '_popup';

  z_parent = x_id;

  // Adjust x and y offsets?
  z_x_offset = isNaN(x_x) ? 0 : x_x;
  z_y_offset = isNaN(x_y) ? 5 : x_y;

  // delay to give position time to be better
  js01_clear_timeout();
  z_timeout = setTimeout('js01_popup_timed_show()', 50);
}

function js01_popup_timed_show() {
  js01_clear_timeout();
  // retrieve data from global var
  f_name = z_name;

  // In case the last was stuck on, let's hide it
  if (z_lastshown && z_lastshown != f_name)
    js01_popup_timed_hide();

  // Grab the current element to be shown
  z_lastshown = f_name;
  var f_field = js01_get_element(f_name);
  if (f_field.style)
    f_field = f_field.style;

  // Get the location of the parent element
  var f_pos = js01_find_position(js01_get_element(z_parent));
  // Set the initial position of the hidden element
  var f_x = parseInt(f_pos[0]);
  var f_y = parseInt(f_pos[1]) + js01_get_element(z_parent).offsetHeight;

  // Get some window information so we can make sure the box doesn't extend off the edge of the screen
  var f_window_width = 0, f_window_height = 0, f_scroll_left = 0, f_scroll_top = 0;
  if (document.documentElement.clientWidth) {
    f_window_width  = document.documentElement.clientWidth;
    f_window_height = document.documentElement.clientHeight;
    f_scroll_left   = document.documentElement.scrollLeft;
    f_scroll_top    = document.documentElement.scrollTop;
  } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
    f_window_width  = document.body.clientWidth;
    f_window_height = document.body.clientHeight;
    f_scroll_left   = document.body.scrollLeft;
    f_scroll_top    = document.body.scrollTop;
  } else {
    f_window_width  = window.innerWidth;
    f_window_height = window.innerHeight;
    if (document.body && document.body.scrollLeft) {
      f_scroll_left = document.body.scrollLeft;
      f_scroll_top  = document.body.scrollTop;
    } else {
      f_scroll_left = window.pageXOffset;
      f_scroll_top  = window.pageYOffset;
    }
  }

  // Do our best to try to keep the popup onscreen and away from the mouse
  if (f_window_width > 0 && f_window_height > 0) {
    var f_orig_field = js01_get_element(f_name);
    f_width  = parseInt(f_orig_field.offsetWidth);
    f_height = parseInt(f_orig_field.offsetHeight);

    // Adjust the element location?
    if (f_x > f_window_width + f_scroll_left - f_width - 2)
      f_x = f_window_width + f_scroll_left - f_width - 2;        // subtract a couple of extra pixels to account for borders
    if (f_y > f_window_height + f_scroll_top - f_height - 7)
      f_y = f_window_height + f_scroll_top - f_height - 7;    // subtract a couple of extra pixels to account for borders

    // Does this now conflict with the parent element?
    if (f_y < parseInt(f_pos[1])) {
      if (f_x < parseInt(f_pos[0]))
        f_y = parseInt(f_pos[1]) - f_height - 10;
      else
        f_x += js01_get_element(z_parent).offsetWidth + 5 - z_x_offset;
    }
  }

  // Make some minor corrections
  f_x += z_x_offset;
  f_y += z_y_offset;
  if (f_x < 0) f_x = 0;
  if (f_y < 0) f_y = 0;

  // Adjust the element
  f_field.left = f_x;
  f_field.top  = f_y;
  if (z_isNN4) {
    f_field.xpos       = f_x;
    f_field.ypos       = f_y;
    f_field.visibility = 'show';
  } else
    f_field.visibility = 'visible';
}

function js01_popup_hide(x_delay) {
  x_delay = parseInt(x_delay);
  if (isNaN(x_delay) || x_delay < 1)
    x_delay = 0;
  js01_clear_timeout();
  z_timeout = setTimeout('js01_popup_timed_hide()', x_delay);
}

function js01_popup_timed_hide() {
  js01_clear_timeout();
  if (z_lastshown) {
    var f_field = js01_get_element(z_lastshown);
    if (f_field.style)
      f_field = f_field.style;
    f_field.visibility = z_isNN4 ? 'hide' : 'hidden';
  }
  z_lastshown = null;
}

function js01_clear_timeout() {
  if (z_timeout) {
    clearTimeout(z_timeout);
    z_timeout = null;
  }
}

var z_numeric = '01234567890';
var z_alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var z_punctuation = '!"£$%^&*()_-+=:;@~#<>,.? ';
var z_alphanumeric = z_numeric + z_alpha;
var z_printable = z_numeric + z_alpha + z_punctuation;

function js01_in_valid_charset( x_str, x_charset ) {
  var f_result = true;

  for ( var i = 0; i < x_str.length; i++ )
    if ( x_charset.indexOf( x_str.substr( i, 1 ) ) < 0 ) {
    f_result = false;
    break;
  }

  return f_result;
}
