// Popup-related functions

// Warning when navigating away from changed form {{{
formWarning = true;
formChanged = false;
function formWarn() {
// Warn user
  if (formWarning && formChanged) {
    return 'If you click OK, any changes will be lost.';
  }
}
window.onbeforeunload = formWarn;
// }}}

openWindowsArray = Array();
function windowOpenOrFocus(url, windowname, options) { // {{{
// Open new window or bring to focus if it's already open

  // If it already exists, give it focus
  if (openWindowsArray[windowname] &&
      openWindowsArray[windowname].open &&
      !openWindowsArray[windowname].closed) {
    openWindowsArray[windowname].focus();
  }

  // Create new window and remember it
  else {
    openWindowsArray[windowname] =
      window.open(url, windowname, options);
  }

} // }}}

// Set to true when page becomes fully loaded
loaded = false;
function onLoadCallback() { // {{{
// Loaded by all pages
  loaded = 1;
} // }}}

function popLeftAdj(w, fraction) { // {{{
// Pass in width, returns suggested left coordinate
// fraction is "1/2" for middle, "1/3" for first third, etc.
// (centered relative to current window)

  // Default to middle
  if (isNaN(fraction))
    fraction = 0.5;

  // Sensible default if all else fails
  useLeft = 25;

  // Find center width (Netscape)
  if (window.outerWidth) {
    if (!isNaN(window.screenX)) {
      useLeft = window.screenX;
    }
    if (window.outerWidth > 0) {
      useLeft += Math.floor((window.outerWidth*fraction) - (w/2));
    }
  }

  // Find center width (IE)
  else {
    if (!isNaN(window.screenLeft))
      useLeft = window.screenLeft;
    if (document.body.offsetWidth > 0)
      useLeft += Math.floor((document.body.offsetWidth*fraction) - (w/2));
  }

  // Nudge back if we go too far right or down
  if (screen.availWidth > 0) {
    if ((useLeft + w) > screen.availWidth)
      useLeft -= (useLeft + w) - screen.availWidth;
  }

  // Make sure we don't go negative
  if (useLeft < 0) useLeft = 0;

  return useLeft;

} // }}}

function popTopAdj(h, fraction) { // {{{
// Pass in height, returns suggested top coordinate
// fraction is "1/2" for middle, "1/3" for first third, etc.
// (centered relative to current window)

  // Default to middle
  if (isNaN(fraction))
    fraction = 0.5;

  // Sensible default if all else fails
  useTop = 25;

  // Find center height (Netscape)
  if (window.outerHeight) {
    if (!isNaN(window.screenY)) {
      useTop = window.screenY;
    }
    if (window.outerHeight > 0)
      useTop += Math.floor((window.outerHeight*fraction) - (h/2));
  }

  // Find center height (IE)
  else {
    if (!isNaN(window.screenTop))
      useTop = window.screenTop;
    if (document.body.offsetHeight > 0)
      useTop += Math.floor((document.body.offsetHeight*fraction) - (h/2));
  }

  // Nudge back if we go too far right or down
  if (screen.availHeight > 0) {
    if ((useTop + h) > screen.availHeight)
      useTop -= (useTop + h) - screen.availHeight;
  }

  // Make sure we don't go negative
  if (useTop < 0) useTop = 0;

  return useTop;

} // }}}

function popWidthAdj(w, fraction) { // {{{
// Pass in width, returns fraction of available screen width if it won't fit

  // Use 90% if not specified
  if (isNaN(fraction) || fraction > 1 || fraction <= 0)
    fraction = 0.9;

  if (screen.availWidth > 0) {
    if (w > (screen.availWidth * fraction))
      w = screen.availWidth * fraction;
  }

  return w;
} // }}}

function popHeightAdj(h, fraction) { // {{{
// Pass in height, returns fraction of available screen height if it won't fit

  // Use 90% if not specified
  if (isNaN(fraction) || fraction > 1 || fraction <= 0)
    fraction = 0.9;

  if (screen.availHeight > 0) {
    if (h > (screen.availHeight * fraction))
      h = screen.availHeight * fraction;
  }

  return h;
} // }}}

function csvString2Hash(str) { // {{{
// Convert '10,25' into
//   myHash[10] = true
//   myHash[25] = true

  myArray = str.split(',');
  myHash  = Array();
  for (x=0; x<myArray.length; x++) {
    myHash[csvArray[x]] = true;
  }

  return myHash;
} // }}}

function select2csvStrings(selectId, win) { // {{{
// Returns object with two Array() member variables:
// csvKeysString
// csvValsString

  s = idOf(selectId, win);
  r = new Object();
  r.csvKeysString = '';
  r.csvValsString = '(none)';

  // If we have a select field
  if (s) {
    csvKeysArray = Array();
    csvValsArray = Array();

    for (x=0; x<s.options.length; x++) {
      if (s.options[x].selected) {
        csvKeysArray.push(s.options[x].value);
        csvValsArray.push(s.options[x].text);
      }
    }

    // Make csv strings
    if (csvKeysArray.length) {
      r.csvKeysString = csvKeysArray.join(',');
      r.csvValsString = csvValsArray.join(', ');
    }
  }

  return r;

} // }}}

function setSelectFromCsvString(str, selectId, win) { // {{{
// Sets multi select from comma separated string

  s = idOf(selectId, win);

  if (s) {
    // Put into hash for easy lookup
    csvArray = str.split(',');
    csvHash  = Array();
    for (x=0; x<csvArray.length; x++) {
      csvHash[csvArray[x]] = true;
    }

    // Loop over select values
    for (x=0; x<s.options.length; x++) {
      if (csvHash[s.options[x].value] == true)
        s.options[x].selected = true;
      else
        s.options[x].selected = false;
    }
  }

} // }}}

function checkboxes2csvStrings(formId, keyPrefix, valPrefix, win) { // {{{
// Returns object with two Array() member variables:
// csvKeysString
// csvValsString
//
// e.g.
// With this HTML:
//  <input type="checkbox" id="id_123" />
//  <input type="hidden" id="text_123" value="Description 3" />
//  <input type="checkbox" id="id_124" />
//  <input type="hidden" id="text_124" value="Description 4" />
//
// This call:
//  obj = checkboxes2csvStrings('myform', 'id_', 'text_');
//
// Could create:
//  obj.csvKeysString = "123,124"
//  obj.csvValsString = "Description 3, Description 4"

  f = idOf(formId, win);
  r = new Object();
  r.csvKeysString = '';
  r.csvValsString = '(none)';

  // If we have a form
  if (f && f.elements) {
    csvKeysArray = Array();
    csvValsArray = Array();

    for (x=0; x<f.elements.length; x++) {
      // Find all the checkboxes
      if (f.elements[x].type == "checkbox" && f.elements[x].checked) {

        // Only consider if it has the right prefix
        if (keyPrefix.length) {
          keyPrefixCompare = f.elements[x].id.substr(0, keyPrefix.length);
          if (keyPrefix != keyPrefixCompare) continue;
        }

        // Suffix
        key = f.elements[x].id.substr(keyPrefix.length, 99);

        // Suffix is the key
        csvKeysArray.push(key);

        // Value is possibly stored in neighboring input field
        valPrefixField = idOf(valPrefix + key);
        if (valPrefixField)
          csvValsArray.push(valPrefixField.value);
      }
    }

    // Make csv strings
    if (csvKeysArray.length) {
      r.csvKeysString = csvKeysArray.join(',');
      r.csvValsString = csvValsArray.join(', ');
    }

  }

  return r;

} // }}}

function setCheckboxesFromCsvString(str, keyPrefix, win) { // {{{
// Checks checkboxes from string like this: '123,124'
//
// e.g.
// With this HTML:
//  <input type="checkbox" id="id_123" />
//  <input type="checkbox" id="id_124" />
//
// Call:
//  setCheckboxesFromCsvString('123,124', 'id_');

  csvArray = str.split(',');

  for (x=0; x<csvArray.length; x++) {
    if (idOf(keyPrefix + csvArray[x], win).type == "checkbox")
      idOf(keyPrefix + csvArray[x], win).checked = true;
  }

} // }}}

function setInputValue(inputId, newValue, win) { // {{{
// Sets input or textarea field to string
// Doesn't generate error if doesn't exist

  i = idOf(inputId, win);

  if (i) {
    i.value = newValue;
  }
} // }}}

// For setInterval call to reloadAndCloseCallback
reloadAndCloseTimes      = 0; // Number of times to check
reloadAndCloseCallbackId = 0; // ID of timer
reloadAndCloseWin        = 0; // Window ID (usually window.opener)
reloadAndCloseDoScroll   = 0;
function reloadAndCloseCallback(closeSelf, Y) { // {{{
// Support function called on interval

  // Only do this a finite number of times
  reloadAndCloseTimes--;

  // Make sure we're operating on a valid window
  if (reloadAndCloseWin) {

    reloadAndCloseWinLoadedTruth = false;
    try {
      reloadAndCloseWinLoadedTruth = reloadAndCloseWin.loaded;
    } catch(e) { }

    // Return if not ready and still counting down
    if (!reloadAndCloseWinLoadedTruth && reloadAndCloseTimes > 0) return;

    // Stop calling this function now
    if (reloadAndCloseCallbackId)
      clearInterval(reloadAndCloseCallbackId);

    // Scroll window
    if (reloadAndCloseDoScroll && reloadAndCloseWinLoadedTruth && reloadAndCloseWin.scrollTo)
      reloadAndCloseWin.scrollTo(0, Y);

    // Set focus
    if (closeSelf)
      reloadAndCloseWin.focus();
  }

  // Close
  if (closeSelf)
    window.close();

} // }}}

function getScrollY(win) { // {{{
// Compatibly gets the offset scrolled down from the top

  Y = 0;

  // Netscape, Mozilla
  if( typeof(win.pageYOffset) == 'number' ) {
    Y = win.pageYOffset;

  // DOM
  } else if ( win.document.body && win.document.body.scrollTop ) {
    Y = win.document.body.scrollTop;

  // IE6 standards compliant
  } else if ( win.document.documentElement &&
              win.document.documentElement.scrollTop ) {
    Y = win.document.documentElement.scrollTop;
  }

  return Y;

} // }}}

function reloadAndClose(win, closeSelf, scrollPolls, url, forceLocation) { // {{{
// Reloads window (typically window.opener), scrolls back into position
// scrollPolls is number of times to poll for window to scroll into position
//   (1 every 1/10 of a second, 0 to turn off, -1 not to reload at all)
// Optionally closes self

  // If window is still there
  if (win) {

    reloadAndCloseWin = win;

    // If we're checking the location
    // and location doesn't match
    // and we're forcing win to load that url
    resetLocationTruth = url && url.length;
    try {
      resetLocationTruth = resetLocationTruth && win.location != url;
    } catch (e) { }

    if (resetLocationTruth && forceLocation) {
      win.location = url;
    }

    // If we're checking the window's location and not forcing
    // Or we're not checking the window's location
    else if (!resetLocationTruth) {

      // Get current scroll position
      if (scrollPolls > 0)
        Y = getScrollY(win);
      else
        Y = 0;

      // Don't reload at all if we were told not to
      if (scrollPolls != -1) {
        win.location.reload();
        realoadAndCloseDoScroll = 1;
      } else {
        realoadAndCloseDoScroll = 0;
      }

      // If we have somewhere to scroll to, set timer and watch
      if (scrollPolls > 0 && Y > 0) {

        // Clear previous if there's still one going
        if (reloadAndCloseCallbackId)
          clearInterval(reloadAndCloseCallbackId);

        // Set number of times to check for window being done loading
        reloadAndCloseTimes = scrollPolls;

        // 10 second max
        if (reloadAndCloseTimes > 100)
          reloadAndCloseTimes = 300;

        // Set timer
        reloadAndCloseCallbackId =
          setInterval("reloadAndCloseCallback(" + closeSelf + ", " + Y + ");", 100);

        return;
      }
    }

  }

  // Call callback directly without an actual timer if we fell through
  reloadAndCloseCallback(closeSelf, 0);

} // }}}

// vim: set fdm=marker:

