/**
 * @file
 * @author Shannon M. Rause <shannon.rause@creativeflavor.com>
 * @version $Revision: 1.37 $
 * @version $Name: FAIRVIEWFRIENDSFOUNDATION_2010-12-06_1 $
 * @version $Id: Core.js,v 1.37 2009/10/27 23:06:13 smr Exp $
 *
 * These files are copyrighted to Creative Flavor Inc. and are
 * subject to the terms of the applicable Service Agreement.
 * If no service agreement is available you must contact us at
 * legal@creativeflavor.com or 303-379-9450.
 * 
 * These files may be watermarked to ensure traceability.
 */
/**
 * Core class.
 */
function Core()
{
} // Core


// path - normally '' but can be set to something different if using shared ssl.
Core.path = '';

Core._userAjaxCommandCb = null;
Core._userAjaxRequest   = null;

Core._windowCloseTimer = null;


/**
 * Sends an ajax request.
 *
 * @param data    Data to pass request as POST data.
 * @param cb      User function to call when response is received.
 * @param cbData  Callback data.
 */
Core.ajaxSendXml = function(data,
                            cb,
                            cbData)
{
   var ajax = new Ajax();
   Core._userAjaxRequest = data;
   ajax.sendXml('/ajax.php',
                data,
                cb,
                cbData);
} // ajaxSendXml


/**
 * Simple function that takes a command name and an array
 * of parameters, builds a request and then calls the callback
 * (hopefully) upon completion.
 *
 * @param cmd     Name of command to execute.
 * @param params  Array of key/value pairs.
 * @param cb      Callback to run upon completion. Must take following parameters: cmd (will 
 *                   contain an object w/ two keys: _message for command message and _return for
 *                   command return value), data (will contain whatever given in cbData below),
 *                   request (will contain whatever given in params above), status, and reason.
 * @param cbData  Optional data that will be passed to the callback 
 *                   unmodified.
 */
Core.ajaxSendCommand = function(cmd,
                                params,
                                cb,
                                cbData)
{
   var ajax = new Ajax();
   var data = {
      'cmd'       : cmd,
      'userData'  : cbData
   }

   params['cmd'] = cmd;
   Core._userAjaxCommandCb = cb;
   Core.ajaxSendXml(params,
                    Core._ajaxCommandCallback,
                    data);
} // ajaxSendCommand


/**
 * Used to change the notify input if the approval status is changed.
 *
 * @param select  Status select control.
 */
Core.changeAdminUserStatus = function(select)
{
   switch (select.value)
   {
      case 'approved':  var msg = 'Notify user that their request has been approved (must click Save below)?'; break;
      case 'denied':    var msg = 'Notify user that their request has been denied (must click Save below)?';   break;
      default:          return;
   } // switch

   var ans = confirm(msg);
   
   if (ans)
   {
      document.getElementById('notify').value = '1';
   } // if
   else
   {
      document.getElementById('notify').value = '0';
   } // else
} // changeAdminUserStatus


/**
 * Displays an error message.
 *
 * @param msg  Error message to display.
 */
Core.displayError = function(msg)
{
   var div = document.getElementById('errorBlock');
   Utils.removeChildren(div);
   div.appendChild(document.createTextNode(msg));
   div.style.display = 'block';
} // displayError


/**
 * Displays a message.
 *
 * @param msg  Message to display.
 */
Core.displayMessage = function(msg)
{
   var div = document.getElementById('messageBlock');
   Utils.removeChildren(div);
   div.appendChild(document.createTextNode(msg));
   div.style.display = 'block';
} // displayMessage


/**
 * Enables/disables access controls as necessary.
 *
 * @param rb         Radio button that was clicked.
 * @param formName   Name of form.
 */
Core.enableAccessControls = function(rb,
                                     formName)
{
   if ((formName == undefined) ||
       (!formName))
   {
      formName = 'adminForm';
   } // if

   var form = document[formName];

   if (form.allowAll[0].checked)
   {
      form['groups[]'].disabled = 'disabled';
      form.ips.disabled = 'disabled';
      form['users[]'].disabled = 'disabled';
   } // if
   else
   {
      form['groups[]'].disabled = '';
      form.ips.disabled = '';
      form['users[]'].disabled = '';
   } // else
} // enableAccessControls


/**
 * This properly sets up the region and province postal code hidden
 * fields based on the current country.
 * 
 * @prefix  If set, this will be prepended to all ids. If this is an
 *             array, it will be performed once for each prefix in the
 *             array.
 */
Core.setupIntlFields = function(prefix)
{
   if ((prefix == null) ||
       (prefix == undefined))
   {
      prefix = new Array('');
   } // if
   else if (typeof(prefix) != 'object')
   {
      prefix = new Array(prefix);
   } // else

   for (var i = 0; i < prefix.length; i++)
   {
      var country = document.getElementById(prefix[i] + 'country');
      var postalCode = document.getElementById(prefix[i] + 'postalCode');
      var region = document.getElementById(prefix[i] + 'region');

      if ((!country) ||
         (!postalCode) ||
         (!region))
      {
         return;
      } // if

      if (country.value == 'CA')
      {
         var r = document.getElementById(prefix[i] + 'caProvince');
         var pc = document.getElementById(prefix[i] + 'caPostalCode');
      } // if
      else
      {
         var r = document.getElementById(prefix[i] + 'intlRegion');
         var pc = document.getElementById(prefix[i] + 'intlPostalCode');
      } // else

      if (pc)
      {
         postalCode.value = pc.value;
      } // if

      if (r)
      {
         region.value = r.value;
      } // if
   } // for
} // setupIntlFields


/**
 * Handles the onchange event for the country select.
 *
 * US data is identified as follows:
 *    Rows that contain US state and/or zip: PusRowX where P is prefix (below) and X is 0, 1, etc...
 *    Rows that contain US errors: PusErrorRowX where P is prefix (below) and X is 0, 1, etc...
 *    Rows that contain only US state: PusState where P is prefix (below).
 *    Rows that contain only US state errors: PusStateErrorRow where P is prefix (below).
 *    Rows that contain only US zip: PusZip where P is prefix (below).
 *    Rows that contain only US zip errors: PusZipErrorRow where P is prefix (below).
 *    US State cells: PusStateCellX where P is prefix (below) and X is 0, 1, etc...
 *    US Zip cells: PusZipCellX where P is prefix (below) and X is 0, 1, etc...
 *
 * Canadian data is identified as follows:
 *    Rows that contain Canadian province and/or postal code: PcaRowX where P is prefix (below) and X is 0, 1, etc...
 *    Rows that contain Canadian errors: PcaErrorRowX where P is prefix (below) and X is 0, 1, etc...
 *    Rows that contain only Canadian province: PcaProvinceRow where P is prefix (below).
 *    Rows that contain only Canadian province errors: PcaProvinceErrorRow where P is prefix (below).
 *    Rows that contain only Canadian postal code: PcaPostalCodeRow where P is prefix (below).
 *    Rows that contain only Canadian postal code errors: PcaPostalCodeErrorRow where P is prefix (below).
 *    Canadian Province cells: PcaProvinceCellX where P is prefix (below) and X is 0, 1, etc...
 *    Canadian Postal code cells: PcaPostalCodeCellX where P is prefix (below) and X is 0, 1, etc...
 *
 * International data is identified as follows:
 *    Rows that contain internation region and/or postal code: PintlRowX where P is prefix (below) and X is 0, 1, etc...
 *    Rows that contain international errors: PintlErrorRowX where P is prefix (below) and X is 0, 1, etc...
 *    Rows that contain only international region: PintlRegionRow where P is prefix (below).
 *    Rows that contain only international region errors: PintlRegionErrorRow where P is prefix (below).
 *    Rows that contain only international postal code: PintlPostalCodeRow where P is prefix (below).
 *    Rows that contain only international postal code errors: PintlPostalCodeErrorRow where P is prefix (below).
 *    International region cells: PintlRegionCellX where P is prefix (below) and X is 0, 1, etc...
 *    International postal code cells: PintlPostalCodeCellX where P is prefix (below) and X is 0, 1, etc...
 *
 * @param select     Country select.
 * @param withZips   Array of countries that have USPS ZIP Codes.
 * @param prefix     String that will be prepended to usData, usHead, etc...
 *                      Can be used if have, say, billing and shipping on same page.
 */
Core.onChangeCountry = function(select,
                                withZips,
                                prefix)
{
   if ((prefix == null) ||
       (prefix == undefined))
   {
      prefix = '';
   } // if

   var usRow = 'none';
   var usStateCell = 'hidden';
   var usStateRow = 'none';
   var usZipCell = 'hidden';
   var usZipRow = 'none';

   var caRow = 'none';
   var caProvinceRow = 'none';
   var caProvinceCell = 'hidden';
   var caPostalCodeRow = 'none';
   var caPostalCodeCell = 'hidden';

   var intlRow = 'none';
   var intlRegionCell = 'hidden';
   var intlRegionRow = 'none';
   var intlPostalCodeCell = 'hidden';
   var intlPostalCodeRow = 'none';

   if (select.value == 'US')
   {
      usRow = '';
      usStateRow = '';
      usStateCell = '';
      usZipRow = '';
      usZipCell = '';
   } // if 
   else if (Utils.inArray(select.value, withZips))
   {
      usRow = '';
      usZipRow = '';
      usZipCell = '';
   } // else if
   else if (select.value == 'CA')
   {
      caRow = '';
      caProvinceRow = '';
      caProvinceCell = '';
      caPostalCodeRow = '';
      caPostalCodeCell = '';
   } // else
   else if (select.value)
   {
      intlRow = '';
      intlRegionRow = '';
      intlRegionCell = '';
      intlPostalCodeRow = '';
      intlPostalCodeCell = '';
   } // else

   Core._changeCountryDisplay(prefix + 'usRow',             usRow);
   Core._changeCountryDisplay(prefix + 'usErrorRow',        usRow);
   Core._changeCountryDisplay(prefix + 'usStateRow',        usStateRow);
   Core._changeCountryDisplay(prefix + 'usStateErrorRow',   usStateRow);
   Core._changeCountryDisplay(prefix + 'usZipRow',          usZipRow);
   Core._changeCountryDisplay(prefix + 'usZipErrorRow',     usZipRow);

   Core._changeCountryDisplay(prefix + 'caRow',                caRow);
   Core._changeCountryDisplay(prefix + 'caErrorRow',           caRow);
   Core._changeCountryDisplay(prefix + 'caProvinceRow',        caProvinceRow);
   Core._changeCountryDisplay(prefix + 'caProvinceErrorRow',   caProvinceRow);
   Core._changeCountryDisplay(prefix + 'caPostalCodeRow',      caPostalCodeRow);
   Core._changeCountryDisplay(prefix + 'caPostalCodeErrorRow', caPostalCodeRow);

   Core._changeCountryDisplay(prefix + 'intlRow',                 intlRow);
   Core._changeCountryDisplay(prefix + 'intlErrorRow',            intlRow);
   Core._changeCountryDisplay(prefix + 'intlRegionRow',           intlRegionRow);
   Core._changeCountryDisplay(prefix + 'intlRegionErrorRow',      intlRegionRow);
   Core._changeCountryDisplay(prefix + 'intlPostalCodeRow',       intlPostalCodeRow);
   Core._changeCountryDisplay(prefix + 'intlPostalCodeErrorRow',  intlPostalCodeRow);

   Core._changeCountryVisibility(prefix + 'usStateCell', usStateCell);
   Core._changeCountryVisibility(prefix + 'usZipCell',   usZipCell);

   Core._changeCountryVisibility(prefix + 'caProvinceCell',    caProvinceCell);
   Core._changeCountryVisibility(prefix + 'caPostalCodeCell',  caPostalCodeCell);

   Core._changeCountryVisibility(prefix + 'intlRegionCell',       intlRegionCell);
   Core._changeCountryVisibility(prefix + 'intlPostalCodeCell',   intlPostalCodeCell);
} // onChangeCountry


/**
 * Handles a pager page change event.
 *
 * @param select        The selct DOM object.
 * @param path          Path.
 * @param queryString   Query string.
 * @param doName        Data object name.
 * @param itemsPerPage  Number of items per page.
 */
Core.onChangePagerPage = function(select,
                                  path,
                                  queryString, 
                                  doName,
                                  itemsPerPage)
{
   if (queryString)
   {
      queryString = '?' + queryString;
   } // if

   document.location.pathname = path + '/_pager/' + doName + '.' + itemsPerPage + '.' + select.value + '/' + queryString;
} // onChangePagerPage


/**
 * Opens a window.
 *
 * @param url        URL to display in window.
 * @param title      Title of window.
 * @param width      Width of window.
 * @param height     Height of window.
 * @param scrollbars 1 to have scrollbars, 0 for none.
 *
 * @return Newly created Window.
 */
Core.openWindow = function(url,
                           title,
                           width,
                           height,
                           scrollbars)
{
   var x = (640 - width) / 2;
   var y = (480 - height) / 2;

   if (screen)
   {
      y = (screen.availHeight - height) / 2;
      x = (screen.availWidth - width) / 2;
   } // if

   if (screen.availWidth > 1800)
   {
      x = ((screen.availWidth / 2) - width) / 2;
   } // if

   params = 'width='    + width  + ',' +
            'height='   + height + ',' +
            'screenX='  + x      + ',' +
            'screenY='  + y      + ',' +
            'top='      + y      + ',' +
            'left='     + x      + ',' +
            'dependent=yes,'  +
            'directories=no,' +
            'location=no,'    +
            'menubar=no,'     +
            'status=no,'      +
            'toolbar=no';

   if (scrollbars)
   {
      params += ',scrollbars=yes';
   } // if
   else
   {
      params += ',scrollbars=no';
   } // else

   newWin = window.open(url,
                        title,
                        params);

   return (newWin);
} // openWindow


/**
 * Opens a window with an image url.
 * Note that window will be automatically closed on a blur event.
 * Also note that window will be 50px wider/taller than given width/height
 * to prevent IE scrollbars.
 *
 * @param imgUrl  Image URL to display in window.
 * @param title   Title of window.
 * @param width   Width of window.
 * @param height  Height of window.
 *
 * @return Newly created Window.
 */
Core.openWindowImg = function(imgUrl,
                              title,
                              width,
                              height)
{
   newWin = Core.openWindow('',
                            title,
                            width + 50,
                            height + 50);
   newWin.document.write('<html><head><script src="' + Core.path + '/scripts/core/Core.js" language="javascript" type="text/javascript"></script></head><body onblur="Core.startWindowCloseTimer(5);" onfocus="Core.stopWindowCloseTimer();"><img src="' + imgUrl + '" /></body></html>');
   newWin.document.close();

   return (newWin);
} // openWindowImg


/**
 * Removes an image via ajax.
 *
 * @param dataObj Data object of this item.
 * @param id      Id of item that has image.
 * @param name    Name of image.
 * @param idx     Index of this image on the page.
 */
Core.removeImage = function(dataObj,
                            id,
                            name,
                            idx)
{
   if (name == undefined)
   {
      name = 'image';
   } // if
   
   Core.ajaxSendCommand('removeImage',
                        { 'doName':dataObj, 'name':name, 'id':id },
                        null,
                        null);

   if (idx != undefined)
   {
      try
      {
         document.getElementById('_input_image_img_' + idx).style.display = 'none';
         document.getElementById('_input_image_br_' + idx).style.display = 'none';
         document.getElementById('_input_image_note_' + idx).style.display = 'none';
      } // try
      catch(e) {}
   } // if
} // removeImage


/**
 * This sets a 15 second timer after which the current window will be closed.
 * stopWindowCloseTimer() can be called to stop it.
 *
 * @param secs Number of seconds for timer.
 */
Core.startWindowCloseTimer = function(secs)
{
   Core._windowCloseTimer = window.setTimeout('window.close()',
                                              secs * 1000)
} // startWindowCloseTimer


/**
 * Stops the timer created w/ startWindowCloseTimer().
 */
Core.stopWindowCloseTimer = function()
{
   if (Core._windowCloseTimer)
   {
      window.clearTimeout(Core._windowCloseTimer);
      Core._windowCloseTimer = null;
   } // if
} // stopWindowCloseTimer


/**
 * This updates the debug response div with the given text for the purposes of
 * displaying an AJAX response.
 *
 * @param text Text to display.
 */
Core.updateResponse = function(text)
{
   if (text)
   {
      var div = document.getElementById('coreDebugResponse');

      if (div)
      {
         Utils.removeChildren(div);
            
         var h1 = document.createElement('h1');
         div.appendChild(h1);

         h1.appendChild(document.createTextNode('AJAX Response'));

         var p = document.createElement('p');
         var temp = text.split('\n');

         for (i in temp)
         {
            p.appendChild(document.createTextNode(temp[i]));
            p.appendChild(document.createElement('br'));
         } // for

         div.appendChild(p);
      } // if
   } // if
} // updateResponse


/**
 * Callback from Core.ajaxSendCommand().
 *
 * @param obj     Returned command object. Should contain two keys: _message for
 *                   command message and _return for command return value under the
 *                   command name key.
 * @param data    Callback data.
 * @param status  HTTP status of response (e.g. 200).
 * @param reason  Status text of response (e.g. OK).
 * @param xml     Raw XML response (DOM).
 * @param text    Rax XML response (text).
 */
Core._ajaxCommandCallback = function(obj,
                                     data,
                                     status,
                                     reason,
                                     xml,
                                     text)
{
   var elem = document.getElementById('debugResponse');

   if (elem)
   {
      var request = '';

      for (var i in Core._userAjaxRequest)
      {
         request += ', ' + i + ':' + Core._userAjaxRequest[i];
      } // for

      if (request)
      {
         request = request.substring(2)
      } // if

      var lt = new RegExp('<', 'g');
      var gt = new RegExp('>', 'g');
      text = text.replace(lt, '&lt;').replace(gt, '&gt;');

      Utils.removeChildren(elem);
      var html = '<h1>AJAX Information</h1>';
      html += '<p><strong>Request:</strong> ' + request + '</p><br />';
      html += '<p><strong>Response: </strong>' + text + '</p>';
      elem.innerHTML = html;
      elem.style.display = 'block';
   } // if

   if ((Core._userAjaxCommandCb) &&
       (data.cmd))
   {
      if ((obj) &&
          (obj[data.cmd]))
      {
         obj[data.cmd]._name = data.cmd;
         Core._userAjaxCommandCb(obj[data.cmd],
                                 data.userData,
                                 Core._userAjaxRequest,
                                 status,
                                 reason);
      } // if
      else
      {
         Core._userAjaxCommandCb(null,
                                 data.userData,
                                 Core._userAjaxRequest,
                                 status,
                                 reason);
      } // else
   } // if
} // _ajaxCommandCallback


/**
 * Changes the display style of the given country field.
 * Note that this will try just the id and then id + 0, id + 1, etc...
 *
 * @param id      Id of element.
 * @param display 'none' or ''.
 */
Core._changeCountryDisplay = function(id,
                                      display)
{
   var elem = document.getElementById(id);

   if (elem)
   {
      elem.style.display = display;
   } // if

   var i = 0;
   elem = document.getElementById(id + i);

   while (elem)
   {
      elem.style.display = display;
      i = i + 1;
      elem = document.getElementById(id + i);
   } // while
} // _changeCountryDisplay


/**
 * Changes the visibility style of the given country field.
 * Note that this will try just the id and then id + 0, id + 1, etc...
 *
 * @param id         Id of element.
 * @param visiblity  'hidden' or ''.
 */
Core._changeCountryVisibility = function(id,
                                         visibility)
{
   var elem = document.getElementById(id);

   if (elem)
   {
      elem.style.visibility = visibility;
   } // if

   var i = 0;
   elem = document.getElementById(id + i);

   while (elem)
   {
      elem.style.visibility = visibility;
      i = i + 1;
      elem = document.getElementById(id + i);
   } // while
} // _changeCountryVisibility



