var Dom = YAHOO.util.Dom;
var Evt = YAHOO.util.Event;

// Map alerts to console.log or disable completely!
function trace(s) { try {if (console && console.log) console.log(s);} catch(ex) {/* you are fed here */} }
function alert(s) { trace(s); }

function ce(localName, attrs, html, parent) {
  var el = null;
  try {
    el = document.createElement(localName);
    if (el && parent) {parent.appendChild(el);}
    if (el && attrs) {for (var a in attrs) {el.setAttribute(a, attrs[a]);}}
    if (el && html) {el.innerHTML = html;}
  }
  catch (e) {}
  return el;
}

function link_tag(url) {
  return ce('link', {'rel': 'stylesheet', 'type': 'text/css', 'href': url}, null, document.body);
}

function script_tag(url) {
  return ce('script', {'type': 'text/javascript', 'src': url}, null,  document.body);
}

function choose_color(promotion) {
  return promotion.promo_color ? promotion.promo_color : '#FFF4BF';
}

function days_from_now(number) {
  var other = new Date();
  other.setDate(new Date().getDate() + number);
  return other;
}

// Global initialization
NCLUtils.onDocumentAvailable(setMaxLengthForTextFields);

/* prints a page */
function doPrint() {
	window.print();
}
/* History -1 */
function back() {
  history.go(-1);
}

/*
 * Correctly handle PNG transparency in Win IE 5.5 or higher.
 */
function correctPNG() {
  for(var i = 0; i < document.images.length; i++) {
    var img = document.images[i];
    var imgName = img.src.toUpperCase();

    if (imgName.substring(imgName.length-3, imgName.length) == "PNG") {
      var imgID = (img.id) ? "id='" + img.id + "' " : "";
      var imgClass = (img.className) ? "class='" + img.className + "' " : "";
      var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' ";
      var imgStyle = "display:inline-block;" + img.style.cssText;

      if (img.align == "left") {
        imgStyle = "float:left;" + imgStyle;
      }

      if (img.align == "right") {
        imgStyle = "float:right;" + imgStyle;
      }

      if (img.parentElement.href) {
        imgStyle = "cursor:hand;" + imgStyle;
      }

      var strNewHTML = "<span " + imgID + imgClass + imgTitle
      + " style=\"width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
      + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
      + "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>";
      img.outerHTML = strNewHTML;
      i -= 1;
    }
  }
}

var popWindow = new Object();
popWindow.closed = true;

function genPopup(url,target,extraProp,pWidth,pHeight) {
  if (genPopup.caller) { trace('genPopup called from ' + genPopup.caller); }
  
  if (!popWindow.closed) {
    popWindow.close();
  }

  popWindow = window.open(url,target,'toolbar=no,width='+pWidth+',height='+pHeight+',left=30,top=30,'+extraProp+',status=yes');
  popWindow.focus();
}

function openPopup(url) {
  genPopup(url, '', 'resizable=yes', 700, 400);
}

// the onloads array holds the functions to be called when the page loads. Each pagelet is responsible for
// loading this array with the functions it needs to run when the page body loads
// add onload functions: use onloads.push(func);
var onloads = new Array();

function bodyOnLoad() {
  for (var i = 0; i < onloads.length; i++) {
    onloads[i]();
  }
}

/*
 * Sets maximum number of characters accepted for text or password input fields
 * to 200. Maximum number is updated only if it wasn't set in HTML.
 */
function setMaxLengthForTextFields() {
  var inputTags = document.getElementsByTagName("input");

  for(var i = 0; i < inputTags.length; i++) {
    if((inputTags[i].type == "text" || inputTags[i].type == "password") && inputTags[i].maxLength == -1) {
      inputTags[i].maxLength = 200;
    }
  }
}

/*
 * Changes height of DIV element that holds main content on the page if
 * its height is smaller then height of DIV that holds secondary content
 * on the right.
 */
function updateContainerHeight() {
  var leftContent = document.getElementById('contentcenter');
  var rightContent = document.getElementById('contentright');

  if (leftContent != null && rightContent != null) {
    var leftContentHeight = parseInt(computedStyle(leftContent).height.replace(/px/,""));
    var rightContentHeight = parseInt(computedStyle(rightContent).height.replace(/px/,"")) + 25;

    if (leftContentHeight < rightContentHeight) {
      leftContent.style.height = (document.getElementById('frame').offsetHeight - document.getElementById('contentheader').offsetHeight) + 'px';
    }
  }
}

/*
 * If pages contains any of the form elements such as text field, dropdown,
 * check box or radio button then first of those elements will be selected.
 * This behavior can be overriden by setting id attribute of element that is
 * desired to be focused to 'defaultFocusTarget'.
 */
function focusOnForm() {
  var defaultFocusTarget = document.getElementById('defaultFocusTarget');
  var formElements = document.getElementsByTagName('input');
  var dropdownFormElements = document.getElementsByTagName('select');

  if (defaultFocusTarget != null) {
    defaultFocusTarget.focus();
  } else if (formElements.length > 0) {

    for (var i = 0; i < formElements.length; i++) {
      if ((NCLUtils.computedStyle(formElements[i], 'visibility') != 'hidden' && NCLUtils.computedStyle(formElements[i], 'display') != 'none')
          && (formElements[i].type == 'text' || formElements[i].type == 'checkbox' || formElements[i].type == 'radio' || formElements[i].type == 'password')) {
        try {
          // if dropdown is first on the form then switch focus to it
          if (dropdownFormElements.length > 0 && elementOrderOnPage(formElements[i], dropdownFormElements[0])) {
            dropdownFormElements[0].focus();
          } else {
            formElements[i].focus();
          }
        } catch (exception) {
          // focus will fail if form is hidden. For example payment page.
        }

        return true;
      }
    }
  }
}

/*
 * Based on element position on the page identifies which element is rendered
 * first.
 */
function elementOrderOnPage(firstElmnt, secondElmnt) {
  var isSecondBeforeFirst = false;
  var elmnt = firstElmnt.previousSibling;

  if (offsetDistance(firstElmnt, 'top', false) > offsetDistance(secondElmnt, 'top', false)) {
    isSecondBeforeFirst = true;
  } else if (offsetDistance(firstElmnt, 'top', false) == offsetDistance(secondElmnt, 'top', false)) {
    if (offsetDistance(firstElmnt, 'left', false) > offsetDistance(secondElmnt, 'left', false)) {
      isSecondBeforeFirst = true;
    }
  }

  return isSecondBeforeFirst;
}

/*
 * If browser is IE6 then adds behaviour to button tags to move background image, if
 * present, up when user moves cursor over button.
 *
 * If browser is Safari duplicates click behaviour to keypress event.
 */
function addButtonBehaviour() {
  var buttons = document.getElementsByTagName('button');

  for (var i = 0; i < buttons.length; i++) {
    if (isBrowserIE && !isIEVersion7) {
      if (computedStyle(buttons[i]).backgroundImage.length > 0) {
        buttons[i].attachEvent('onmouseover', function () {event.srcElement.style.backgroundPosition = 'left bottom';});
        buttons[i].attachEvent('onmouseout', function () {event.srcElement.style.backgroundPosition = 'left top';});
      }
    } else if (isBrowserSafari) {
      buttons[i].addEventListener('keypress', function () {if (event.keyCode == 13) {this.click();}});
    }
  }
}

//formId = The name of the form to be submitted
//target = the value of the page dispatch to be set to
//formAction = the value the form action will be set to
function formSubmit(formId, target, formAction) {
  if (target != null) {
    document.forms[formId].dispatch.value = target;
  }

  if (formAction != null) {
    document.forms[formId].action=formAction;
  }

  document.forms[formId].submit();
}

/////////////////////////////////////////////////////////////////
// General purpose functions

/*
 * Removes preceding and trailing whites spaces from string.
 *
 *   - str  string to be operated on
 */
function trim(str) {
  return str.replace(/^\s+|\s+$/g, '');
}

// A better web context parser that respects teh internets...
function getWebContext() {
	var path = document.location.pathname;
	if (null == path || 0 == path.length ||
		null == path.substr(1) || 0 == path.substr(1).length) return "";
	return '/' + path.substr(1).split(/[\/\\]/)[0];
}

// Creates a URL that includes the web context. Ex: $U('/foo') => '/web/foo'
function $U(path) {
	if (null == path) path = "";
	if (path.match(/^https?:\/\//)) return path;
	return getWebContext() + (path.match(/^\//) ? '' : '/') + path;
}

/*
 * Returns CSSStyleDeclaration object for an element.
 *
 *   - elmnt  object whose styles to return
 */
function computedStyle(elmnt) {
  var computedStyle = null;

  if (document.defaultView && document.defaultView.getComputedStyle) {
    computedStyle = document.defaultView.getComputedStyle(elmnt, '');
  } else if (elmnt.currentStyle) {
    computedStyle = elmnt.currentStyle;
  } else {
    computedStyle = element.style;
  }

  return computedStyle;
}

/*
 * E-mail validation function. Taken from
 * http://www.quirksmode.org/js/mailcheck.html
 *
 * Note. This function will not detect all of the e-mail addresses
 *       1) address that have user name in quotes with strange characters
 *          ex: "J. P. 's-Gravezande, a.k.a. The Hacker!"@server.com
 *       2) address with IP address instead of domain name
 *          ex: me@[187.223.45.119]
 *          some of the mail servers won't even recognize this address
 *       Historically a domain name may not begin with a number, but in
 *       practice this rule is disregarded. So address like this is accepted
 *       ex: someone@123.com
 */
function validateEmail(email) {
  var filter  = /^[\w\.\-]+@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
  return filter.test(email);
}

/*
 * Retrieves element using its id attribute.
 *
 *   - elmnt either reference to element or its id
 */
function getElement(elmnt) {
  return (elmnt != null && (typeof elmnt) == 'string') ? document.getElementById(elmnt): elmnt;
}

var isBrowserIE = false;
var isIEVersion7 = false;
var isBrowserSafari = (window.navigator.userAgent.match(/.*safari.*/i) != null);;

if (document.all) {
  isBrowserIE = true;
  isIEVersion7 = (window.navigator.userAgent.match('.*MSIE 7.*') == null) ? false: true;
}

/*
 * Calculates font size value.
 *
 *   - elmnt  element whose font to calculate
 */
function parseFontSize(elmnt) {
  var baseFontSizeValue = (computedStyle(elmnt).fontSize.match('em')) ? baseFontSize(): 1;
  return parseFloat(computedStyle(elmnt).fontSize.replace(/px|em/, '')) * baseFontSizeValue;
}

/*
 * Returns font size of BODY element. It is assumed that font value is set in pixels.
 */
function baseFontSize() {
  return parseInt(computedStyle(document.getElementsByTagName('body')[0]).fontSize.replace(/px/, ''));
}

/*
 * Returns random number that is greater then low and
 * lower then high
 */
function createRandomValue(low, high) {
  return Math.floor(Math.random() * (1 + high - low) + low);
}

/*
 * If user pressed enter key then executes some function.
 *
 *   - evnt  reference to global browser object containing information
 *           on produced event
 *   - functionReference  function to be executed in enter key was pressed
 */
function executeOnEnter(event, functionReference) {
  if (event.keyCode == 13) {
    functionReference();
    return false;
  } else {
    return true;
  }
}

/*
 * Returns list of document elements with corresponding
 * tag and class name.
 *
 *   - container  parent element that holds search targets
 *   - tagName  element tag used in search
 *   - className  element class used in search
 */
function getElementsByClassName(container, tagName, className) {
  var foundElmnts = new Array();
  var elmnts = (getElement(container) != null) ? getElement(container).getElementsByTagName(tagName) : new Array();
  var re = new RegExp('(^|\\s)' + className + '(\\s|$)');

  for (var i = 0; i < elmnts.length; i++) {
    if (re.test(elmnts[i].className)) {
      foundElmnts.push(elmnts[i]);
    }
  }

  return foundElmnts;
}

/////////////////////////////////////////////////////////////////
// In page pop-up functions

/*
 * Hides currently displayed content element, if any, and displays
 * requested content element. Elements are identified by some string
 * that is followed by number. Index numbers should start from 1 and
 * indeces should be sequential.
 *
 * If there is only one element then contentIdPrefix becomes element
 * identifier. In this case index parameter can be null OR have
 * two values 'show' or 'hide'. This allows user to explicitely
 * specify operation to be performed.
 *
 *   - contentIdPrefix  id of elements that belong to same group should start
 *                      with this string
 *   - index  after prefix comes number that identifies element in group
 *            This parameter has dual usage
 */
function displayContent(contentIdPrefix, index) {
  var counter = 1;
  var currentElmnt = YAHOO.util.Dom.get(contentIdPrefix);

  if (index != null && index != 'show' && index != 'hide') {
    while ((currentElmnt = document.getElementById(contentIdPrefix + counter)) != null) {
      if (counter != index){
      	YAHOO.util.Dom.addClass(currentElmnt, 'no_display');
      }else{
      	YAHOO.util.Dom.removeClass(currentElmnt, 'no_display');
      }
      counter++;
    }
  } else if (YAHOO.util.Dom.hasClass(currentElmnt, 'no_display') && (index == null || index == 'show')
             || index == 'show') {
  	YAHOO.util.Dom.removeClass(currentElmnt, 'no_display');
  } else {
  	YAHOO.util.Dom.addClass(currentElmnt, 'no_display');
  }
}

/*
 * Displays element on page. Element is positioned in center of the page.
 *
 * Note. Hidden element's CSS position and z-index will be set to 'absolute' and '3'
 *
 *   - hiddenElmnt  elemnt that is being manipulated
 *   - isModal  switch indicating if page functionality will be disabled when
 *              hiddenElement is displayed. Accepted value 'modal'
 *   - top  distance from top of the page
 *   - left  distance from left side of the page
 */
function displayElement(hiddenElmnt, isModal, top, left) {
  hiddenElmnt = getElement(hiddenElmnt);

  // setting visibility to "hidden" here and changing it at the end to "visible"
  // displays element to user after it was positioned. Otherwise users will see
  // element move into final position from its base position
  hiddenElmnt.style.visibility = 'hidden';
  hiddenElmnt.style.position = 'absolute';
  hiddenElmnt.style.zIndex = '3';
  displayContent(hiddenElmnt, 'show');

  positionElement(hiddenElmnt);

  if (top != null) {
    hiddenElmnt.style.top = top + 'px';
  }

  if (left != null) {
    hiddenElmnt.style.left = left + 'px';
  }

  if (isModal == 'modal') {
    disableFunctionality();
  }

  hiddenElmnt.style.visibility = 'visible';
}

/*
 * Hides element on page.
 *
 *  - elmntId identifier of element to be hidden
 *  - isModal  switch indicating if page functionality should be enabled.
 *             Accepted value is 'modal'
 */
function hideElement(elmntId, isModal) {
  var elmnt = getElement(elmntId);
  displayContent(elmnt, 'hide');

  if (isModal == 'modal') {
    enablePageFunctionality(document.body);
  }
}

/*
 * Positions element either in center of the page.
 *
 *   - elmnt  element on page to be positioned
 */
function positionElement(elmnt) {
  var top = elmnt.offsetHeight / 2;
  var left = getElement('frame').offsetWidth / 2 - elmnt.offsetWidth / 2;

  if (document.documentElement.clientHeight) {
    top = (document.documentElement.clientHeight / 2 + document.documentElement.scrollTop) - top;
  } else {
    top = (window.innerHeight / 2 + window.scrollY) - top;
  }

  elmnt.style.top = calculateOffsetDistance(document.body, elmnt, 'top', top) + 'px';
  elmnt.style.left = calculateOffsetDistance(document.body, elmnt, 'left', left) + 'px';
}

/*
 * Calculates number of pixels element should be moved into position.
 *
 *   - refElmnt  element on page relative to which displayed element is beeing positioned
 *   - posElmnt  element for which position coordinates are beeing calculated
 *   - axis  indicator whether distance is from top or left side of the element
 *   - displacement  distance element should be moved in refElmnt
 */
function calculateOffsetDistance(refElmnt, posElmnt, axis, displacement) {
  // number of pixels from top or left of the page where element should be positioned
  var totalVisibleDistance = offsetDistance(refElmnt, axis, false) + displacement;
  return totalVisibleDistance - offsetDistance(posElmnt, axis, true);
}

/*
 * Calculates distance relative to body element or first element (between
 * body and element beeing position) that is relatively positioned.
 */
function offsetDistance(obj, axis, fromRelativeElmnt) {
  var offsetDistance = 0;

  while (obj.offsetParent != null) {
    if ((offsetDistance > 0 || !fromRelativeElmnt || computedStyle(obj).position.match('.*relative.*')) && computedStyle(obj).position.match('.*absolute.*') == null) {
      offsetDistance += (axis == 'left') ? obj.offsetLeft: obj.offsetTop;
    }

    obj = obj.offsetParent;
  }

  return offsetDistance;
}

/*
 * Removes user access to the page or its parts.
 *
 *  - refElmntId  element to cover. If not specified then
 *                whole page
 *  - opacity  transparency level. By default set to 50.
 *             0 is opaque and 100 fully transparent
 */
function disableFunctionality(refElmntId, opacity) {
  var refElmnt = (refElmntId == null) ? document.body: getElement(refElmntId);
  var fullPageCover = (refElmntId == null) ? true: false;
  var blockingElmnt = getElement(refElmnt.getAttribute('blockingElementId'));

  if (blockingElmnt == null) {
    blockingElmnt = document.createElement('div');
    blockingElmnt.id = findUnusedId('blockingElement');
    blockingElmnt.className = 'disablingBackground';
    blockingElmnt.style.opacity= '.' + opacity;
    refElmnt.insertBefore(blockingElmnt, refElmnt.firstChild);
    refElmnt.setAttribute('blockingElementId', blockingElmnt.id);
  } else {
    displayContent(blockingElmnt, 'show');
  }

  // IE < 7 needs special treatment
  if (isBrowserIE && !isIEVersion7) {
    blockingElmnt.style.position = 'absolute';
    blockingElmnt.style.height = document.documentElement.scrollHeight + 'px';
    var selectTags = refElmnt.getElementsByTagName('select');

    // disabling all dropdowns on page because in IE they will
    // shine through DIV used for blocking current page
    for (var i = 0; i < selectTags.length; i++) {
      if (selectTags[i].disabled == false) {
        selectTags[i].disabled = true;
        selectTags[i].setAttribute('disabledWithPageFunctionality', 'true');
      }
    }
  }

  if (!fullPageCover) {
    blockingElmnt.style.position = 'absolute';
    blockingElmnt.style.top = calculateOffsetDistance(refElmnt, blockingElmnt, 'top', 0) + 'px';
    blockingElmnt.style.left = calculateOffsetDistance(refElmnt, blockingElmnt, 'left', 0) + 'px';
    blockingElmnt.style.width = refElmnt.offsetWidth + 'px';
    blockingElmnt.style.height = refElmnt.offsetHeight + 'px';
  }
}

/*
 * Gives user access to page.
 */
function enablePageFunctionality(refElmnt) {
  refElmnt = getElement(refElmnt);
  displayContent(refElmnt.getAttribute('blockingElementId'), 'hide');

  if (isBrowserIE && !isIEVersion7) {
    var selectTags = refElmnt.getElementsByTagName('select');

    for (var i = 0; i < selectTags.length; i++) {
      if (selectTags[i].getAttribute('disabledWithPageFunctionality') == 'true') {
        selectTags[i].disabled = false;
        selectTags[i].setAttribute('disabledWithPageFunctionality', null);
      }
    }
  }
}

/*
 * Find unique element id on page. Id is based on a random
 * digit between 100 and 250 appended to a string provided.
 *
 *   - idPostfix  string used as part of the generated id
 */
function findUnusedId(idPostfix) {
  var id = 0;

  do {
    id = createRandomValue(100, 250);
  } while (getElement(id + idPostfix) != null);

  return id + idPostfix;
}

/////////////////////////////////////////////////////////////////
// Tab functions


/*
 * Creates tab click event handlers for every tab controls on the page.
 */
function setupTabHandling() {
  var tabArrays = getElementsByClassName(document, 'div', 'tabArray');

  for (var i = 0; i < tabArrays.length; i++) {
    var tabs = tabArrays[i].getElementsByTagName('span');

    for (var j = 0; j < tabs.length; j++) {
      tabs[j].onmousedown = function() {
        getElementsByClassName(this.parentNode, 'span', 'tabHover')[0].className = ''; // de-select previous selection
        this.className = 'tabHover';
      }
    }

    // if tab content is too big to fit on same line then padding will be decreased
    var sidePadding = 9;

    while (tabArrays[i].offsetHeight > 20 && sidePadding > 0) {
      for (var j = 0; j < tabs.length; j++) {
        tabs[j].style.padding = '3px ' + sidePadding + 'px';
      }

      sidePadding--;
    }
  }
}

/////////////////////////////////////////////////////////////////
// Date selection functions

/*
 * Updates day drop down with correct number of days for selected
 * month. If user selected day that does not appear in selected month
 * then selection will be defaulted to first dropdown option.
 *
 *   - elmnt  reference to either month or year dropdown
 */
function updateDateSelectionDaysList(elmnt) {
  // indicates whether next or previous sibling in DOM tree should be
  // searched for day dropdown
  var forward = (elmnt.name.match('month') != null) ? true: false;
  var month = (forward) ? elmnt.selectedIndex: 0;
  var year = (!forward) ? elmnt.value: 0;
  var dayDropDown = null;

  while (month == 0 || year == 0) {
    elmnt = (forward) ? elmnt.nextSibling: elmnt.previousSibling;

    if (elmnt.name != null) {
      dayDropDown = (elmnt.name.match('day') != null) ? elmnt: dayDropDown;
      month = parseInt((elmnt.name.match('month') != null) ? elmnt.value: month);
      year = parseInt((elmnt.name.match('year') != null) ? elmnt.value: year);
    }
  }

  var daysPerMonth = getDaysPerMonth(month, year);
  var i = dayDropDown.options.length - 1;

  while (i != daysPerMonth) {
    if (i < daysPerMonth) {
      i++;
      dayDropDown.options[i] = new Option(i, i);
    } else {
      dayDropDown.options[i] = null;
      i--;
    }
  }
}

/*
 * Calculates number of days in selected month.
 *
 *   - month  day of the month
 *   - year  digit corresponding to year
 */
function getDaysPerMonth(monthValue, yearValue) {
  var daysPerMonth = 31;

  if (monthValue == 4 || monthValue == 6 || monthValue == 9 || monthValue == 11) {
    daysPerMonth = 30;
  } else if (monthValue == 2) {
    daysPerMonth = ((yearValue % 4 == 0 && yearValue % 100 != 0 || yearValue % 400 == 0) || yearValue == -1) ? 29: 28;
  }

  return daysPerMonth;
}

/////////////////////////////////////////////////////////////////
// Function used on Travel Choices, Captain's Club Benefits, Registration Retrieval Options and Payment pages

/**
 * Changes section styles to open/close it.
 *
 *  - sectionId  section block identifier or reference to section block
 *  - controlElmnt  element that receives open/close event
 *  - open  flag that can be used to identify what action to take.
 *          Values can be either 'open' or 'close'
 */
function openCloseSection(sectionId, controlElmnt, open) {
  if (getElement(sectionId) != null) {
    var openClose = ((open == null && controlElmnt.className == 'arrow_right') || open == 'open') ? 'open': 'close';

    displayContent(sectionId, (openClose == 'open') ? 'show': 'hide');

    controlElmnt.parentNode.className.match(/(.* )(open|close)/);

    // if open or close is not specified in className then no change will be made
    controlElmnt.parentNode.className = RegExp.$1 + ((RegExp.$2 == '') ? '': openClose);
    controlElmnt.className = (openClose == 'open') ? 'arrow_down' : 'arrow_right';

    // if opened section content is too long for main content body then it will
    // overlap with the footer. Removing height value will allow content to adapt for opened section
    document.getElementById('contentcenter').style.height = '';
  }
}

/////////////////////////////////////////////////////////////////

function submitAndDisable(formId, divId, elementId){
  getElement(elementId).disabled = true;
  disableFunctionality(divId, 50);
  document.forms[formId].submit();
}

function updateGenderByTitle(index,genderMale,genderFemale) {
  if (index == 1) {
    Dom.get('genderMale').checked = 'checked'
    return;
  }

  if (index == 2 || index == 3 || index == 4) {
		Dom.get('genderFemale').checked = 'checked'
    return;
  }
}

/*
 * Changes opacity of element that will be reloaded with Ajax and
 * displays loading message if there is enough space for it.
 *
 *   - elementId  identifier on page for element whose body will be
 *                reloaded
 * Note: leftOffset variable must be a number (Integer or Floating Point)
 */
function displayWaitMessage(elementId, isPayment, leftOffset) {
  var refElmnt = getElement(elementId);

  if (refElmnt == null) {
  	return;
  }

  var maxWidth = 270;
  var maxHeight = 75;
  var backgroundOpacity = 70;

  var elmnts = refElmnt.getElementsByTagName('div');
  var i = 0;

  for (; i < elmnts.length && elmnts[i].className != 'loading_image'; i++);

  // skip showing of wait loading graphics if they are already displayed
  if (i == elmnts.length) {
    disableFunctionality(refElmnt, backgroundOpacity);

    if (refElmnt.offsetWidth > maxWidth && refElmnt.offsetHeight > maxHeight) {
      displayLoadingElement(refElmnt, isPayment, true, leftOffset);
    } else {
      displayLoadingElement(refElmnt, isPayment, false, leftOffset);
    }
  }
}

/*
 * Creates element with loading message and adds it to element that
 * will be reloaded by Ajax.
 *
 * Note: leftOffset variable must be a number (Integer or Floating Point)
 *
 *   - refElmnt  element that will contain loading message
 */
function displayLoadingElement(refElmnt, isPayment, withFlash, leftOffset) {
  var loadingContentDiv = document.createElement('div');
  loadingContentDiv.id = 'loading';

  if (leftOffset == null) {
    leftOffset = 0;
  }

  refElmnt.appendChild(loadingContentDiv);
  loadingContentDiv.innerHTML = '<img src="' + NCLUtils.createURL('/images/locale_us/loading_small.gif') + '" />';

  // position loading message in middle of reference element and 10% from the top
  if (refElmnt.style.position == 'absolute') {
    loadingContentDiv.style.top = (refElmnt.offsetHeight / 10) + 'px';
    loadingContentDiv.style.left = (((refElmnt.offsetWidth - loadingContentDiv.offsetWidth) / 2) + leftOffset) + 'px';
  } else {
    loadingContentDiv.style.top = calculateOffsetDistance(refElmnt, loadingContentDiv, 'top', refElmnt.offsetHeight / 10) + 'px';
    loadingContentDiv.style.left = calculateOffsetDistance(refElmnt, loadingContentDiv, 'left', ((refElmnt.offsetWidth - loadingContentDiv.offsetWidth) / 2) + leftOffset) + 'px';
  }

  loadingContentDiv.style.visibility = 'visible';
}

// toggles collapse/expand sections of Find a Cruise
function toggleSearchParameters(id) {
  NCLUtils.displayContent(id);
  updateSearchFormFrame();
  
  var browser=navigator.appName;
  var b_version=navigator.appVersion;
  var version=parseFloat(b_version);
  var otherButton;
  
  var buttonVal = (/none|^$/.test(NCLUtils.computedStyle(id, 'display'))) ? 'Plus' : 'Minus';
  getElement(id + 'Button').src = getElement(id + 'Button').src.replace(/Plus|Minus/, buttonVal);
  
  if ((browser=="Microsoft Internet Explorer")
		  && (version<7)){
	  if(buttonVal=='Minus'){
		  document.getElementById('residencyState').style.visibility= 'hidden';
	  }
	  if(buttonVal=='Plus'){
		  //get opposite button name
		  if(id=='fac-bestdeal-options'){
			  otherButton = "fac-advancedSearch";
		  }else{
			  otherButton = "fac-bestdeal-options";
		  }
		  //get opposite button state
		  var otherButtonState = (/none|^$/.test(NCLUtils.computedStyle(otherButton, 'display'))) ? 'Plus' : 'Minus';
		  
		  if(otherButtonState=="Plus"){
			  document.getElementById('residencyState').style.visibility='visible';
		  }
	  }
  }
}

/*
 * Adds an event handler to element.
 *
 * elmnt        - element that is going to throw the event
 * eventName    - name of event (name should not have "on" prefix. Example "mouseover")
 * eventHandler - function to handle event
 * direction    - boolean specifying at what point to initiate event handler, capture or bubble.
 *                Browsers other then IE
 */
function addEventHandler(elmnt, eventName, eventHandler, direction) {
  if (elmnt.attachEvent) {
    elmnt.attachEvent('on' + eventName, eventHandler);
  } else {
    direction = (direction == null) ? false: true;
    elmnt.addEventListener(eventName, eventHandler, direction);
  }
}

/*
 * Removes an event handler from element.
 *
 * elmnt        - element that throws event
 * eventName    - name of event (name should not have "on" prefix. Example "mouseover")
 * eventHandler - function that handles event
 * direction    - boolean specifying at what point to initiate event handler, capture or bubble.
 *                Browsers other then IE
 */
function removeEventHandler(elmnt, eventName, eventHandler, direction) {
  try {
    if (elmnt.detachEvent) {
      elmnt.detachEvent('on' + eventName, eventHandler);
    } else {
      direction = (direction == null) ? false: true;
      elmnt.removeEventListener(eventName, eventHandler, direction);
    }
  } catch (Exception) {}
}

/*
 * Returns object that produced event
 */
function getEventTarget(evnt) {
  return (evnt.target) ? evnt.target: event.srcElement;
}

/*
 * Searchs DOM tree for parent node with specified CSS class.
 *
 * elmnt - child node whose parent is to find
 * className - string with parent node's CSS class
 */
function findParent(elmnt, className) {
  while ((elmnt = elmnt.parentNode) != null && elmnt.className != className);
  return elmnt;
}


/////////////////////////////////////////////////////////////////
// In page cruise search form pop-up

function showCruiseSearchForm() {
  getElement('cruiseSearchPopoutForm').style.visibility = 'visible';

  if (getElement('boat').getElementsByTagName('object').length == 0) {
    updateCruiseSearchDateRange('all');
    NCLUtils.createFlashElement('boat', NCLUtils.createURL('/flash/bkgdSearchBottom.swf'), 252, 161);
    getElement('boat').style.background = 'none';
  }

  addEventHandler(document, 'click', closeCruiseSearchForm, false);
}

function closeCruiseSearchForm(event, forceClose) {
  if (findParent(getEventTarget(event), 'cruiseSearchForm') == null || forceClose) {
    getElement('cruiseSearchPopoutForm').style.visibility = 'hidden';
    removeEventHandler(document, 'click', closeCruiseSearchForm, true);
  }
}

/*
 * Changes height iframe embeded in search form. IE 6 only.
 */
function updateSearchFormFrame() {
  var cruiseSearchForm = getElement('cruiseSearchPopoutForm');

  if (cruiseSearchForm != null) {
    var frame = cruiseSearchForm.getElementsByTagName('iframe');

    if (frame.length > 0) {
      frame[0].style.height = getElement('top').offsetHeight + 'px';
    }
  }
}

// NOTE: updateType is a string type - see CruiseSearchUpdateType for possible values
function updateCruiseSearchDateRange(updateType, notHomePage) {
  var suffix = (notHomePage && notHomePage != 'searchDates') ? 'DetailsPg' : '';
  var areDateFieldsOnPage = (getElement('selectedFromDate' + suffix) != null);
  var url = (/\/secure/.test(document.location.pathname)) ? '/secure/searchDatesUpdate.html' : '/cruisesearch/cruisesearch.html';

  // Grab the values we'll send off to the request (allowing them to not be present, for
  // the first call) the action will use the default value if "" supplied
  sendAjaxRequest(url, 'dispatch=ajaxUpdateSearchFields'
    + '&destinationCode=' + getElement('destinationCode' + suffix).value
    + '&selectedFromDate=' + ((areDateFieldsOnPage) ? getElement('selectedFromDate' + suffix).value: '')
    + '&selectedToDate=' + ((areDateFieldsOnPage) ? getElement('selectedToDate' + suffix).value: '')
    + '&suffix=' + suffix + '&updateType=' + updateType, 'searchDates' + suffix);
}

function submitFormOnEnterKey(evnt, formId) {
  var keyCode = (document.all) ? event.keyCode: evnt.keyCode;

  if (keyCode == 13) {
    formSubmit(formId);
  }
}

function show(el, fn) {
	Dom.setStyle(el, 'display', 'block');
	if (fn) { fn(Dom.get(el)); }
}

function hide(el, fn) {
	Dom.setStyle(el, 'display', 'none');
	if (fn) { fn(Dom.get(el)); }
}

function is_hidden(el) {
	return 'none' == Dom.getStyle(el, 'display');
}

// Toggle any block-level element by setting its display style
function toggleDisplay(el, onshow, onhide) {
  if (is_hidden(el)) {
	show(el, onshow);
  }
  else {
    hide(el, onhide);
  }
}