/**
* Форма поиска
*
* @version 4.1
* Правила встраивания поисковой формы на HTML-страницу:
Для доступа к возможностям поисковой формы на странице надо прописать ссылку для загрузки
данного скрипта, вот так:
Ссылка для загрузки скрипта может располагаться в любом месте страницы,
но ДО вызова конструктора объекта ExatSearchForm.
После закрытия тега нужно создать объект ExatSearchForm
и вызвать его метод initForm().
Все элементы управления на поисковой форме необязательны, но если в ней
встретятся элементы управления с префиксом из имени формы, сконкатенированным
с одним из зарезервированных id, то методы объекта ExatSearchForm
будут соответствующим образом манипулировать их содержимым.
Теоретически на странице может быть несколько поисковых форм, но они должны быть
с разными id, и для каждой должен быть создан свой экземпляр объекта ExatSearchForm.
Пример:
*/
/** Конструктор класса ExatSearchForm.
* @access public
* @param formId - значение атрибута id тега form, для которого конструируется
* объект. Загрузка HTML-текста формы в момент конструирования объекта необязательна.
* @param clientId - зашифрованный идентификатор клиентских настроек
* @param defaults - необязательный объект, значения по умолчанию для параметров
* поиска, которые будут использованы при отсутствии свойств параметра values
* метода initForm,либо при сбросе после ошибки. Поддерживаемые свойства:
* departureId - код точки отправления. По умолчанию 64(Москва).
* tourTypeIds - коды туров через запятую. По умолчанию - все типы туров.
* countryId - код страны. По умолчанию 0 (не выбрана).
* countryFilter - id групп стран через запятую.
* countryIncTrans - значение галочки "только с вкл. перелётом": 0=не зависит от страны,
* 1=зависит от страны. По умолчанию 1.
* resortIds - коды курортов через запятую. По умолчанию - все курорты.
* minDate - дата тура "от" в формате "DD.MM.YYYY".
* Пустая строка (не путать с null или undefined) = без ограничений.
* minDateOffset - смещение в днях от текущей даты для даты тура "от".
* По умолчанию - неделя вперёд от текущей даты. Игнорируется при наличии minDate.
* maxDate - дата тура "до" в формате "DD.MM.YYYY".
* Пустая строка (не путать с null или undefined) = без ограничений.
* maxDateOffset - смещение в днях от текущей даты для даты тура "до".
* По умолчанию - две недели вперёд от текущей даты. Игнорируется при наличии maxDate.
* minDuration - длительность тура "от" в днях. По умолчанию - 8 дней (неделя). 0=[все]
* maxDuration - длительность тура "до" в днях. По умолчанию - 8 дней (неделя). 0=[все]
* minNightsDuration - длительность тура "от" в ночях. По умолчанию - 7 ночей (неделя). 0=[все]
* maxNightsDuration - длительность тура "до" в ночях. По умолчанию - 7 ночей (неделя). 0=[все]
* categoryIds - коды категорий отелей через запятую. По умолчанию - все категории.
* hotelIds - коды отелей через запятую. По умолчанию - все отели (ограничены только категориями).
* minAmount - цена "от" в валюте currencyId.
* maxAmount - цена "до" в валюте currencyId.
* currencyId - код валюты. По умолчанию - доллары, если для страны нет своей валюты по умолчанию.
* foodTypeIds - коды типов питания через запятую. По умолчанию - все типы питания.
* serviceIds - коды услуг через запятую. По умолчанию - все услуги.
* accommodation - размещение в виде строки ВЗР_РЕБ
* show123Acc - 0 или 1: отображать ли размещение 1/2/3 взрослых
* в списке доступных размещений, если есть DBL. По умолчанию 1.
* ages - возраста детей через запятую
* transportRequired - 0 или 1: искать ли только туры с включённым перелётом.
* По умолчанию 1, но зависит от countryIncTrans
* resortFilter - 0 или 1, поиск маршрутов только по выбранным курортам/странам, и ни по каким другим.
* resultType - 'tours' или 'hotels': в каком виде будут представлены результаты поиска -- в виде списка туров или списка отелей.
* дополнительные поля, только для профессиональной версии:
* tourOperatorIds - коды туроператоров через запятую. По умолчанию - все "предпочтительные" туроператоры.
* includeStop - 0 или 1: показывать ли остановленные продажи. По умолчанию 0.
* limit - количество строк в странице результатов. По умолчанию 20.
* showTourCount - битовая маска, управляющая показом числа туров в опциях списков выбора (1 -- отправление, 2 -- страна, 4 -- курорт, 8 -- отель). По умолчанию 0.
* resortDepth - глубина отображения дерева курортов (1 -- показывать только подкурорты страны первого уровня, напр. Болгария / Банско)
* @param host - необязательный параметр, указывающий имя HTTP-хоста, с которого будут подгружаться данные.
* По умолчанию равен "http://exat.ru"
* @param params - необязательный параметр (ассоциативный массив).
* params[newWindowParams] - свойства нового окна (2-ой аргумент метода window.open)
* По умолчанию равен "resizable=yes, scrollbars=yes"
* params[alertLocks] - блокировка уведомлений об ошибках
*/
var allCountryText;
function ExatSearchForm(formId, clientId, defaults, host, params)
{
this.clientId = clientId;
this.formId = formId;
this.host = (typeof(host)=='undefined') ? "http://exat.ru" : host;
this.params = (typeof(params)=='undefined') ? { newWindowParams : 'resizable=yes, scrollbars=yes' } : params;
window.exatForms[formId] = this;
// константы
this.ONE_HOUR_MS = 1000 * 3600; //количество миллисекунд в часе
this.ONE_DAY_MS = 1000 * 3600 * 24; //количество миллисекунд в сутках
this.DEF_HOURS = 4;
this.MAX_TOUR_DAYS = 22; // максимальное количество дней для генерации из суточных цен
//специальные константы для случаев, когда ничего не выбрано
this.ALL_TOUR_TYPES = 0xffffffff;
this.ALL_CATEGORIES = 0xffffffff;
this.ALL_FOOD_TYPES = 0xffffffff;
this.ALL_ACCOMMODATIONS = 0xffffffff;
this.MAX_AMOUNT = 999999999;
this.ACC_TEXT = new Array( '1 / 2 / 3 взр',
'1 взр', '2 взр', '3 взр', '4 взр', '5 взр', '6 взр', '7 взр', '8 взр',
'9 взр', '10 взр', '11 взр', '12 взр','13 взр', '14 взр', '15 взр', '16 и более взр',
'1 взр + 1 реб', '1 взр + 2 реб', '1 взр + 3 реб', '1 взр + 4 и более детей',
'2 взр + 1 реб', '2 взр + 2 реб', '2 взр + 3 реб', '2 взр + 4 и более детей',
'3 взр + 1 реб', '3 взр + 2 реб', '3 взр + 3 реб', '3 взр + 4 и более детей',
'4 и более взр + 1 реб', '4 и более взр + 2 реб', '4 и более взр + 3 реб', '4 и более взр + 4 и более детей'
);
this.ACC_VAL = new Array(0,
'1_0', '2_0', '3_0', '4_0', '5_0', '6_0', '7_0', '8_0',
'9_0','10_0','11_0','12_0','13_0','14_0','15_0','16_0',
'1_1', '1_2', '1_3', '1_4', '2_1', '2_2', '2_3', '2_4',
'3_1', '3_2', '3_3', '3_4', '4_1', '4_2', '4_3', '4_4');
this.CAT_TEXT = new Array('[все]', '5*', '4*', '3*', '2*', '1*', 'HV-1', 'HV-2', 'без кат.');
this.CAT_VAL = new Array(this.ALL_CATEGORIES, '5', '4', '3', '2', '1', '17', '16', '0');
this.CAT_NEW_VAL = new Array(this.ALL_CATEGORIES, '11,10', '9,8', '7,6', '5,4', '3,2', '17', '16', '0');
this.departureData = null; //ассоциативный массив: код точки отправления=>Array(название,маска доступных типов туров, Array(код страны, ...))
this.tourTypeData = null; //ассоциативный массив: код типа тура=>название типа тура
this.countryData = null; //ассоциативный массив: код страны=>Array(название страны, маска типов туров)
this.foodTypeData = null; //ассоциативный массив: код типа питания=>название типа питания
this.currencyData = null; //ассоциативный массив: код валюты=>название валюты
this.servicesData = null; //ассоциативный массив: код услуги=>Array()
this.tourOperatorData = null; //ассоциативный массив: код туроператора=>название туроператора
this.resortData = []; //ассоциативный массив: 'x'+код точки отправления+'-'+код страны => Array()
/* Идентификаторы элементов управления внутри формы,
* которыми умеет манипулировать ExatSearchForm
* Предполагается, что на странице перед каждым идентификатором
* будет префикс в виде идентификатора формы
*
* Элементы управления профессиональной версии (отображение стопов, технической информации,
* переключатель старого/нового вида результатов поиска) здесь не отражены,
* для них обработчики надо прописывать явно
*/
this.controls = [
{name:'DepartureCtrl', onchange:1},
{name:'TourTypeCtrl', onchange:1},
{name:'CountryCtrl', onchange:1},
{name:'CountryFilterCtrl', onchange:1},
{name:'ResortCtrl', onchange:1},
{name:'MinDateCtrl', onchange:1},
{name:'MaxDateCtrl', onchange:1},
{name:'MinDurationCtrl', onchange:1},
{name:'MaxDurationCtrl', onchange:1},
{name:'MinNightsDurationCtrl', onchange:1},
{name:'MaxNightsDurationCtrl', onchange:1},
{name:'MinAmountCtrl', onchange:1},
{name:'MaxAmountCtrl', onchange:1},
{name:'CurrencyCtrl', onchange:1},
{name:'CategoryCtrl', onchange:1},
{name:'HotelCtrl', onchange:1},
{name:'FoodTypeCtrl', onchange:1},
{name:'AccommodationCtrl', onchange:1},
{name:'AgeCtrl', onchange:1},
{name:'ServiceCtrl', onchange:1},
{name:'TourOperatorCtrl', onchange:1},
{name:'TransportRequiredCtrl', onclick:1},
{name:'ResortFilterCtrl', onchange:1},
{name:'LimitCtrl', onchange:1},
{name:'ResultTypeCtrl', onchange:1},
{name:'SubmitCtrl', onclick:1},
{name:'ResetCtrl', onclick:1}
];
this.initTimeout = 0; //сброс таймера начальной инициализации для initForm
this.resortException = false; //специальный случай комбинации страна/тип тура/точка отправления, по которой нет туров
this.nextNewWindowName = this.generateNewWindowName(); //заранее определяем имя нового окна для тестирования
this.prefTourOperators = ''; //список предпочтительных туроператоров, действующий, когда выбран пункт "все"
//предусмотрим вариант отсутствия аргумента values совсем
this.defaults = (typeof(defaults)=='undefined' || defaults==null) ? {} : defaults;
var htmlDefaults=window[this.formId + 'Defaults'];
if(htmlDefaults)
this.defaults=htmlDefaults;
this.defaults.minDate = '23.02.2012';
this.defaults.maxDate = '01.03.2012';
if(this.defaults.countryId==null) this.defaults.countryId = 0;
if(this.defaults.minNightsDuration==null) this.defaults.minNightsDuration = 7;
if(this.defaults.maxNightsDuration==null) this.defaults.maxNightsDuration = 14;
if(this.defaults.minDuration==null) this.defaults.minDuration = 0;
if(this.defaults.maxDuration==null) this.defaults.maxDuration = 0;
if(this.defaults.departureId==null) this.defaults.departureId = 64;/* Москва */
if(this.defaults.countryFilter==null) this.defaults.countryFilter = 0;
if(this.defaults.countryIncTrans==null) this.defaults.countryIncTrans = 1;
if(this.defaults.minDateOffset==null) this.defaults.minDateOffset = 7;
if(this.defaults.maxDateOffset==null) this.defaults.maxDateOffset = 21;
if(this.defaults.minAmount==null) this.defaults.minAmount = 0;
if(this.defaults.maxAmount==null) this.defaults.maxAmount = this.MAX_AMOUNT;
if(this.defaults.currencyId==null) this.defaults.currencyId = 'undefined';
if(this.defaults.show123Acc==null) this.defaults.show123Acc = 1;
if(this.defaults.transportRequired==null) this.defaults.transportRequired = 1;
if(this.defaults.resortFilter==null) this.defaults.resortFilter = 0;
if(this.defaults.accommodation==null) this.defaults.accommodation = 0;
if(this.defaults.includeStop==null) this.defaults.includeStop = 0;
if(this.defaults.showTechInfo==null) this.defaults.showTechInfo = 0;
if(this.defaults.showTourOperator==null) this.defaults.showTourOperator = 0;
if(this.defaults.limit==null) this.defaults.limit = 20;
if(this.defaults.showTourCount==null) this.defaults.showTourCount = 0;
if(this.defaults.resortDepth==null) this.defaults.resortDepth = 1;
if(this.defaults.resultType==null) this.defaults.resultType = 'tours';
//загрузка дополнительных скриптов в конце конструктора инициализации, иначе Opera выполняет сначала эти подгруженные скрипты, а потом уже остальную часть конструктора
this.AutoRefreshTimeout = 720000; //Период автоматической перезагрузки данных формы во избежание устаревания
this.loadPrefData();
this.loadInitData();
}
ExatSearchForm.prototype.loadPrefData = function() {
if(typeof(exatPrefData) == 'undefined') {
exatPrefData = [];
}
//если динамические настройки предпочтения ещё не загружены для предыдущей формы, загружаем
if(typeof(exatPrefData[this.clientId]=='undefined')) {
document.write('');
}
}
ExatSearchForm.prototype.loadInitData = function() {
// Последний выполненный запрос будет автоматически повторяться, чтобы данные не устаревали
if (this.LoadResortTimeout != null) {
clearTimeout(this.LoadResortTimeout);
}
if (this.LoadInitTimeout != null) {
clearTimeout(this.LoadInitTimeout);
}
this.LoadInitTimeout = setTimeout('exatForms.' + this.formId + '.loadInitData()', this.AutoRefreshTimeout);
//загрузим начальные общие справочники
this.loadScript(this.host
+ '/touronline/?jsapp=getjs&ver=4&file=data&form_id='
+ this.formId
+ '&showTourCount='
+ this.defaults.showTourCount
+ (this.clientId ? '&client_id=' + this.clientId : ''));
}
ExatSearchForm.prototype.getInitVal = function(name) {
if(this.values!=undefined && this.values[name]!=null) {
return this.values[name];
}
else {
return this.defaults[name];
}
}
ExatSearchForm.prototype.getInitArr = function(name) {
var strIds='';
if(this.values!=undefined && this.values[name]!=null) {
if(this.values[name]=="")
return [];
else
strIds=this.values[name];
}
else if(this.defaults!=undefined && this.defaults[name]!=null) {
if(this.defaults[name]=="")
return [];
else
strIds=this.defaults[name];
}
else {
return [];
}
strIds=String(strIds);
strIds=strIds.replace(/^,/,'');
return strIds.split(",");
}
ExatSearchForm.prototype.array2hash = function(arraydata){
var hashdata=new Array();
for(var i=0; i= 150) {
throw new Error('Не удалось инициализировать поисковую форму в течении 30 сек.' +
' Причина: ' + reason +
'. Попробуйте перезагрузить страницу (удерживая клавишу Ctrl, нажмите F5).' +
' В случае повторного появления ошибки ' +
'обратитесь в службу технической поддержки');
return;
}
else {
this.initTimeout++;
setTimeout('window.exatForms[\''+this.formId+'\'].initForm()', 200);
return;
}
}
this.form = document.getElementById(this.formId);
if(!this.form) {
this.reportError('Форма с id="'+this.formId+'" не найдена');
return;
}
// запрет сабмита по нажатие Enter в текстовом поле формы, так как в этом случае не запускается обработчик
this.form.onsubmit=function(){return false;};
this.departureId = this.getInitVal('departureId');
this.countryId = this.getInitVal('countryId');
this.resortIds = [];
var ids = this.getInitArr('resortIds');
for(var i=0; i0) ? this.minAmount : '';
}
ctrl = this.form.elements[this.formId + 'MaxAmountCtrl'];
if(ctrl) {
ctrl.value = (this.maxAmount < this.MAX_AMOUNT && this.maxAmount>0) ? this.maxAmount : '';
}
//установка обработчиков событий
for (var i = 0; i < this.controls.length; i++) {
var c = this.form.elements[this.formId + this.controls[i].name];
if(c) {
if(!c.onchange && this.controls[i].onchange) {
c.onchange = new Function(
"window.exatForms['" + this.formId + "'].on"
+ this.controls[i].name + "Change" + "()");
}
if(!c.onclick && this.controls[i].onclick) {
c.onclick = new Function(
"window.exatForms['" + this.formId + "'].on"
+ this.controls[i].name + "Click" + "()");
}
}
}
this.enableControls();
this.resortException = false;
if(typeof(this.values)!='undefined') {
delete this.values;
}
this.initTimeout = 0;
if(this.form.elements[this.formId + 'IncludeStopCtrl']){
var checkIncludeStop=this.form.elements[this.formId + 'IncludeStopCtrl'];
checkIncludeStop.checked=this.includeStop;
}
if(this.form.elements[this.formId + 'ShowTechInfoCtrl']){
var checkShowTechInfo=this.form.elements[this.formId + 'ShowTechInfoCtrl'];
checkShowTechInfo.checked=this.showTechInfo;
}
if(this.form.elements[this.formId + 'ShowTourOperatorCtrl']){
var checkShowTourOperator=this.form.elements[this.formId + 'ShowTourOperatorCtrl'];
checkShowTourOperator.checked=this.showTourOperator || this.showTechInfo;
checkShowTourOperator.disabled=this.showTechInfo;
}
this.formInitAutoAppend();
}
ExatSearchForm.prototype.formInitAutoAppend = function(){
}
ExatSearchForm.prototype.test = function(){
//D EBUG BEGIN
var res = [];
obj=this.hotelIds;
for (var prop in obj) {
//return;
if (obj.hasOwnProperty(prop)) {
if (useValues=0 && (typeof(obj[prop]) != 'boolean') && (obj[prop] == Number(obj[prop]))){
res.push(obj[prop]);
} else if (prop == Number(prop)) {
res.push(prop);
}
}
}
var rrr=res.join(',');
alert(rrr);
//D EBUG END
}
/**
* Зависимость пункта отправления "Без перелета" и чекбокса "Без перелета"
**/
/**
* селект -> чекбокс
**/
ExatSearchForm.prototype.Departure2TransportReq=function(){
this.transportRequired = this.departureId!=1
var c = this.form.elements[this.formId+'TransportRequiredCtrl'];
if(c) {
exatSetCheckedValue(c, this.transportRequired);
}
}
/**
* чекбокс -> селект
**/
ExatSearchForm.prototype.TransportReq2Departure=function(){
var transportReq=this.form.elements[this.formId +'TransportRequiredCtrl'].checked;
//смена в селекте места отправления
if(transportReq){// выбрать прежний город
if(!this.departurePrevId)// если последний город не известен
this.departurePrevId=this.defaults.departureId;// то установить дефолтный
this.departureId=this.departurePrevId;// установить предыдущий город текущим
}else{// выбрать "без перелета"
this.departurePrevId=this.departureId;// запомнить последний город
this.departureId=1;// установить городом отправления "без перелета"
}
var c = this.form.elements[this.formId +'DepartureCtrl'];
for(var i=0;i 0) {
q.push(['transportRequired', 1]);
}
if(this.resortFilter > 0) {
q.push(['selectedPlacesOnly', 1]);
}
if(this.countryFilter) {
if (this.countryFilter instanceof Array) {
q.push(['countryFilter', exatJoinNumbers(this.countryFilter, true)]);
} else {
q.push(['countryFilter', +this.countryFilter]);
}
}
if(this.includeStop > 0) {
q.push(['includeStop', 1]);
}
if(!this.resortIds || !this.resortIds.length) {
q.push(['placeGroupId[]', this.countryId ]);
q.push(['placeItemId[]', this.countryId ]);
}
else {
var resortStr = exatJoinNumbers(this.resortIds, /*isArray=*/ false);
if(resortStr.length) {
q.push(['placeGroupId[]', resortStr ]);
q.push(['placeItemId[]', resortStr ]);
}
else {
q.push(['placeGroupId[]', this.countryId ]);
q.push(['placeItemId[]', this.countryId ]);
}
}
if(this.tourTypeMask!=this.ALL_TOUR_TYPES) {
var a = '';
for(var i=0; i<31; ++i) {
if(this.tourTypeMask & (1< 0) {
q.push(['minDate', exatFromTime(this.minTimestamp)]);
}
if(this.maxTimestamp > 0) {
q.push(['maxDate', exatFromTime(this.maxTimestamp)]);
}
if(this.minDuration > 0) {
q.push(['minDuration', this.minDuration]);
}
if(this.maxDuration > 0) {
q.push(['maxDuration', this.maxDuration]);
}
if(this.minNightsDuration > 0) {
q.push(['minNightsDuration', this.minNightsDuration]);
}
if(this.maxNightsDuration > 0) {
q.push(['maxNightsDuration', this.maxNightsDuration]);
}
if(this.minAmount > 0) {
q.push(['minAmount', this.minAmount]);
}
if(this.maxAmount!=this.MAX_AMOUNT) {
q.push(['maxAmount', this.maxAmount]);
}
if(this.accommodationId > 0) {
q.push(['accommodation', this.ACC_VAL[this.accommodationId]]);
}
if(this.ages && this.ages.length) {
q.push(['ages[]', this.ages]);
}
var hotels = exatJoinNumbers(this.hotelIds, /*isArray=*/ false);//у отелей могут быть отрицательные id, поэтому свойство length массива проверять нельзя
if(hotels.length) {
q.push(['hotelId[]', hotels]);
}
if(!!this.serviceIds && this.serviceIds.length) {
q.push(['serviceId[]', exatJoinNumbers(this.serviceIds, /*isArray=*/ false)]);
}
if(this.tourOperatorIds && this.tourOperatorIds.length) {
var str = exatJoinNumbers(this.tourOperatorIds, /*isArray=*/ false);
if(str.length) {
q.push(['tourOperatorId[]', str]);
}
}
else {
if(this.prefTourOperators.length > 0) {
q.push(['tourOperatorId[]', this.prefTourOperators]);
}
}
if (this.resultType != 'tours') {
q.push(['resultType', this.resultType]);
}
return q;
}
/** Сконвертировать объект с параметрами запроса в строку суффикса
* @access public
* @param sdata объект с параметрами для конвертации в строку запроса,
* полученный, например, через getSubmitData
* @return URL suffix to append to search query
*/
ExatSearchForm.prototype.getSubmitSuffix = function(sdata)
{
var result = '';
for(var i=0; i< sdata.length; ++i) {
result += '&' + sdata[i][0] + '=' + sdata[i][1];
}
return result;
}
/** Получить стандартный префикс для action
* @access public
* @return строка префикса
*/
ExatSearchForm.prototype.getSubmitPrefix = function()
{
return '/tour_search1.php';
}
/** Отправить поисковый запрос
* @access public
* @param openNewWindow - если true, то будет открыто новое окно
* @param customAction - если не пуст, то запрос будет отправлен на указнный action url
*/
ExatSearchForm.prototype.submitForm = function(openNewWindow, customAction)
{
if (!this.checkParameters()) {
return false;
}
var holder=window.document.location.protocol+'//'+window.document.location.hostname+'/';
this.form.action = this.getSubmitPrefix()
;
if(openNewWindow) {
var wnd = window.open('', this.nextNewWindowName, this.params['newWindowParams']);
wnd.document.write('Пожалуйста, подождите. Идет поиск туров...');
wnd.focus();
this.form.method='post';
this.form.target = this.nextNewWindowName;
this.nextNewWindowName = this.generateNewWindowName();
}
this.form.submit();
}
ExatSearchForm.prototype.onSubmitCtrlClick = function()
{
this.submitForm(0);
}
ExatSearchForm.prototype.onResetCtrlClick = function()
{
this.initForm();
}
ExatSearchForm.prototype.resetForm = function()
{
this.initForm();
}
ExatSearchForm.prototype.generateNewWindowName = function()
{
return 'result_' + exatGenRandomStr(10);
}
/**
* Динамическая загрузка скрипта
*/
ExatSearchForm.prototype.loadScript = function(url) {
var s = document.createElement('script');
s.src = url;
s.language = 'javascript';
try {
s.charset = 'Windows-1251';
} catch (e) {}
// Dirty fix for an occasional IE7 bug
document.body.insertBefore(s, document.body.firstChild);
}
/** Динамическая асинхронная загрузка данных курортов и др. после выбора страны.
* @access protected, но предназначена для вызова только из скриптов системы "Ехать!"
*/
ExatSearchForm.prototype.asyncLoadResort = function() {
// Последний выполненный запрос будет автоматически повторяться, чтобы данные не устаревали
if (this.LoadResortTimeout != null) {
clearTimeout(this.LoadResortTimeout);
}
if (this.LoadInitTimeout != null) {
clearTimeout(this.LoadInitTimeout);
}
this.LoadResortTimeout = setTimeout('exatForms.' + this.formId + '.asyncLoadResort()', this.AutoRefreshTimeout);
this.loadScript(this.host + '/touronline/?jsapp=getjs&ver=4&file=data-'
+ this.departureId + '-' + this.countryId
+ '&form_id=' + this.formId
+ '&showTourCount=' + this.showTourCount
+ (this.clientId ? '&client_id=' + this.clientId : ''));
}
/** Заполнение списка курортов и зависимых от них данных.
* @access public, но предназначена для вызова только из скриптов системы "Ехать!"
*/
ExatSearchForm.prototype.fillResort = function()
{
this.initResortCtrl();
this.initLCDCtrl();
this.initCategoryCtrl();
this.initFoodTypeCtrl();
this.initAccommodationCtrl();
this.initHotelCtrl();
this.initTourOperatorCtrl();
this.enableControls();
}
/** Заполнение данных, привязанных к текущим выбранным точке отправления и стране
* @access public, но для вызова только из скриптов "Ехать!"
* @param departureId - код точки отправления
* @param countryId - код страны
* @param propName - имя свойства, куда вписать массив данных
* @param propVal - данные
*/
ExatSearchForm.prototype.setResortParam = function(departureId, countryId, propName, propVal) {
var id = 'x' + departureId + '-' + countryId;
if (!this.resortData[id]) {
this.resortData[id] = [];
}
this.resortData[id][propName] = propVal;
}
/** Получить данные свойства, учитывая выбранную точку отправления и страну
* @access protected
* @param propName имя свойства
* @return null, если не выбрана страна или данные ещё не загружены, иначе -
* значение свойства с именем propName
*/
ExatSearchForm.prototype.getResortData = function(propName)
{
if (!this.countryId) {
return null;
}
var id = 'x' + this.departureId + '-' + this.countryId;
if (!this.resortData[id]) {
this.asyncLoadResort();//отдадим команду на загрузку данных
return null;//но не будем дожидаться загрузки
}
return this.resortData[id][propName];
}
/** Возвратить строку символов с объёдинёнными битами дат/длительностей по курортам
* В каждом символе используется только шесть бит
* @param indx 0=даты, 1=длительности
* @return строка с символами с установленными битами
*/
ExatSearchForm.prototype.getString6 = function(indx)
{
var r = this.getResortData('lcd');
if(r==null) {
reportWarning("Не выбрана страна или не загружены данные курортов");
return '';
}
var res = '';
var allResorts = true; //выбраны [все] курорты
for(var resortId in this.resortIds) {
if(resortId != Number(resortId)) continue;
allResorts = false;
break;
}
for(resortId in r) {
if(resortId != Number(resortId)) continue;
if(allResorts || this.resortIds[resortId]) {
var str = r[resortId][indx];
if (str.length < res.length) {
// Если строка с упакованными датами короче текущего значения res, дополним ее пустышками
var padLength = res.length - str.length;
var padString = "";
for (var i = 0; i < padLength; i++) {
padString += '?';
}
str += padString;
}
var len = str.length;
if(res=='') {
for (var i = 0; i < len; i++) {
res += '?';
}
}
var buffer = '';
for (var j = 0; j < len; j++) {
buffer += String.fromCharCode(((str.charCodeAt(j) - 63) | (res.charCodeAt(j) - 63)) + 63);
}
res = buffer;
}
}
return res;
}
/** Заполнить список значений single select "точка отправления" и выбрать одно
* в соответствии с this.departureId
* @access protected
*/
ExatSearchForm.prototype.initDepartureCtrl = function()
{
var c = this.form.elements[this.formId +'DepartureCtrl'];
if (!c || c.nodeName != 'SELECT') {
return 1;
}
exatClearCtrl(c);
var arr = this.departureData;
var f = false;
for (var i in arr) {
if(i!=Number(i)) continue; //пропустим нечисловые свойства
var o = exatCreateOptionElement(i, arr[i][0]);
if (i == this.departureId) {
f = true;
o.setAttribute('selected', 'selected');
}
if (i == 1) { // выделение "без перелета"
o.style.fontWeight = "bold";
}
c.appendChild(o);
}
if (!f){
//не нашли, выбираем первую попавшуюся точку отправления
if(c.firstChild) {
c.firstChild.setAttribute('selected', 'selected');
this.departureId = c.firstChild.value;
}
else {
this.departureId = 0;
this.reportError("Нет доступных точек отправления");
}
}
this.Departure2TransportReq();
}
/** Заполнить список значений single/multi select "типы туров"
* и выбрать одно или несколько значений в соответствии с this.tourTypeMask
* @access protected
*/
ExatSearchForm.prototype.initTourTypeCtrl = function()
{
var c = this.form.elements[this.formId + 'TourTypeCtrl'];
if(!c) {
return 1;
}
exatClearCtrl(c);
//битовая маска доступных типов туров в текущей точке отправления
var availableTourTypes = this.departureData[this.departureId][1];
var firstElement = exatCreateOptionElement(0, '[все]');
if(this.tourTypeMask == this.ALL_TOUR_TYPES) {
firstElement.setAttribute('selected', true);
}
c.appendChild(firstElement);
var allSelected = true;
//в tourTypeId установлен всегда только один бит
for(var tourTypeId in this.tourTypeData) {
if (tourTypeId!=Number(tourTypeId) || !(tourTypeId & availableTourTypes)) {
continue;
}
var o = exatCreateOptionElement(tourTypeId, this.tourTypeData[tourTypeId]);
if (!(tourTypeId & this.tourTypeMask)) {
this.tourTypeMask &= ~tourTypeId;
allSelected = false;
}
c.appendChild(o);
}
var selectTourType=false;
if(allSelected) {
exatSelectChild(firstElement);
selectTourType=true;
}
else {
for (var opt = c.firstChild.nextSibling; opt; opt = opt.nextSibling) {
if(this.tourTypeMask & opt.value) {
exatSelectChild(opt);
selectTourType=true;
}
}
}
if(!selectTourType){
exatSelectChild(firstElement);
}
}
/** Заполнить список значений для select "группа стран"
* @access protected
*/
ExatSearchForm.prototype.initCountryFilterCtrl = function()
{
var c = this.form.elements[this.formId + 'CountryFilterCtrl'];
if(!c || !this.countryGroups) {
return;
}
exatClearCtrl(c);
c.appendChild(exatCreateOptionElement(0, '[все]'));
var countryIds = this.departureData[this.departureId][2];
for (var i = 0; i < this.countryGroups.length; i++) {
var groupIsPopulated = false;
for (var j = 0; j < countryIds.length; j++) {
var countryId = countryIds[j];
if (typeof(this.countryData[countryId]) != 'undefined'
&& this.countryData[countryId][1] & this.tourTypeMask
) {
if (this.countryData[countryId][2]) {
for (var gi = 0; gi < this.countryData[countryId][2].length; gi++) {
if (this.countryData[countryId][2][gi] == this.countryGroups[i][0]) {
groupIsPopulated = true;
break;
}
}
}
}
}
if (!groupIsPopulated) {
continue;
}
c.appendChild(exatCreateOptionElement(this.countryGroups[i]['0'], this.countryGroups[i]['1']));
}
if (!!this.countryFilter) {
var val = this.countryFilter;
if (!(this.countryFilter instanceof Array)) {
val = [+this.countryFilter];
}
for (var i = 0; i < c.options.length; i++) {
for (var j = 0; j < val.length; j++) {
if (c.options[i].value == val[j]) {
c.options[i].selected = true;
}
}
}
}
}
/** Заполнить список значений для single select "страна" и выбрать одно значение
* в соответствии с this.countryId
* @access protected
*/
ExatSearchForm.prototype.initCountryCtrl = function()
{
var c = this.form.elements[this.formId + 'CountryCtrl'];
if(!c) {
return;
}
exatClearCtrl(c);
var f = false;
var availableCountryIds = this.departureData[this.departureId][2];
c.appendChild(exatCreateOptionElement(0, allCountryText?allCountryText:'выберите страну'));
for (var i = 0; i 0 && this.countryIncTrans > 0 &&
typeof(exatPrefData[this.clientId].prefIncludeCheckbox) != 'undefined' &&
typeof(exatPrefData[this.clientId].prefIncludeCheckbox[this.countryId]) != 'undefined')
{
this.transportRequired = exatPrefData[this.clientId].prefIncludeCheckbox[this.countryId] ? 1 : 0;
} else {
this.transportRequired = this.defaults.transportRequired;
}
var c = this.form.elements[this.formId+'TransportRequiredCtrl'];
if(c) {
exatSetCheckedValue(c, this.transportRequired);
}
}
/** Заполнить список значений single/multi select "курорты" и выбрать одно
* или несколько значений в соответствии с массивом this.resortIds
* @access protected
*/
ExatSearchForm.prototype.initResortCtrl = function() {
var c = this.form.elements[this.formId+'ResortCtrl'];
var isSelected=false;
if(!c) {
return 1;
}
exatClearCtrl(c);
if(!Number(this.countryId)) {
return 0;
}
this.foodTypeRange = this.ALL_FOOD_TYPES;
this.categoryRange = this.ALL_CATEGORIES;
this.accommodationRange = this.ALL_ACCOMMODATIONS;
var resortData = this.getResortData('resorts');
if (!resortData) {
return 0;
}
var firstElement = exatCreateOptionElement(this.countryId, '[все]');
c.appendChild(firstElement);
var filled = false;
for (var resortId in resortData) {
if (resortId!=Number(resortId) || !(resortData[resortId][1] & this.tourTypeMask)){
continue;
}
if (resortData[resortId][4] && resortData[resortId][4].length) {
filled = true;
if (resortData[resortId][4].length > ((this.resortDepth + 1) * 7)) {
continue; // отображать курорт не нужно, задана меньшая глубина дерева
}
if (resortData[resortId][4].length <= 7) {
continue; // отображать курорт не нужно, это корневой курорт (страна)
}
}
filled = true;
var opt = exatCreateOptionElement(resortId, resortData[resortId][0]);
if(this.resortIds[resortId]) {
opt.setAttribute('selected', 'selected');
isSelected=true;
this.resortIds[resortId] = 2;
}
var optt = c.appendChild(opt);
if (resortData[resortId][0].charAt(0) != String.fromCharCode(160)) {
optt.style.fontWeight = "bold";
//optt.style.color = "blue";
}
}
//удалим из resortIds невыбранные курорты
for(resortId in this.resortIds) {
if(resortId == Number(resortId) && this.resortIds[resortId] != 2) {
delete this.resortIds[resortId];
}
}
this.resortException = false;
if (!filled) {
this.resortException = true;
return -1;
}
if(!isSelected)
firstElement.setAttribute('selected', true);
return 0;
}
/** Установить значение checkbox "туры только в выбранные курорты"
* в соответствии с this.resortFilter
* @access protected
*/
ExatSearchForm.prototype.initResortFilterCtrl = function()
{
var c = this.form.elements[this.formId+'ResortFilterCtrl'];
if(!c) {
return 1;
}
if (c && c.nodeName == 'INPUT' && c.getAttribute('type') == 'checkbox') {
c.checked = this.resortFilter;
}
}
/** Заполнить список значений single select'ов "дата от"/"до",
* длительность от"/"до" и выбрать значения в соответствии
* с this.minTimestamp, this.maxTimestamp, this.minDuration, this.maxDuration,
* а также this.transportRequired
* @access protected
*/
ExatSearchForm.prototype.initLCDCtrl = function()
{
var oCl, oCh;
var cl, ch;
var ddstr;
var symb;
var tmpDate;
var val, name;
var d0 = this.getResortData('date');
if(d0==null) { //данные не подгружены (возможно, туров нет в этой связке точка отправления/страна)
return;
}
var dNow = new Date();
// Даты
d0.setHours(this.DEF_HOURS);
d0.setMinutes(0);
d0.setSeconds(0);
d0.setMilliseconds(0);
dNow.setHours(this.DEF_HOURS);
dNow.setMinutes(0);
dNow.setSeconds(0);
dNow.setMilliseconds(0);
var zeroTime = d0.getTime();
var nowTime = dNow.getTime();
cnl = this.form.elements[this.formId + 'MinNightsDateCtrl'];
cnh = this.form.elements[this.formId + 'MaxNightsDateCtrl'];
cl = this.form.elements[this.formId + 'MinDateCtrl'];
ch = this.form.elements[this.formId + 'MaxDateCtrl'];
if(cnl) {
exatClearCtrl(cnl);
oCl = exatCreateOptionElement(0, '[все]');
cnl.appendChild(oCl);
}
if (cnh) {
exatClearCtrl(cnh);
oCh = exatCreateOptionElement(0, '[все]');
cnh.appendChild(oCh);
}
if(cl) {
exatClearCtrl(cl);
oCl = exatCreateOptionElement(0, '[все]');
cl.appendChild(oCl);
}
if (ch) {
exatClearCtrl(ch);
oCh = exatCreateOptionElement(0, '[все]');
ch.appendChild(oCh);
}
var loSel = null;
var hiSel = null;
var lonSel = null;
var hinSel = null;
ddstr = this.getString6(0);
for (j = 0; j < ddstr.length; j++) {
symb = ddstr.charCodeAt(j) - 63;
if (symb) {
for (var l = 1; l < 7; l++) {
if (Math.pow(2, l - 1) & symb) {
tmpTime = zeroTime + this.ONE_DAY_MS * (j * 6 + l);
val = tmpTime;
name = exatGetNiceDate(tmpTime);
if(cnl) {
oCnl = cnl.appendChild(exatCreateOptionElement(val, name));
if(this.minTimestamp > 0
&& tmpTime <= this.minTimestamp
) {
//пытаемся выбрать предыдущую дату "от", если нет - то ближайшую более раннюю
lonSel = oCnl;
}
}
if(cnh) {
oCnh = cnh.appendChild(exatCreateOptionElement(val, name));
if(this.maxTimestamp > 0 && !hinSel && tmpTime >= this.maxTimestamp) {
//пытаемся выбрать предыдущую дату "до", если нет - то ближайшую более позднюю
hinSel = oCnh;
}
}
if(cl) {
oCl = cl.appendChild(exatCreateOptionElement(val, name));
if(this.minTimestamp > 0
&& tmpTime <= this.minTimestamp
) {
//пытаемся выбрать предыдущую дату "от", если нет - то ближайшую более раннюю
loSel = oCl;
}
}
if(ch) {
oCh = ch.appendChild(exatCreateOptionElement(val, name));
if(this.maxTimestamp > 0 && !hiSel && tmpTime >= this.maxTimestamp) {
//пытаемся выбрать предыдущую дату "до", если нет - то ближайшую более позднюю
hiSel = oCh;
}
}
}
}
}
}
if(cnl) {
lonSel = lonSel ? lonSel : cnl.firstChild;
this.minTimestamp = lonSel.value;
exatSelectChild(lonSel);
}
if(cnh) {
hinSel = hinSel ? hinSel : cnh.firstChild;
this.maxTimestamp = hinSel.value;
exatSelectChild(hinSel ? hinSel : cnh.firstChild);
}
if(cl) {
loSel = loSel ? loSel : cl.firstChild;
this.minTimestamp = loSel.value;
exatSelectChild(loSel);
}
if(ch) {
hiSel = hiSel ? hiSel : ch.firstChild;
this.maxTimestamp = hiSel.value;
exatSelectChild(hiSel ? hiSel : ch.firstChild);
}
// Продолжительности
cnl = this.form.elements[this.formId + 'MinNightsDurationCtrl'];
cnh = this.form.elements[this.formId + 'MaxNightsDurationCtrl'];
cl = this.form.elements[this.formId + 'MinDurationCtrl'];
ch = this.form.elements[this.formId + 'MaxDurationCtrl'];
if(cnl) {
exatClearCtrl(cnl);
oCnl = exatCreateOptionElement(0, '[все]');
cnl.appendChild(oCnl);
}
if (cnh) {
exatClearCtrl(cnh);
oCnh = exatCreateOptionElement(0, '[все]');
cnh.appendChild(oCnh);
}
if(cl) {
exatClearCtrl(cl);
oCl = exatCreateOptionElement(0, '[все]');
cl.appendChild(oCl);
}
if (ch) {
exatClearCtrl(ch);
oCh = exatCreateOptionElement(0, '[все]');
ch.appendChild(oCh);
}
ddstr = this.getString6(1);
lonSel = null;
hinSel = null;
loSel = null;
hiSel = null;
if (this.transportRequired || ((ddstr.charCodeAt(0) - 63) & 0x03) == 0) {
//если "только с перелётом" или нет туров на 1/2 дня (т.е. суточных)
for (var j = 0; j < ddstr.length; j++) {
symb = ddstr.charCodeAt(j) - 63;
if (symb) {
//пропустим в for'e туры на 1 день, т.к. это признак "суток",
//а "сутки" у нас сейчас автоматически складываются
for (var m = 1 + (j?0:1); m < 7; m++) {
if ( (1 << (m - 1)) & symb) {
val = (j * 6 + m);
name = val;
nightsname=name-1;
if(cnl) {
oCnl = exatCreateOptionElement(val, nightsname);
if(this.minNightsDuration > 0 && val <= this.minNightsDuration) {
lonSel = oCnl;
}
cnl.appendChild(oCnl);
}
if(cnh) {
oCnh = exatCreateOptionElement(val, nightsname);
if(this.maxNightsDuration > 0 && !hinSel && val >= this.maxNightsDuration) {
hinSel = oCnh;
}
cnh.appendChild(oCnh);
}
if(cl) {
oCl = exatCreateOptionElement(val, name);
if(this.minDuration > 0 && val <= this.minDuration) {
loSel = oCl;
}
cl.appendChild(oCl);
}
if(ch) {
oCh = exatCreateOptionElement(val, name);
if(this.maxDuration > 0 && !hiSel && val >= this.maxDuration) {
hiSel = oCh;
}
ch.appendChild(oCh);
}
}
}
}
}
}
else {
for(var j = 2; j <= this.MAX_TOUR_DAYS; j++) {
val=j;
name=j;
nightsname=name-1;
if(cnl) {
oCnl = exatCreateOptionElement(val, nightsname);
if (this.minNightsDuration > 0 && j <= this.minNightsDuration) {
lonSel = oCnl;
}
cnl.appendChild(oCnl);
}
if(cnh) {
oCnh = exatCreateOptionElement(val, nightsname);
if (this.maxNightsDuration > 0 && !hinSel && j >= this.maxNightsDuration) {
hinSel = oCnh;
}
cnh.appendChild(oCnh);
}
if(cl) {
oCl = exatCreateOptionElement(val, name);
if (this.minDuration > 0 && j <= this.minDuration) {
loSel = oCl;
}
cl.appendChild(oCl);
}
if(ch) {
oCh = exatCreateOptionElement(val, name);
if (this.maxDuration > 0 && !hiSel && j >= this.maxDuration) {
hiSel = oCh;
}
ch.appendChild(oCh);
}
}
}
if(cnl) {
lonSel = lonSel ? lonSel : cnl.firstChild;
this.minDuration = this.minNightsDuration = lonSel.value;
exatSelectChild(lonSel);
}
if(cnh) {
hinSel = hinSel ? hinSel : cnh.firstChild;
this.maxDuration = this.maxNightsDuration = hinSel.value;
exatSelectChild(hinSel ? hinSel : cnh.firstChild);
}
if(cl) {
loSel = loSel ? loSel : cl.firstChild;
this.minNightsDuration = this.minDuration = parseInt(loSel.value);
exatSelectChild(loSel);
}
if(ch) {
hiSel = hiSel ? hiSel : ch.firstChild;
this.maxNightsDuration = this.maxDuration = parseInt(hiSel.value);
exatSelectChild(hiSel ? hiSel : ch.firstChild);
}
return true;
}
/** Заполнить список значений single/multi select "категория отеля",
* в соответствии с this.categoryIds
* @access protected
*/
ExatSearchForm.prototype.initCategoryCtrl = function()
{
var c = this.form.elements[this.formId + 'CategoryCtrl'];
if(!c) {
return;
}
exatClearCtrl(c);
firstElement = exatCreateOptionElement(this.CAT_VAL[0], this.CAT_TEXT[0]);
if(this.categoryMask==this.ALL_CATEGORIES || this.categoryMask==0) {
exatSelectChild(firstElement);
}
c.appendChild(firstElement);
var mask = 0;
for (var i = 1; i < this.CAT_TEXT.length; i++) {
var element = exatCreateOptionElement(this.CAT_NEW_VAL[i], this.CAT_TEXT[i]);
var vals = this.CAT_NEW_VAL[i].split(",");
for(var j=0; j =0) {
if(this.accommodationHandSelectedId==i+1) {
o.setAttribute("selected","selected");
newId = i+1;
}
}
else {
if(this.accommodationId==i+1) {
o.setAttribute("selected","selected");
newId = i+1;
}
}
c.appendChild(o);
}
}
if (newId!=null) {
this.accommodationId = newId;
}
else {
if(firstId != null) {
this.accommodationId = firstId;
}
else {
this.accommodationId = 0;
}
}
}
/** Заполнить список значений single/multi select "отель",
* в соответствии с this.hotelIds и доступными отелями
* @access protected
*/
ExatSearchForm.prototype.initHotelCtrl = function()
{
var c = this.form.elements[this.formId+'HotelCtrl'];
if(!c) {
return;
}
exatClearCtrl(c);
var availableHotels = this.getResortData('hotels');
if (!availableHotels) {
return;
}
var f = false; //признак уже встретившейся фортуны
var hotelSelected = false; //был ли выбран хотя бы один отель
var tm = this.tourTypeMask;
var fm = this.foodTypeMask & this.foodTypeRange;
var am = this.accommodationRange;
var cm = (this.categoryMask == this.ALL_CATEGORIES) ? 0xffffffff : this.categoryMask;
firstElement = exatCreateOptionElement('', '[все]');
c.appendChild(firstElement);
var allResortsSelected = true;
for(var resortId in this.resortIds) {
if(resortId != Number(resortId)) continue;
allResortsSelected = false;
break;
}
var strHotelIds=","+this.hotelIds.join(",")+",";
for (var i =0; i < availableHotels.length; ++i) {
var item = availableHotels[i];
if (!((1 << item[2]) & cm)) {
continue;
}
if (!(item[3] & tm) || !(item[4] & fm) || !(item[5] & am)) {
continue;
}
// если выбран конкретный курорт или курорты, проверить, находится ли отель в нем или в одном из его подкурортов
if (!allResortsSelected && !this.resortIds[item[6]]) {
var availableResorts = this.getResortData('resorts');
var hotelPlace = item[6];
if (availableResorts[hotelPlace] && availableResorts[hotelPlace][4]) {
var hotelPlacePath = new String(availableResorts[hotelPlace][4].toString());
} else {
// курорт, где размещен отель, не найден или не имеет placePath (некорректные данные с сервера)
continue;
}
// перебираем все выбранные курорты; если путь к отелю включает путь к выбранному курорту в позиции 0, то отель считается принадлежащим курорту и не пропускается
var skipThisHotel = true;
for(var resortId in this.resortIds) {
if(resortId != Number(resortId)) continue;
if (availableResorts[resortId] && availableResorts[resortId][4]) {
var currResortPlacePath = availableResorts[resortId][4];
if (hotelPlacePath.indexOf(currResortPlacePath) == 0) {
skipThisHotel = false;
continue;
}
}
}
if (skipThisHotel == true) {
continue;
}
}
var val = item[0];
if (isNaN(val)) {//фортуна
if (!f) {
f = true;
val = 0;
o = exatCreateOptionElement(val, "[фортуна]");
}
else {
continue;
}
}
else {
o = exatCreateOptionElement(val, item[1]);
}
if(strHotelIds.indexOf(","+val+",") !== -1
|| this.hotelIds[val]!=undefined && this.hotelIds[val]==2
){
o.setAttribute("selected", "selected");
hotelSelected = true;
this.hotelIds[val] = 2; //to show it's used
}
c.appendChild(o);
}
//удалим из hotelIds невыбранные курорты
for(hotelId in this.hotelIds) {
if(hotelId == Number(hotelId) && this.hotelIds[hotelId] != 2) {
delete this.hotelIds[hotelId];
}
}
if(!hotelSelected) {
//ни один отель не был выбран, тогда выбираем пункт "[все]"
exatSelectChild(c.firstChild);
this.hotelIds=new Array();
}
}
/** Заполнить список значений single select "валюта",
* в соответствии с this.currencyId и предпочтениями
* @access protected
*/
ExatSearchForm.prototype.initCurrencyCtrl = function()
{
var c = this.form.elements[this.formId + 'CurrencyCtrl'];
if(!c) {
return;
}
exatClearCtrl(c);
var o;
var prefCur;
if(this.currencyId)
{
prefCur = this.currencyId;
}
if( this.countryId
&& typeof(exatPrefData[this.clientId].prefCurrency) != 'undefined'
&& typeof(exatPrefData[this.clientId].prefCurrency[this.countryId]) != 'undefined')
{
prefCur = exatPrefData[this.clientId].prefCurrency[this.countryId];
}
if(typeof(this.defaults.currencyId) != 'undefined'
&& this.defaults.currencyId>0
)
prefCur = this.defaults.currencyId;
for(var currencyId in this.currencyData) {
if(currencyId != Number(currencyId)) {
continue;
}
o = exatCreateOptionElement(currencyId, this.currencyData[currencyId]);
if(prefCur && prefCur == currencyId) {
exatSelectChild(o);
}
c.appendChild(o);
}
this.currencyId = Number(c.options[c.selectedIndex].value);
}
/** Заполнить список значений multi select "услуги",
* и выбрать некоторые в соответствии с this.serviceIds
* @access protected
*/
ExatSearchForm.prototype.initServicesCtrl = function()
{
var c = this.form.elements[this.formId+'ServiceCtrl'];
if(!c) {
return;
}
exatClearCtrl(c);
var noServicesSelected = true;
for(var serviceId in this.serviceIds) {
if(serviceId == Number(serviceId)) {
noServicesSelected = false;
break;
}
}
firstElement = exatCreateOptionElement('', '[все]');
if(noServicesSelected) {
firstElement.setAttribute('selected', true);
}
c.appendChild(firstElement);
for (var serviceGroupId in this.servicesData) {
if(serviceGroupId != Number(serviceGroupId)) {
continue;
}
var g = exatCreateGroupElement(this.servicesData[serviceGroupId][0]);
var sarr = this.servicesData[serviceGroupId][1];
for (var i = 0; i < sarr.length; ++i) {
if(typeof(sarr[i])!='object') {
continue;
}
var opt = exatCreateOptionElement(sarr[i][1], sarr[i][0]);
if(this.serviceIds[sarr[i][1]]) {
opt.setAttribute('selected', true);
}
g.appendChild(opt);
}
c.appendChild(g);
}
}
/** Заполнить список значений multi select "туроператоры",
* и выбрать некоторых в соответствии с this.tourOperatorIds и с предыдущими значениями контрола "Туроператоры"
* @access protected
*/
ExatSearchForm.prototype.initTourOperatorCtrl = function()
{
var c = this.form.elements[this.formId + 'TourOperatorCtrl'];
if(!c) {
return;
}
var prevTo = new Array();
var allTourOperatorsSelected = true;
if(this.tourOperatorDefIds!=-1 && this.tourOperatorDefIds.length>0){
prevTo=this.tourOperatorDefIds;
}else{
if (c.firstChild && !c.firstChild.selected && !this.resetTourOperatorEvent) {
for(o = c.firstChild.nextSibling; o; o = o.nextSibling) {
if(o.selected) {
prevTo[o.value] = 2;
} else {
prevTo[o.value] = 1;
}
}
}
for(var toId in this.tourOperatorIds) {
if(toId == Number(toId)) {
allTourOperatorsSelected = false;
prevTo[toId] = 2;
}
}
}
exatClearCtrl(c);
var selTourOperatorIds=this.tourOperatorIds;
this.tourOperatorIds = [];
var availableTourOperators = this.getResortData('tourOperators');
if (!availableTourOperators) {
return;
}
var tm = this.tourTypeMask;
var fm = this.foodTypeMask & this.foodTypeRange;
var am = this.accommodationRange;
var usePrefTo = false;
var resortToCnt = 0;
this.prefTourOperators = '';
if( typeof(exatPrefData[this.clientId].arrPrefTo) != 'undefined' &&
exatPrefData[this.clientId].arrPrefTo.length > 0)
{
usePrefTo = true;
}
var f = 0; //количество выбранных туроператоров
var allInPref = true; //все имеющиеся туроператоры - в предпочтениях, поэтому можно this.prefTourOperators сделать пустой
var firstElement = exatCreateOptionElement('', '[все]');
if(allTourOperatorsSelected) {
firstElement.setAttribute('selected', true);
}
c.appendChild(firstElement);
for (var i = 0; i < availableTourOperators.length; ++i) {
var item = availableTourOperators[i];
var toId = item[0];
if (!(item[1] & tm) || !(item[2] & fm) || !(item[3] & am)) {
continue;
}
resortToCnt++;
if (usePrefTo && !exatPrefData[this.clientId].arrPrefTo[toId]){
allInPref = false;
continue;
}
this.prefTourOperators += (this.prefTourOperators.length > 0 ) ? (','+ toId) : toId;
element = exatCreateOptionElement(toId, this.tourOperatorData[toId]);
if(prevTo.length > 0 && (prevTo[toId] == 2 || !prevTo[toId] && this.tourOperatorDefIds==-1)) {
//выбираем всех вновь появившихся туроператоров и тех, кто был выбран на пред. этапе
exatSelectChild(element);
this.tourOperatorIds[toId] = true;
f++;
}
c.appendChild(element);
}
if(allInPref) {
this.prefTourOperators = '';
}
if (c.length == 1) {
// есть только пункт [все], а самих ТО ни одного
c.removeChild(c.firstChild);
} else if (f > 0 && f < (c.length - 1)) {
// есть выделенные ТО, поэтому снимается выделение с пункта [все]
exatUnselectChild(c.firstChild);
} else if (f > 0 && f == (c.length - 1)) {
// все ТО выделены, поэтому с них снимается выделение и выделяется пункт [все]
var o;
for(o = c.firstChild.nextSibling; o; o = o.nextSibling) {
exatUnselectChild(o);
delete this.tourOperatorIds[o.value];
}
exatSelectChild(c.firstChild);
}
this.tourOperatorDefIds=-1;
}
/** Заполнить список значений single select "размер страницы"
* и выбрать пункт, соответствующий this.limit
* @access protected
*/
ExatSearchForm.prototype.initLimitCtrl = function()
{
var c = this.form.elements[this.formId + 'LimitCtrl'];
if(!c) {
return;
}
exatClearCtrl(c);
var limits = [20,100,500,1000];
for(var i=0; i maxCtrl.value)) {
maxCtrl.value = minCtrl.value;
this.maxTimestamp = this.minTimestamp;
}
}
ExatSearchForm.prototype.onMaxDateCtrlChange = function()
{
if(!this.form) {
return;
}
var minCtrl = this.form.elements[this.formId + 'MinDateCtrl'];
var maxCtrl = this.form.elements[this.formId + 'MaxDateCtrl'];
if(maxCtrl) {
this.maxTimestamp = maxCtrl.value;
}
if (minCtrl && maxCtrl && maxCtrl.value != 0 && minCtrl.value > maxCtrl.value) {
minCtrl.value = maxCtrl.value;
this.minTimestamp = this.maxTimestamp;
}
}
ExatSearchForm.prototype.onMinNightsDurationCtrlChange = function()
{
if(!this.form) {
return;
}
var minCtrl = this.form.elements[this.formId + 'MinNightsDurationCtrl'];
if(! minCtrl)
minCtrl = this.form.elements[this.formId + 'MinNightsDurationCtrl'];
var maxCtrl = this.form.elements[this.formId + 'MaxNightsDurationCtrl'];
if(!maxCtrl)
maxCtrl = this.form.elements[this.formId + 'MaxNightsDurationCtrl'];
if(!minCtrl) {
return;
}
this.minDuration = this.minNightsDuration = minCtrl.value;
if(maxCtrl && (minCtrl.value == 0 || parseInt(minCtrl.value) > parseInt(maxCtrl.value))) {
this.maxDuration = maxCtrl.value = this.maxNightsDuration = this.minNightsDuration;
}
}
ExatSearchForm.prototype.onMinDurationCtrlChange = function()
{
if(!this.form) {
return;
}
var minCtrl = this.form.elements[this.formId + 'MinDurationCtrl'];
if(! minCtrl)
minCtrl = this.form.elements[this.formId + 'MinDurationCtrl'];
var maxCtrl = this.form.elements[this.formId + 'MaxDurationCtrl'];
if(!maxCtrl)
maxCtrl = this.form.elements[this.formId + 'MaxDurationCtrl'];
if(!minCtrl) {
return;
}
this.minNightsDuration = this.minDuration = minCtrl.value;
if(maxCtrl && (minCtrl.value == 0 || parseInt(minCtrl.value) > parseInt(maxCtrl.value))) {
this.maxNightsDuration = maxCtrl.value = this.maxDuration = this.minDuration;
}
}
ExatSearchForm.prototype.onMaxNightsDurationCtrlChange = function()
{
if(!this.form) {
return;
}
var minCtrl = this.form.elements[this.formId + 'MinNightsDurationCtrl'];
var maxCtrl = this.form.elements[this.formId + 'MaxNightsDurationCtrl'];
if(!maxCtrl) {
return;
}
this.maxDuration = this.maxNightsDuration = maxCtrl.value;
if (minCtrl && maxCtrl.value!=0 && parseInt(minCtrl.value) > parseInt(maxCtrl.value)) {
this.minDuration = minCtrl.value = this.minNightsDuration = this.maxNightsDuration;
}
}
ExatSearchForm.prototype.onMaxDurationCtrlChange = function()
{
if(!this.form) {
return;
}
var minCtrl = this.form.elements[this.formId + 'MinDurationCtrl'];
var maxCtrl = this.form.elements[this.formId + 'MaxDurationCtrl'];
if(!maxCtrl) {
return;
}
this.maxNightsDuration = this.maxDuration = maxCtrl.value;
if (minCtrl && maxCtrl.value!=0 && parseInt(minCtrl.value) > parseInt(maxCtrl.value)) {
this.minNightsDuration = minCtrl.value = this.minDuration = this.maxDuration;
}
}
ExatSearchForm.prototype.onMinAmountCtrlChange = function()
{
if(!this.form) {
return;
}
var ctrl = this.form.elements[this.formId + 'MinAmountCtrl'];
this.minAmount = ctrl.value;
}
ExatSearchForm.prototype.onMaxAmountCtrlChange = function()
{
if(!this.form) {
return;
}
var ctrl = this.form.elements[this.formId + 'MaxAmountCtrl'];
this.maxAmount = ctrl.value;
}
ExatSearchForm.prototype.onCurrencyCtrlChange = function()
{
if(!this.form) {
return;
}
var ctrl = this.form.elements[this.formId + 'CurrencyCtrl'];
this.currencyId = ctrl.value;
}
ExatSearchForm.prototype.onServiceCtrlChange = function()
{
if(!this.form) {
return;
}
var ctrl = this.form.elements[this.formId+'ServiceCtrl'];
if(!ctrl) {
throw new Error("Can't find element with id="+this.formId + "ServiceCtrl");
return;
}
if(!ctrl.options.length) {
return;
}
var opt = ctrl.options[0];
this.serviceIds = [];
if((opt.value=='' || opt.value==0)) {
if(opt.selected) {
//спец. значение "[все]"
return;
}
}
for (var i=1; i Number(this.maxTimestamp)) {
alert('Начальная дата больше конечной');
return false;
}
if (Number(this.maxNightsDuration) && Number(this.minNightsDuration) > Number(this.maxNightsDuration)) {
alert('Задан некорректный диапазон количества ночей');
return false;
}
if (Number(this.maxDuration) && Number(this.minDuration) > Number(this.maxDuration)) {
alert('Задан некорректный диапазон количества дней');
return false;
}
c = this.form.elements[this.formId+'TourOperatorCtrl'];
if (c && c.length == 0) {
var s = 'Список туроператоров пуст. Это означает, что среди туроператоров, обслуживающих маршрут, нет' +
' ни одного из предпочитаемых Вами. Попробуйте настроить список предпочтительных туроператоров' +
' при помощи ссылки "настроить список" над списком туроператоров или изменить маршрут.';
alert(s);
return false;
}
c = this.form.elements[this.formId+'AgeCtrl'];
if (c && c.value.length > 0) {
var ageS = c.value;
var ageL = ageS.length;
var ageN = 1;
var age1 = '';
var age2 = '';
var sep = 0;
for (var i = 0; i < ageL; i++) {
var ch = ageS.charAt(i);
if (ch >= '0' && ch <= '9') {
if (sep && age1.length > 0) {
ageN++;
age1 += ',';
age2 = '';
sep = 0;
}
age1 += ch;
age2 += ch;
if (age2 > 25) {
alert('Возраст ребенка должен быть до 25 лет включительно.');
c.focus();
return false;
}
}
else {
sep = 1;
}
}
this.ages = age1;
var chnum = this.getChildren();
if(chnum > 0 && ageN > chnum) {
alert('Введено больше возрастов, чем выбрано детей.\nУдалите лишние возрасты.');
c.focus();
return false;
}
}
return true;
}
/** Поиск по коду тура
* @access public
*/
ExatSearchForm.prototype.searchTpid = function(val, newWindow)
{
if (val.length) {
var url = '/touronline/tpid_search.php?tpid=' + val;
var st = this.form.elements[this.formId + "ShowTechInfoCtrl"];
var so = this.form.elements[this.formId + "ShowTourOperatorCtrl"];
if (st && st.checked) {
url += '&show_tech_info=1';
} if (so && so.checked) {
url += '&show_operator=1';
}
exatShowWindow(url, 700, 500);
} else {
alert('Укажите код тура');
}
}
/** показать сообщение о предупреждении (нефатальной ошибке), если оно не пустое
* @access protected
*/
ExatSearchForm.prototype.reportWarning = function(msg)
{
if(this.params.alertLocks)
return;
if (msg != '') {
this.showMessage('Предупреждение : ' + msg);
} else {
this.showMessage('Неизвестная ошибка');
}
}
/** показать сообщение о фатальной ошибке, если оно не пустое
* @access protected
*/
ExatSearchForm.prototype.reportError = function(msg)
{
if(this.params.alertLocks)
return;
if (msg != '') {
this.showMessage('Фатальная ошибка : ' + msg);
} else {
this.showMessage('Неизвестная фатальная ошибка');
}
}
/** показать сообщение, если оно не пустое
* @access protected
*/
ExatSearchForm.prototype.showMessage = function(msg)
{
if(msg) {
alert(msg);
return true;
}
else {
return false;
}
}
ExatSearchForm.prototype.getChildren = function()
{
var children = new Array(0,0);
var accom = this.ACC_VAL[this.accommodationId];
if (accom != Number(accom)) children = accom.split('_');
return Number(children[1]);
}
/* глобальные утилитарные функции */
function exatGenRandomStr(strlen)
{
str = '';
for (i = 0; i < strlen; i++) {
str += String.fromCharCode(Math.random()*25 + 97);
}
return str;
}
function exatShowWindow(url, width, height)
{
size = '';
if(width && height) {
size = ',width=' + width + ',height=' + height;
}
var strInitParam='directories=no,status=yes,scrollbars=yes,resizable=yes,menubar=no,toolbar=no';
exat_wndname = exatGenRandomStr(10);
var description = window.open('', exat_wndname, strInitParam+size);
description.document.write('Пожалуйста, подождите. Идет загрузка...');
if (url) {
description.document.location=url;
}
description.focus();
return description;
}
// возвращена функция с оригинальным названием для совместимости
// by Eduard Pakaln
function w(url, width, height)
{
return exatShowWindow(url, width, height);
}
function exatGetNiceDate(dateObj)
{
dateObj = new Date(dateObj);
var daysOfWeek = new Array('вс', 'пн', 'вт', 'ср', 'чт', 'пт', 'сб');
var months = new Array('янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек');
var day = dateObj.getDate();
return daysOfWeek[dateObj.getDay()] + ' ' + (day < 10 ? '0' : '') + day.toString() + ' ' + months[dateObj.getMonth()];
}
/** Упаковка-распаковка строк
*/
function str2code(str_in) {
var tmp="";
var i;
var tmp_c="";
str_in=str_in.toString();
for(i = 0; i < str_in.length; i++) {
tmp_c = str_in.charCodeAt(i) - 23;
tmp += ''+(tmp_c<10 ? '0'+tmp_c : tmp_c);
}
var substr_len=14, out="", len_bit_tmp=0;
while(tmp!=''){
len_bit_tmp=tmp.length 31) || (d[1] > 12) || (d[2].length !== 4)) {
return null;
}
res = new Date(d[2], d[1] - 1, d[0])
return res.getTime();
}
/** Преобразование значения 'DD.MM.YYYY' элемента управления ctrl
* в кол-во миллисекунд с 1 января 1970 года
*/
function exatCheckDate(ctrl)
{
if (ctrl && ctrl.value.length) {
var res = exatToTime(ctrl.value);
if (res==null) {
ctrl.focus();
return false;
}
else {
return res;
}
}
return 0;
}
/**
* Получение значения элемента типа select. Если установлено свойство multiple и выбраны несколько элементов списка, возвращается массив значений
*
* @access global
* @param element
* @return mixed
*/
function exatGetSelectValue(el)
{
if (!el.nodeName || el.nodeName != 'SELECT') {
return;
}
if (!el.multiple) {
return el.value;
}
var result = [];
for (var i = 0; i < el.options.length; i++) {
if (!!el.options[i].selected) {
result.push(el.options[i].value);
}
}
if (!result.length) {
return;
}
if (result.length == 1) {
return result[0];
}
return result;
}
/**
* Получение значения установлено/сброшено объекта. Объект может быть input(checkbox, hidden, text)
* Сделано на случай когда на сайте некоторые компоненты делают скрытыми
*
* @access global
* @param obj
* @return bool or null on error
*/
function exatGetCheckedValue(obj)
{
var checkedValue;
if(obj.nodeName == 'INPUT'){
switch (obj.type) {
case 'text':
case 'hidden':
checkedValue = obj.value;
break;
case 'checkbox':
checkedValue = obj.checked;
break;
default:
checkedValue = null;
}
} else {
checkedValue = null;
}
return checkedValue;
}
/**
* Установка значения установлено/сброшено объекта. Объект может быть input(checkbox, hidden, text)
* Сделано на случай когда на сайте некоторые компоненты делают скрытыми
*
* @access global
* @param obj
* @param value
* @return bool
*/
function exatSetCheckedValue(obj, value)
{
if (!obj)
return;
else if (obj.nodeName == 'INPUT') {
switch (obj.type) {
case 'text':
case 'hidden':
obj.value = value;
ret = true;
break;
case 'checkbox':
obj.checked = value ? true : false;
ret = true;
break;
default:
ret = false;
}
} else {
ret = false;
}
return ret;
}
/**
* Возвращает числовые имена свойств или значения свойств объекта в виде строки через запятую
*
* @param useValues если false, то возвращает имена свойств, иначе, если это массив, то значения
*/
function exatJoinNumbers(obj, useValues) {
var res = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (useValues && (typeof(obj[prop]) != 'boolean') && (obj[prop] == Number(obj[prop]))){
res.push(obj[prop]);
} else if (prop == Number(prop)) {
res.push(prop);
}
}
}
return res.join(',');
}
function exatCreateGroupElement(l)
{
var g = document.createElement('optgroup');
g.setAttribute('label', l);
return g;
}
function exatCreateOptionElement(v, n)
{
var o = document.createElement('option');
var t = document.createTextNode(n);
o.setAttribute('value', v);
o.appendChild(t);
return o;
}
function exatClearCtrl(c)
{
// чтобы очистка поменьше тормозила и визуально не выбирала элементы,
// сначала выберем первый элемент, а затем удалим всё с конца
if(c && c.firstChild) {
if(c.nodeName=='SELECT') {
/* FIX for Opera
* операция делает выбранные не существующее пустое поле
* c.selectedIndex=-1; //чтобы в multiselect сбросить выделение совсем
*/
}
else {
c.firstChild.setAttribute('selected', true);
}
do {
c.removeChild(c.lastChild);
}
while(c.lastChild);
}
}
/** Кроссбраузерный выбор опции в селекте
*/
function exatSelectChild(chd) {
chd.setAttribute('selected', true);//для IE, в FF не работает
if(!chd.selected) {
chd.selected = true;//работает только в FF, в IE вызывает ошибку
}
}
function exatUnselectChild(chd) {
chd.setAttribute('selected', false);//для IE, в FF не работает
if(chd.selected) {
chd.selected = false;//работает только в FF, в IE вызывает ошибку
}
}
//глобальный реестр поисковых форм на странице. Заполняется конструктором.
if(typeof(exatForms)=='undefined') {
exatForms = [];
}
// функция для парсинга параметров GET
function getSearchParams(){
var tmp = new Array(); // два вспомагательных
var tmp2 = new Array(); // массива
var param = new Array();
var get = location.search; // строка GET запроса
if(get != '')
{
tmp = (get.substr(1)).split('&'); // разделяем переменные
for(var i=0; i < tmp.length; i++)
{
tmp2 = tmp[i].split('='); // массив param будет содержать
param[tmp2[0]] = tmp2[1]; // пары ключ(имя переменной)->значение
}
}
return param;
}
//
// find browser inner dimensions
//var width = 0, height = 0;
function getWindowDimensions(){
var width = 0, height = 0;
if(window.innerWidth){
width = window.innerWidth;
height = window.innerHeight;
}
else if(document.documentElement && document.documentElement.clientWidth){
width = document.documentElement.clientWidth;
height = document.documentElement.clientHeight;
}
else if(document.body && document.body.clientWidth){
width = document.body.clientWidth;
height = document.body.clientHeight;
}
return {'width':width, 'height':height};
}
// find browser inner dimensions End