function is_defined(str)            { return typeof(str) != "undefined"; }
function is_digit(str)              { return /^\d$/.test(str);                                                                         }
function is_integer(str)            { return /^[-]?\d+$/.test(str); }
function is_integer_gez(str)        { return is_integer(str) && str >= 0; }
function is_integer_gz(str)         { return is_integer_gez(str) && str > 0; }
function is_float(str)              { return /^([-]?((([0-9]+(\.)?)|([0-9]*\.[0-9]+))([eE][-]?[0-9]+)?))$/.test(replace_comma(str)); }
function is_float_nz(str)           { return is_float(str) && str != 0; }

function replace_comma(str)         { return str.toString().replace(',','.'); }

function parse_float(str)           { return parseFloat(replace_comma(str)); }

function is_element_value_float(element_name)    { return element_defined(element_name) && is_float(element_value(element_name)); }
function is_element_value_float_nz(element_name) { return element_defined(element_name) && is_float_nz(element_value(element_name)); }

function get_elements_by_name(element_name)      { return document.getElementsByName(element_name); }

function element_defined(element_name)           { return typeof(document.getElementById(element_name)) != "undefined"; }
function element_value(element_name)             { return document.getElementById(element_name).value; }
function element_value_to_string(element_name)   { return document.getElementById(element_name).value.toString(); }
function element_value_length(element_name)      { return get_length(element_value(element_name)); }
function element_value_or_n(element_name)        { return is_element_value_nn(element_name) ? element_value(element_name) : ""; }
function element_innerhtml(element_name)         { return document.getElementById(element_name).innerHTML; }

function is_element_value_nn(element_name)       { return element_defined(element_name) && element_value(element_name) != ""; }
function is_element_value_n(element_name)        { return !is_element_value_nn(element_name); }
function is_element_value_trim_nn(element_name)  { return element_defined(element_name) && trim(element_value(element_name)) != ""; }
function is_element_value_trim_n(element_name)   { return !is_element_value_trim_nn(element_name); }

function form_submit(element_name)               { if (!is_defined(element_name)) { element_name="form"; } document.getElementById(element_name).submit(); }

function set_element_focus(element_name)                    { if (is_defined(element_name)) { document.getElementById(element_name).focus(); }                     }
function set_element_value(element_name, value)             { document.getElementById(element_name).value = value; }
function set_element_innerhtml(element_name, value)         { document.getElementById(element_name).innerHTML = value.toString(); }
function set_element_innerhtml_add(element_name, value)     { document.getElementById(element_name).innerHTML = element_innerhtml(element_name) + value; }

function is_element_checked(element_name) {
   var elements = get_elements_by_name(element_name);
   var result = 0;
   for (var i = 0; i < elements.length; i++) { if (elements[i].checked) { result = 1; break; } }
   return result;
}

// use this for captcha image refresh
function RefreshImage(valImageId) {
	var objImage = document.images[valImageId];
	if (objImage == undefined) {
		return;
	}
	var now = new Date();
	objImage.src = objImage.src.split('?')[0] + '?x=' + now.toUTCString();
}


function is_last_name(element_name) { 
   var value = "", result = 0;
   if (is_element_value_nn(element_name)) {
      value = element_value(element_name);
      result = ( (value.length >= 2) && (value.length <= 25) && is_letter_with_minus(value) );
   }
   return result;
}

function is_first_name(element_name) { return is_last_name(element_name) && element_value_length(element_name) >= 3; }

function is_email(element_name) { 
   var value = "", result = 0;
   if (is_element_value_nn(element_name)) {
      value = element_value(element_name);
      result = ( (value.toString().length <= 40) && Util.isEmail(value) );
   }
   return result;
}

function is_valid_phone(element_name) { return is_element_value_nn(element_name) && validPhone(element_value_to_string(element_name)); }

function is_letter_with_minus(value) { return /^(([a-zA-Zà-ÿÀ-ß]+)|([a-zA-Zà-ÿÀ-ß]+[-]?[a-zA-Zà-ÿÀ-ß]+))$/.test(value); }
function is_letter(value) { return /^[a-zA-Zà-ÿÀ-ß]+$/.test(value); }

function get_length(str) { return str.toString().length; }

function trim(str)       { return str.replace(/^\s*(.*?)\s*$/, "$1"); }
function ltrim(str)      { return str.replace(/^\s+(.*?)/i, "$1");    }
function rtrim(str)      { return str.replace(/(.*?)\s+$/i, "$1");    }

function imposeMaxLength(Object, MaxLen) { return (Object.value.length < MaxLen-5); }

function isMacAddress(src) {
    if (src.length == "12" && isHex(src)) {
        return true;
    }
    else {
        return false;
    }
}

function is_passport_deal_number(str) {
   var i, result = 1;
   if ( str.length == 22 ) { for (i = 0; i < str.length; i++ ) { if ( !(is_digit(str.charAt(i)) || str.charAt(i) == "/" ) ) { result = 0; break; } } } else { result = 0; }
   return result;
}

function isHex(entry) {
    validChar='0123456789ABCDEF';// characters allowed in hex
    strlen=entry.length;         // how long is test string
    if (strlen < 1) {
        return false;
    }
    entry=entry.toUpperCase();   // lowercase characters?
    for (i=0; i<strlen; i++) {
        if (validChar.indexOf(entry.charAt(i))<0) {
            return false;
        }    
    } // end scanning loop
    return true;
}


// 11.12.2008 Yurkov A. S. íå äàåì Textarea ââîäèòü áîëüøå ñèìâîëîâ
function TextareaMaxLength(Object, MaxLen) { return (Object.value.length <= MaxLen); }

function URLDecode1(psEncodeString) {
  var lsRegExp = /\+/g;
  return unescape(String(psEncodeString).replace(lsRegExp, " ")); 
}

function URLDecode(psEncodeString) { return unescape(psEncodeString); }

//25.11.2008 Yurkov A. S. èç çàêàçîâ èíòåðíåò áèëåòîâ
function validPhone(v) {
  var si='0123456789', n=0, i, c='';
  for(i=0; i<v.length; i++) {
    if (si.indexOf(v.substr(i,1))!=-1) {
    if (n==0) c=v.substr(i,1);
    n++;
  }
  }
  return ( n==10 || (n==11 && (c=='8' || c=='7')));
}

function _validPhone(v) {
	//return /^([87]\s?)?(\(\d{3,5}\))? ?((\d{6})|(\d{2}[-\s]\d{2}-\d{2})|(\d{3}-\d{3})|(\d{4}[-\s]?\d{3}))( äîá. \d{1,4})?$/.test(v);
	return /^([87]\s?)?\(?\d{3,5}\)?\s?((\d{6})|(\d{2}[-\s]\d{2}[-\s]\d{2})|(\d{3}-\d{3})|(\d{4}[-\s]?\d{3}))( äîá. \d{1,4})?$/.test(v);
}

//25.11.2008 Yurkov A. S. ñêà÷àë â èíòåðíåòå
function isPhone(str) {
  var filter=/^(\+?(\d{1})?( )?\(?\d{1} ?\d{2}(\d{1})?\)? ?\d{1}-? ?\d{1}-? ?\d{1}-? ?(\d{1})?-? ?(\d{1})?-? ?(\d{1})?-? ?(\d{1})?)$/;
  if (filter.test(str)) {
    return true;
  } else {
    return false;
  }
}

//25.11.2008 Yurkov A. S. ñêà÷àë â èíòåðíåòå
function isEmail(str) {
  return /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
  if (filter.test(str)) {
    return true;
   } else {
    return false;
  }
}

  
Util = new function () {
  this.countChar = function (str,chr) {
    var _len = str.length;
    var _result = 0;
    for (var _i = 0; _i < _len; _i++) {
      if (str.charAt(_i) == chr) {
        _result++;
      }
    }
    return _result;
  }
  
  this.countNonASCII = function (str) {
    var _len = str.length;
    var _result = 0;
    for (var _i = 0; _i < _len; _i++) {
      if (str.charCodeAt(_i) > 127) {
        _result++;
      }
    }
    return _result;
  }
  
  this.countWhiteSpaces = function (str) {
    var _len = str.length;
    var _result = 0;
    for (var _i = 0; _i < _len; _i++) {
      if (str.charCodeAt(_i) < 33) {
        _result++;
      }
    }
    return _result;
  }
  
  this.countNonDigits = function (str) {
    var _len = str.length;
    var _result = 0;
    for(var _i = 0; _i < _len; _i++) {
      if ((str.charCodeAt(_i) < 48) || (str.charCodeAt(_i) > 57)) {
        _result++;
      }
    }
    return _result;
  }
  
  this.isInteger = function (n) {
    return (!isNaN(n) && (Math.ceil(n) == Math.floor(n)));
  }
  
  this.isNatural = function (n) {
    return this.isInteger(n) && (n >= 0);
  }
  
  this.isPositiveNumber = function (n) {
    return (!isNaN(n) && (n > 0));
  }
  
  this.isPositiveInteger = function (n) {
    return this.isInteger(n) && (n > 0);
  }
  
  this.trimLeft = function (str) {
    var _len = str.length;
    var _i;
    var _result = new String(str);
    if (_len < 1) {
      return _result;
    }
    for (_i = 0; _i < _len; _i++) {
      if ((str.charCodeAt(_i) > 32) || (str.charCodeAt(_i) < -1)) {
        break;
      }
    }
    if (_i < 1) {
      return _result;
    }
    _result = _result.substring(_i,_len);
    return _result;
  }
  
  this.trimRight = function (str) {
    var _len = str.length;
    var _i;
    var _result = new String(str);
    if (_len < 1) {
      return _result;
    }
    for (_i = 0; _i < _len; _i++) {
      if ((str.charCodeAt(_len - _i - 1) > 32) || (str.charCodeAt(_i) < -1)) {
        break;
      }
    }
    if (_i < 1) {
      return _result;
    }
    _result = _result.substring(0,_len - _i);
    return _result;
  }
  
  this.trim = function (str) {
    var _result = this.trimLeft(str);
    if (_result.length > 0) {
      _result = this.trimRight(_result);
    }
    return _result;
  }
  
  this.isBlank = function (str) {
    return (str == null) || (this.trimLeft(str).length == 0);
  }
  
  this.isEmail = function (str) {
    var _str = new String(this.trim(str));
    if (this.countWhiteSpaces(_str) > 0) {
      return false;
    }
    if (this.countNonASCII(_str) > 0) {
      return false;
    }
    if ((_str.length < 6) || (this.countChar(_str,"@") != 1)) {
      return false;
    }
    var leftPart = _str.substring(0,_str.indexOf("@"));
    var rightPart = _str.substr(_str.indexOf("@") + 1);
    return ((leftPart.length > 0) && (rightPart.length > 3)
      && (this.countChar(rightPart,".") > 0)
      && (rightPart.charAt(rightPart.length - 1) != ".")
      && (rightPart.charAt(0) != "."));
  }
  
  //25.11.2008 Yurkov A. S. ñêà÷àë â èíòåðíåòå
  this.checkEmail = function (str) {
    var _result = true;
    var filter=/^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
    if (!(filter.test(str))) {
      _result = false;
    }
    return _result; 
  }
  
  this.isPhoneNumber = function (str) {
    var _len = str.length;
    var _result = true;
    var _code;
    if (_len < 1) {
      return false;
    }
    for(var _i = 0; _i < _len ; _i++) {
      _code = str.charCodeAt(_i);
      if(
        (_code == 32) // space
        || ((_code >= 48) && (_code <= 57)) // digits
        || (_code == 43) // plus sign
        || (_code == 45) // minus sign
        ) {
        continue;
      }
      _result = false;
      break;
    }
    return _result;
  }
  
  //25.11.2008 Yurkov A. S. ñêà÷àë â èíòåðíåòå
  this.checkPhoneNumber = function (str) {
    var _result = true;
    var filter=/^(\+?(\d{1})?( )?\(?\d{1} ?\d{2}(\d{1})?\)? ?\d{1}-? ?\d{1}-? ?\d{1}-? ?(\d{1})?-? ?(\d{1})?-? ?(\d{1})?-? ?(\d{1})?)$/;
    if (!(filter.test(str))) {
      _result = false;
    }
    return _result; 
  }
  
  this.isICQ = function (str) {
    var _len = str.length;
    var _result = true;
    var _code;
    if (_len < 1) {
      return false;
    }
    for(var _i = 0; _i < _len ; _i++) {
      _code = str.charCodeAt(_i);
      if(
        (_code == 32) // space
        || ((_code >= 48) && (_code <= 57)) // digits
        || (_code == 45) // minus sign
        ) {
        continue;
      }
      _result = false;
      break;
    }
    return _result;
  }
  
  this.isUrl = function (str) {
    var _str = new String(this.trim(str));
    if (this.countWhiteSpaces(_str) > 0) {
      return false;
    }
    if (this.countChar(_str,".") < 1) {
      return false;
    }
    return true;
  }
  
  this.fillLeft = function (s,c,l) {
    if (s.length >= l) {
      return new String(s);
    }
    var result = "";
    for (var i = 0; i < (l - s.length); i++) {
      result += c;
    }
    return result + s;
  }
  
  this.fillRight = function (s,c,l) {
    if (s.length >= l) {
      return new String(s);
    }
    var result = "";
    for (var i = 0; i < (l - s.length); i++) {
      result += c;
    }
    return s + result;
  }
  
  /*
   * Function call onFocus="textFocus(this);" onBlur="textBlur(this);"
   */
  this.textFocus = function (el, val) {
    if (val) {
      el.defaultValue = val;
      if (el.value == val) {
        el.value = "";
      }
    } else if (el.value != "") {
      el.defaultValue = el.value;
      el.value = "";
    }
  }
  
  this.textBlur = function (el, val) {
    if (val) {
      el.defaultValue = val;
    }
    if (el.value == "") {
      el.value = el.defaultValue;
    }
  }
    
  this.findXCoord = function (evt) {
    if (evt.x) {
      return evt.x;
    }
    if (evt.pageX) {
      return evt.pageX;
    }
  }
  
  this.findYCoord = function (evt) {
    if (evt.y) {
      return evt.y;
    }
    if (evt.pageY) {
      return evt.pageY;
    }
    return null;
  }
    
  this.getElementInAllB = function (str) {
    if (document.layers) {
      return document.layers[str];
    } else if (document.getElementById) {
      return document.getElementById(str);
    } else if (document.all) {
      return document.all[str];
    }
    return null;
  }
  
  this.findFormElement = function (theForm, name) {
    for (var i = 0; i < theForm.elements.length; i++) {
      var el = theForm.elements[i];
      if ((el.name == name) || (el.id == name)) {
        return el;
      }
    }
    return null;
  }
  
  this.buildUrl = function (link) {
    if (link.charAt(0) == '/') {
      return link;
    }
    var p = BASE_URL.indexOf(";jsession");
    if (p == -1) {
      return BASE_URL + link;
    }
    return BASE_URL.substr(0, p) + link + BASE_URL.substr(p, BASE_URL.length);
  }
}

PopupUtil = new function () {
  this.showTicket = function (url) {
    var wndName = "ticketWnd";
    var w = 650;
    var h = 500;
    var l = (screen.availWidth - w) / 2;
    var t = (screen.availHeight - h) / 2;
    var wndFeatures = "toolbar=no,location=no,directories=no,status=no,menubar=1,scrollbars=yes,resizable=yes,top="
      + t + ",left=" + l + ",width=" + w + ",height=" + h;
    var popupWnd = window.open("", wndName, wndFeatures);
    popupWnd.focus();
    popupWnd = window.open(url, wndName, wndFeatures);
  }
  
  this.open = function (file, pop) {
    window.open(Util.buildUrl(file), pop,
      'width=550,height=500,resizable=1,scrollbars=yes,left=50,top=50');
  }
}

DateUtil = new function () {
  this.MSEC_PER_MINUTE = 1000 * 60;
  this.MSEC_PER_HOUR = this.MSEC_PER_MINUTE * 60;
  this.MSEC_PER_DAY = this.MSEC_PER_HOUR * 24;
  // statndard minimal OUT date for calendars
  this.STANDARD_MIN_OUT_DATE = new Date();
  // statndard minimal stay for calendars (in days)
  this.STANDARD_MIN_STATE = 0;
  
  var utcHours = this.STANDARD_MIN_OUT_DATE.getHours()
      + this.STANDARD_MIN_OUT_DATE.getTimezoneOffset() / 60;
  if (utcHours >= 15) {
    this.STANDARD_MIN_OUT_DATE.setTime(this.STANDARD_MIN_OUT_DATE.getTime()
      + this.MSEC_PER_HOUR * (48 - utcHours));
  } else {
    this.STANDARD_MIN_OUT_DATE.setTime(this.STANDARD_MIN_OUT_DATE.getTime()
      + this.MSEC_PER_HOUR * 12);
  }
  
  this.checkInOutDates = function (outDateStr, inDateStr, fmt, isOneWay) {
    isOneWay = (isOneWay == true);
    var msecPerDay = 24 * 60 * 60 * 1000;
    var currDT = new Date();
    currDT.setHours(0);
    currDT.setMinutes(0);
    currDT.setSeconds(0);
    currDT.setMilliseconds(0);
    var outDT = Date.parseDate(outDateStr, fmt);
    if (outDT == null) {
      return Resources.ERR_INVALID_OUT_DATE;
    }
    if ((outDT.getTime() - currDT.getTime()) < msecPerDay) {
      return Resources.ERR_OUT_DATE_TOO_SMALL;
    }
    if (isOneWay) {
      return null;
    }
    var inDT = Date.parseDate(inDateStr, fmt);
    if (inDT == null) {
      return Resources.ERR_INVALID_IN_DATE;
    }
    if ((inDT.getTime() - outDT.getTime()) < msecPerDay) {
      return Resources.ERR_INVALID_OUT_IN_INTERVAL;
    }
    if ((outDT.getTime() - currDT.getTime()) >= 331 * msecPerDay) {
      return Resources.ERR_OUT_DATE_TOO_BIG;
    }
    if ((inDT.getTime() - currDT.getTime()) >= 331 * msecPerDay) {
      return Resources.ERR_IN_DATE_TOO_BIG;
    }
    return null;
  };

  /*
   * Compares two dates and returns: -1 if date1 earlier date2, 0 if date1 equals date2 and 1 if date1 later date2.
   * date1 and date2 are objects of type Date
   */
  this.compareDates = function (date1,date2) {
    var dateInt1 = date1.getTime();
    var dateInt2 = date2.getTime();
    if (dateInt1 == dateInt2) {
      return 0;
    } else if (dateInt1 < dateInt2) {
      return -1;
    } else {
      return 1;
    }
  };
  
  this.isLeapYear = function (year) {
    if (year % 4 != 0) {
      return false;
    } else if (year % 400 == 0) {
      return true;
    } else if (year % 100 != 0) {
      return true;
    } else {
      return false;
    }
  };
  
  this.getDaysInMonth = function (month,year) {
    if ((month < 1) || (month > 12)) {
      return 0;
    }
    var _daysInMonth = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
    var _result = _daysInMonth[month - 1];
    if ((month == 2) && this.isLeapYear(year)) {
      _result++;
    }
    return _result;
  };
  
  this.isCorrectDate = function (year,month,day) {
    if (!Util.isNatural(year) || !Util.isNatural(month)
        || !Util.isNatural(day)) {
      return false;
    }
    if ((year < 1) || (month < 1) || (month > 12) || (day < 1)) {
      return false;
    }
    var _daysInMonth = this.getDaysInMonth(month,year);
    if (day > _daysInMonth) {
      return false;
    }
    return true;
  };
  
  /**
   *  Tries to identify the date represented in a string.  If successful it also
   *  calls this.setDate which moves the calendar to the given date.
   */
  this.isValidDateString = function (str, fmt) {
    return str == Date.parseDate(str, fmt).print(fmt);
  };
  
  this.isOutDateEnabled = function (date) {
    var diff = date.getTime() - this.STANDARD_MIN_OUT_DATE.getTime()
      + this.MSEC_PER_DAY;
    return (diff >= 0) && (diff <= 331 * this.MSEC_PER_DAY);
  }
  
  this.isInDateEnabled = function (outDate, date) {
    if (outDate == null) {
      outDate = this.STANDARD_MIN_OUT_DATE;
    }
    var diff = date.getTime() - outDate.getTime()
      - this.STANDARD_MIN_STATE * this.MSEC_PER_DAY;
    return (diff >= 0) && (diff <= 331 * this.MSEC_PER_DAY);
  }
}

CalendarRestrictions = function (minDateStr, maxDateStr, fmt) {
  this.minDate = Date.parseDate(minDateStr, fmt);
  this.maxDate = Date.parseDate(maxDateStr, fmt);
  this.disabledDates = new Array();
  
  this.isDateEnabled = function (date) {
    var result = (date.getTime() >= this.minDate.getTime())
      && (date.getTime() <= this.maxDate.getTime());
    if (!result) {
      return false;
    }
    for (var i = 0; i < this.disabledDates.length; i++) {
      if (date.getTime() == this.disabledDates[i].getTime()) {
        return false;
      }
    }
    return true;
  };
  
  this.addDisabledDates = function (datesStr, fmt) {
    var p = this.disabledDates.length;
    for (var i = 0; i < datesStr.length; i++) {
      this.disabledDates[p + i] =
        Date.parseDate(datesStr[i], fmt);
    }
  }
}

GeoNavigator = new function () {
  this.dataElement = null;
  
  this.show = function (theForm, pointType, event) {
    //this.dataElement = theForm.elements[pointType];
    this.dataElement = Util.findFormElement(theForm, pointType);
    this.showWnd(event);
  }
  
  this.setPoint = function (value) {
    if (this.dataElement != null) {
      this.dataElement.value = value;
    }
  }
  
  this.showWnd = function (event) {
    var geoNav = document.getElementById("geoNavDiv");
    if (event.pageX != null) {
      geoNav.style.left = event.pageX + "px";
      geoNav.style.top = event.pageY + "px";
    } else {
      geoNav.style.left = event.x + document.body.scrollLeft + "px";
      geoNav.style.top = event.y + document.body.scrollTop + "px";
    }
    geoNav.style.display = "block";
    document.getElementById("geoNavFrame").src =
      "geoNavigator.do?pattern=" + encodeURIComponent(this.dataElement.value);
  }
  
  this.closeWindow = function (windowRef) {
    if ((windowRef.opener != null) && (windowRef.opener != self)) {
      windowRef.opener.GeoNavigator.hideWnd(windowRef);
    } else {
      parent.GeoNavigator.hideWnd();
    }
  }
  
  this.hideWnd = function (windowRef) {
    if (windowRef != null) {
      windowRef.close();
    } else  {
      document.getElementById("geoNavDiv").style.display = "none";
      document.getElementById("geoNavFrame").src = "about:blank";
    }
  }
}

Splash = new function () {
  this.playCount = 0;
  
  this.play = function () {
    var search_splash = document.getElementById('searchSplash');
    search_splash.style.top = document.body.scrollTop
      + document.body.clientHeight / 2 - 150 / 2
      + (Math.random() - 0.5) * 5;
    search_splash.style.left = document.body.scrollLeft
      + document.body.clientWidth / 2 - 250 / 2
      + (Math.random() - 0.5) * 5;
    if (this.playCount < 30) {
      this.playCount++;
      setTimeout("Splash.play()", 40);
    } else {
      this.playCount = 0;
      setTimeout("Splash.play()", 6000);
    }
  }
  
  this.show = function () {
    var search_splash = document.getElementById('searchSplash');
    search_splash.style.display = 'block';
    search_splash.style.top = document.body.scrollTop
      + document.body.clientHeight / 2 - 150 / 2;
    search_splash.style.left = document.body.scrollLeft
      + document.body.clientWidth / 2 - 250 / 2;
    setTimeout("Splash.play()",3000);
    return;
  }
}

DomUtil = new function () {
  this.findParent = function (node, name, id) {
    if (node == null) {
      return null;
    }
    if (node.nodeName == name) {
      if (id == null) {
        return node;
      } else if (node.getAttribute("id") == id) {
        return node;
      }
    }
    return this.findParent(node.parentNode, name, id);
  }
  
  this.findChild = function (node, name, id) {
    if (node == null) {
      return null;
    }
    var children = node.childNodes;
    for (var i = 0; i < children.length; i++) {
      var result = children.item(i);
      if (result.nodeName == name) {
        //alert("node=" + result.nodeName + ", id=" + result.getAttribute("id"));
        if (id == null) {
          return result;
        } else if (result.getAttribute("id") == id) {
          return result;
        }
      }
      result = this.findChild(result, name, id);
      if (result != null) {
        return result;
      }
    }
    return null;
  }
  
  this.visitNodes = function (parent, nodeName, callback) {
    if (parent == null) {
      return;
    }
    var children = parent.childNodes;
    var idx = -1;
    for (var i = 0; i < children.length; i++) {
      var child = children.item(i);
      if (child.nodeName == nodeName) {
        idx++;
        callback(child, idx);
      }
      this.visitNodes(child, nodeName, callback);
    }
  }
}

SearchUtil = new function () {
  this.validateRouteSegment = function (theForm, idx) {
    var startPoint = Util.findFormElement(theForm, "routeSegment[" + idx + "].startPoint");
    var endPoint = Util.findFormElement(theForm, "routeSegment[" + idx + "].endPoint");
    var dateStr = Util.findFormElement(theForm, "routeSegment[" + idx + "].dateStr");
    if ((startPoint == null) || (endPoint == null) || (dateStr == null)) {
      return null;
    }
    if (Util.isBlank(startPoint.value)) {
      alert(Resources.ERR_INVALID_START_POINT);
      startPoint.focus();
      return false;
    }
    if (Util.isBlank(endPoint.value)) {
      alert(Resources.ERR_INVALID_END_POINT);
      endPoint.focus();
      return false;
    }
    if (startPoint.value == endPoint.value) {
      alert(Resources.ERR_INVALID_START_END_POINTS);
      endPoint.focus();
      return false;
    }
    if (!DateUtil.isValidDateString(dateStr.value, Resources.DATE_FORMAT)) {
      alert(Resources.ERR_INVALID_OUT_DATE);
      dateStr.focus();
      return false;
    }
    return true;
  }
  
  this.doSearch = function (theForm) {
    var idx = 0;
    while (true) {
      var validationResult = this.validateRouteSegment(theForm, idx);
      if (validationResult == null) {
        break;
      }
      if (validationResult == false) {
        return false;
      }
      idx++;
    }
    if ((theForm.routeType != null) && ((theForm.routeType.value == "1")
        || ((theForm.routeType[0] != null)
        && theForm.routeType[0].checked))) {
      if (!DateUtil.isValidDateString(theForm.returnDateStr.value,
          Resources.DATE_FORMAT)) {
        alert(Resources.ERR_INVALID_IN_DATE);
        theForm.returnDateStr.focus();
        return false;
      }
    }
    if ((theForm.searchMode != null) && ((theForm.searchMode.value == "2")
        || ((theForm.searchMode[1] != null)
        && theForm.searchMode[1].checked))
        && (theForm.returnDateStr != null)) {
      var datesCheckResult = DateUtil.checkInOutDates(
        theForm["routeSegment[0].dateStr"].value,
        theForm.returnDateStr.value, Resources.DATE_FORMAT,
        !isRoundTrip(theForm));
      if (datesCheckResult != null) {
        alert(datesCheckResult);
        return false;
      }
    }
    Splash.show();
    return true;
    function isRoundTrip(theForm) {
      return (theForm.routeType != null) && ((theForm.routeType.value == 1)
        || ((theForm.routeType[0] != null)
        && theForm.routeType[0].checked));
    }
  }
  
  this.airVendorsChanged = function (theForm, forceSelection) {
    theForm.anyAirVendor[0].checked = !forceSelection;
    theForm.anyAirVendor[1].checked = forceSelection;
    if (forceSelection) {
      var selectedCount = 0;
      var opts = theForm.airVendors.options;
      var optLen = opts.length;
      for (var i = 0; i < optLen; i++) {
        if (opts[i].selected) {
          selectedCount++;
        }
        if (selectedCount > 3) {
          break;
        }
      }
      if (selectedCount == 0) {
        opts[0].selected = true;
      }
    }
  }
  
  this.routeSegmentDateChanged = function (field) {
    var theForm = field.form;
    if (!DateUtil.isValidDateString(field.value, Resources.DATE_FORMAT)) {
      return;
    }
    if (!theForm.returnDateStr) {
      return;
    }
    var outDate = Date.parseDate(field.value, Resources.DATE_FORMAT);
    if (!DateUtil.isValidDateString(theForm.returnDateStr.value,
        Resources.DATE_FORMAT)) {
      outDate.setDate(outDate.getDate() + 7);
      theForm.returnDateStr.value = outDate.print(Resources.DATE_FORMAT);
      return;
    }
    var inDate = Date.parseDate(theForm.returnDateStr.value,
      Resources.DATE_FORMAT);
    if (inDate.getTime() <= outDate.getTime()) {
      outDate.setDate(outDate.getDate() + 7);
      theForm.returnDateStr.value = outDate.print(Resources.DATE_FORMAT);
    }
  }
  
  this.updateSegmentBoxes = function () {
    var children =
      Util.getElementInAllB("routeSegment_0").parentNode.childNodes;
    var idx = -1;
    for (var i = 0; i < children.length; i++) {
      var child = children.item(i);
      var id =
        (child.getAttribute != null) ? child.getAttribute("id") : null;
      if (("TABLE" == child.nodeName) && (id != null)
          && (id.indexOf("routeSegment_") == 0)) {
        idx++;
        if (idx > 0) {
          this.updateSegmentBox(child, idx);
        }
      }
    }
  }

  this.updateSegmentBox = function (node, idx) {
    node.setAttribute("id", "routeSegment_" + idx);
    var removeRouteSegmentBoxNode =
      DomUtil.findChild(node, "TR", "removeRouteSegmentBox");
    DomUtil.findChild(removeRouteSegmentBoxNode, "A").setAttribute("href",
        "javascript:SearchUtil.deleteRouteSegment('routeSegment_"
        + idx + "')");
    removeRouteSegmentBoxNode.style.display =
      document.all ? "block" : "table-row";
    var replaceIdxFunc = function(nd) {
      if (nd.name != null) {
        nd.name = nd.name.replace(
          /routeSegment\[\d+\]/g, "routeSegment[" + idx + "]");
      }
      if (nd.id != null) {
        nd.id = nd.id.replace(/\[\d+\]/g, "[" + idx + "]");
      }
    };
    DomUtil.visitNodes(node, "INPUT", replaceIdxFunc);
    DomUtil.visitNodes(node, "SELECT", replaceIdxFunc);
    DomUtil.visitNodes(node, "A", replaceIdxFunc);
    DomUtil.visitNodes(node, "A", function(nd) {
      if (nd.id == "geoNav[" + idx + "].startPoint") {
        nd.onclick = function(event) {
          GeoNavigator.show(DomUtil.findParent(nd, "FORM"),
            "routeSegment[" + idx + "].startPoint",
            document.all ? window.event : event);
        }
      } else if (nd.id == "geoNav[" + idx + "].endPoint") {
        nd.onclick = function(event) {
          GeoNavigator.show(DomUtil.findParent(nd, "FORM"),
            "routeSegment[" + idx + "].endPoint",
            document.all ? window.event : event);
        }
      }
    });
    DomUtil.visitNodes(node, "INPUT", function(nd) {
      if (nd.id != null) {
        nd.id = nd.id.replace(/dateStr_\d+/g, "dateStr_" + idx);
      }
    });
    DomUtil.visitNodes(node, "IMG", function(nd) {
      if (nd.id != null) {
        nd.id = nd.id.replace(/dateTrigger_\d+/g, "dateTrigger_" + idx);
      }
    });
    Calendar.setup({
      inputField  : "dateStr_" + idx,
      ifFormat    : Resources.DATE_FORMAT,
      button      : "dateTrigger_" + idx,
      firstDay    : 1,
      electric    : false,
      cache       : true,
      disableFunc : isRouteSegmentDateDisabled
    });
  }
  
  this.addRouteSegment = function () {
    var src = Util.getElementInAllB("routeSegment_0");
    var dest = src.cloneNode(true);
    DomUtil.visitNodes(dest, "INPUT", function(nd) {
      nd.value = "";
    });
    src.parentNode.insertBefore(dest,
      Util.getElementInAllB("returnDateBox"));
    this.updateSegmentBoxes();
  }
  
  this.deleteRouteSegment = function (segmentId) {
    var routeSegmentBoxNode = Util.getElementInAllB(segmentId);
    if (routeSegmentBoxNode == null) {
      return;
    }
    routeSegmentBoxNode.parentNode.removeChild(routeSegmentBoxNode);
    this.updateSegmentBoxes();
  }
  
  this.deleteAllRouteSegments = function () {
    var idx = 1;
    var doUpdate = false;
    while (true) {
      var routeSegmentBoxNode =
        Util.getElementInAllB("routeSegment_" + idx);
      if (routeSegmentBoxNode == null) {
        break;
      }
      routeSegmentBoxNode.parentNode.removeChild(routeSegmentBoxNode);
      doUpdate = true;
      idx++;
    };
    if (doUpdate) {
      this.updateSegmentBoxes();
    }
  }
  
  this.routeTypeChanged = function (theForm) {
    if (theForm.routeType[0].checked) {
      // RT
      theForm.searchMode[0].disabled = false;
      Util.getElementInAllB("tariffModeBox").style.display =
        document.all ? "block" : "table-row";
      theForm.returnDateStr.disabled = false;
      theForm.returnTimeInterval.disabled = false;
      Util.getElementInAllB("returnDateBox").style.display = "block";
      Util.getElementInAllB("newRouteSegmentBox").style.display = "none";
      this.deleteAllRouteSegments();
    } else if (theForm.routeType[1].checked) {
      // OW simple
      theForm.searchMode[0].disabled = false;
      Util.getElementInAllB("tariffModeBox").style.display =
        document.all ? "block" : "table-row";
      theForm.returnDateStr.disabled = true;
      theForm.returnTimeInterval.disabled = true;
      Util.getElementInAllB("returnDateBox").style.display = "none";
      Util.getElementInAllB("newRouteSegmentBox").style.display = "none";
      this.deleteAllRouteSegments();
    } else {
      // OW complex
      if (theForm.searchMode[0].checked) {
        theForm.searchMode[1].checked = true;
      }
      theForm.searchMode[0].disabled = true;
      Util.getElementInAllB("tariffModeBox").style.display = "none";
      theForm.returnDateStr.disabled = true;
      theForm.returnTimeInterval.disabled = true;
      Util.getElementInAllB("returnDateBox").style.display = "none";
      Util.getElementInAllB("newRouteSegmentBox").style.display = "block";
    }
  }
}