mtst_init_count=0;

function mtst_form(formId,type,urlPostfix) {
  this.formType=type;
  this.formId=formId;
  this.formSelector="#"+formId;
  this.dataUrl="/ts/ts_data_"+urlPostfix+".php";
  this.submitUrl="/ts/ts_res_"+urlPostfix+".php";
  this.hotelStops=new Array(1);
  this.refreshDisabled=false;
  this.submitAfterRefresh=false;

  // -----------------   misc   -----------------

  this.startBlinking=function(selector) {
    if(!$(selector).length) return;
    var o=$(selector).css("opacity");
    opacity=(o<0.5)? 1:0.2;
    $(selector)
      .prop('disabled',true).css('cursor','auto')
      .animate({opacity:opacity}, 800, "linear", $.proxy(function(){this.startBlinking(selector);},this))
      .children('span').text("Идет поиск...");
  };

  this.stopBlinking=function(selector) {
      $(selector)
        .stop() .animate({opacity:1},300)
        .prop('disabled',false) .css('cursor','pointer')
        .children('span').text("Показать");
  };

  this.isDateAvail=function(d) {
    var dstr=$.datepicker.formatDate("dd.mm.yy",d);
    for(var i=-1;++i<this.datesAvail.length;)
    {
      if (dstr==this.datesAvail[i])
        return true;
    }
    return false;
  };

  this.fillCombo=function(selector,options,value) {
    sel=$(selector);
    sel.empty();
    jQuery.each(options,function(){
      sel.append('<option value="'+this[0]+'">'+this[1]+'</option>');
    });
    sel.val(value);
    Select().refresh(selector);
  }

  this.comboIsLoading=function(sel) {
    this.fillCombo(sel, [[-1,'загрузка...']], 0);
  };

  this.getJSP=function(sel) {
    if(!$(sel).length)
      return false;
    var jsp=$(sel).data('jsp');
    if(jsp)
      return jsp;
    $(sel).jScrollPane({
      scrollbarWidth:15,
      showArrows:true
    });
    jsp=$(sel).data('jsp');
    if(!jsp)
      alert('JSP creation error');
    return jsp;
  };

  this.clearMultichecks=function(sel,showMsg) {
    var jsp=this.getJSP(sel);
    if(!jsp)
      return;
    jsp.getContentPane().empty();
    if(showMsg)
      jsp.getContentPane().append("<label>загрузка...</label>");
    jsp.reinitialise();
  };

  this.setupCheckBox=function(selector) {
    Checkbox().set(selector,'checkbox1','checkbox1_checked','checkbox1_label');
  };

  this.addCheckBox=function(parent,id,caption,checked) {
    var checkedStr=checked? ' checked="checked"':'';
    parent.append(
      '<label>' +
      '<input type="checkbox" id="'+id+'"'+checkedStr+' class="checkbox1" />' +
      caption + '</label><br/>'
    );
  };

  this.delCheckBox=function(parentId,id) {
    $("#"+id).parent().parent().next().remove();
    $("#"+id).parent().parent().remove();
    $("#"+parentId).data('jsp').reinitialise();
  };

  this.delSelHotel=function(listIdx,id) {
    this.delCheckBox(this.formId+"_hotel_sel_"+listIdx,id)
  };

  this.getHotelIdFromCB=function(cb) {
    // find last '_':
    var pos=cb.id.search(/_[^_]+$/i);
    if(pos<0)
      return '0';
    return cb.id.substr(pos+1);
  };

  this.checkAnySelector=function(name,listIdx) {
    return this.formSelector+"_"+name+"_any_"+listIdx;
  };

  this.setCheckAny=function(name,listIdx,state) {
    var sel=this.checkAnySelector(name,listIdx);
    $(sel).prop('checked',state);
    $(sel).change();
  };

  // ----------------   init   ----------------

  this.tuneDatePicker=function(dpName,dateText) {
    // проверяем-подгоняем, чтобы 2-е значение было не меньше 1-го
    var date=$.datepicker.parseDate('dd.mm.yy',dateText);
    if(!date) return;
    var otherSel=this.formSelector + " .datepicker[name="+
      (dpName=='date1'? 'date2':'date1') + "]";
    var otherDate=$(otherSel).datepicker("getDate");
    if(otherDate) {
      if((dpName=='date1' && date>otherDate)||(dpName=='date2' && date<otherDate))
        $(otherSel).datepicker("setDate",date);
    }
  };

  this.tuneNights=function(changedElName) {
    // проверяем-подгоняем, чтобы 2-е значение было не меньше 1-го
    var el=$(this.formSelector + " select[name="+changedElName+"]");
    var otherElSel=this.formSelector + " select[name="+
      (changedElName=="nights1"? "nights2":"nights1") + "]";
    var otherEl=$(otherElSel);
    var val=new Number(el.val());
    var otherVal=new Number(otherEl.val());
    if((changedElName=="nights1" && val>otherVal)||
       (changedElName=="nights2" && val<otherVal)) {
      otherEl.val(el.val());
      Select().refresh(otherElSel);
    }
  };

  this.init=function() {

    $(this.formSelector+" select[name=dep_city]").change(
      $.proxy(function(){this.refreshForm("dep_city");},this));
    $(this.formSelector+" select[name=country]").change(
      $.proxy(function(){this.refreshForm("country");},this));
    $(this.formSelector+" select[name=arr_city]").change(
      $.proxy(function(){this.refreshForm("arr_city");},this));
    if(this.formType=="std")
      $(this.formSelector+" select[name=tour_kind]").change(
        $.proxy(function(){this.refreshForm("tour_kind");},this));
    $(this.formSelector+" select[name=wt]").change(
      $.proxy(function(){this.refreshForm("wt");},this));
    $(this.formSelector).submit($.proxy(function(){try{this.submit();}catch(e){alert(e);}return false},this));

    this.datesAvail=Array();
    $(this.formSelector+' .datepicker').datepicker({
      beforeShowDay: $.proxy(function(date){return [this.isDateAvail(date), ''];},this),
      onSelect: $.proxy(function(dateText, inst) {
        this.tuneDatePicker(inst.input.attr('name'),dateText);
      },this),
      dateFormat: 'dd.mm.yy'
    });
    if(this.formType!="quick") {
      if(this.formType!="combi") {
        var n=$(this.formSelector+" select[name^=nights]");
        for(var i=0;++i<=30;)
          n.append('<option value="' +i+ '">' + i + '</option>');
      }

      $(this.formSelector+" select[name=childs]").change($.proxy(this.childsChanged,this));

      if(this.formType=="combi") {
        for(var i=-1;++i<3;) {
          var select=this.getHotelNightsSelect(i);
          $(select).change(
            $.proxy(function(event){this.hotelNightsChanged(event);},this));
          //alert(i);
        }
      }

      this.refreshForm("init");

      this.childsChanged();

      if(this.formType!="combi") {
        //var minN=(this.formType=="cruises")? 4:7;
        //$(sel1).val(minN); $(sel2).val(15);
        $(this.formSelector+" select[name=nights1]").change(
          $.proxy(function(){this.tuneNights("nights1");},this));
        $(this.formSelector+" select[name=nights2]").change(
          $.proxy(function(){this.tuneNights("nights2");},this));
      }

      if(!mtst_init_count) {
        if(location.hash.indexOf("submit=1")>=0)
          this.doSubmit(location.hash.substr(1));
        else if(location.hash.indexOf("submit=2")>=0)
          this.submitAfterRefresh=true;
      }
    }
    else {
      this.refreshForm('init');
    }
    if(!mtst_init_count++) {
      if(location.hash.length)
        location.hash='';
    }
  };

  this.initDates=function() {
    if(this.datesAvail.length) {
      $(this.formSelector+' .datepicker').datepicker('option',{
        minDate: this.datesAvail[0],
        maxDate: this.datesAvail[this.datesAvail.length-1]
      });
      // set both datepickers to first available date:
      $(this.formSelector+' .datepicker').datepicker('setDate',this.datesAvail[0]);
      // shift second datepicker for cruises:
      if(this.formType=='cruises') {
        var date=$.datepicker.parseDate('dd.mm.yy',this.datesAvail[0]);
        date.setDate(date.getDate()+21);
        $(this.formSelector+' .datepicker[name=date2]').datepicker('setDate',date);
      }
    }
  };

  this.initNights=function()
  {
    if(!this.nightsAvail.length)
      return;
    if(this.formType=="combi") {
      $(this.formSelector+" input[name=nights]").val(this.nightsAvail[0]);
      return;
    }
    /*
    var n1=$(this.formSelector+" select[name=nights1]").val();
    var n2=$(this.formSelector+" select[name=nights2]").val();
    if(n1>this.nightsAvail[this.nightsAvail.length-1])
      $(this.formSelector+" select[name=nights1]").val(this.nightsAvail[this.nightsAvail.length-1]);
    if(n2<this.nightsAvail[0])
      $(this.formSelector+" select[name=nights2]").val(this.nightsAvail[0]);
    */
    $(this.formSelector+" select[name=nights1]").val(this.nightsAvail[0]);
    $(this.formSelector+" select[name=nights2]").val(this.nightsAvail[this.nightsAvail.length-1]);
    $(this.formSelector+" select[name^=nights] option").each($.proxy(function(i,elem){
      if(jQuery.inArray((new Number(elem.value)).valueOf(),this.nightsAvail)>=0)
        $(elem).removeClass("grayed");
      else
        $(elem).addClass("grayed");
    },this));
    Select().refresh(this.formSelector+" select[name^=nights]");
  };

  this.setCurrency=function(cur)
  {
    var prevCur=$(this.formSelector+" input[name=currency]").val();
    if(prevCur!=cur)
      $(this.formSelector+" input[name^=pricem]").val("");
    $(this.formSelector+" input[name=currency]").val([cur]).change();
  };

  // ----------------   hotels list   -------------------

  this.initHotelsList=function(listIdx)
  {
    var jsp=0;

    // fill cities
    var cityPrefix=this.formId+"_city_"+listIdx;
    if($("#"+cityPrefix).length) {
      jsp=this.getJSP("#"+cityPrefix);
      jsp.getContentPane().empty();
      for(var i=-1;++i<this.hotelStops[listIdx].cities.length;) {
        this.addCheckBox(jsp.getContentPane(),
          cityPrefix+"_"+this.hotelStops[listIdx].cities[i][0],
          this.hotelStops[listIdx].cities[i][1],
          false
        );
      }
      this.setupCheckBox("input[id^="+cityPrefix+"_]");
      jsp.reinitialise();
      $("*[id^="+cityPrefix+"_]").click($.proxy(function(){
        this.hotelsFilterCheckChanged("city",listIdx);},this));
    }

    // fill boards
    var boardPrefix=this.formId+"_board_"+listIdx;
    jsp=this.getJSP("#"+boardPrefix);
    jsp.getContentPane().empty();
    for(var i=-1;++i<this.hotelStops[listIdx].boards.length;)
      this.addCheckBox(jsp.getContentPane(),
        boardPrefix+"_"+this.hotelStops[listIdx].boards[i][0],
        this.hotelStops[listIdx].boards[i][1],
        false
      );
    this.setupCheckBox("input[id^="+boardPrefix+"_]");
    jsp.reinitialise();
    $("*[id^="+boardPrefix+"_]").click($.proxy(function(){
      this.hotelsFilterCheckChanged("board",listIdx);},this));

    // fill stars (array)
    var stars=new Array;
    for(var i=-1;++i<this.hotelStops[listIdx].hotels.length;) {
      var hotelAttr=this.hotelStops[listIdx].hotels[i];
      // 0 - id, 1 - name, 2 - cityId, 3,4 - stars (as is/encoded), 5 - boards (array)
      var id=hotelAttr[4];
      var found=false;
      for(var j=-1;++j<stars.length;) {
        if(stars[j][1]==id) {
          found=true;
          break;
        }
      }
      if(!found)
        stars.push(Array(hotelAttr[3],id));
    }
    stars.sort();

    // fill stars (html)
    var starsPrefix=this.formId+"_stars_"+listIdx;
    jsp=this.getJSP("#"+starsPrefix);
    jsp.getContentPane().empty();
    for(var i=-1;++i<stars.length;)
      this.addCheckBox(jsp.getContentPane(),
        starsPrefix + "_" + stars[i][1], stars[i][0], false
      );
    this.setupCheckBox("input[id^="+starsPrefix+"_]");
    jsp.reinitialise();
    $("*[id^="+starsPrefix+"_]").click($.proxy(function(){
      this.hotelsFilterCheckChanged("stars",listIdx);},this));

    // set event handlers
    $(this.checkAnySelector("city",listIdx)).click($.proxy(function(){
      this.checkAnyChanged("city",listIdx);
    },this));
    $(this.checkAnySelector("stars",listIdx)).click($.proxy(function(){
      this.checkAnyChanged("stars",listIdx);
    },this));
    $(this.checkAnySelector("board",listIdx)).click($.proxy(function(){
      this.checkAnyChanged("board",listIdx);
    },this));
    $(this.checkAnySelector("hotel",listIdx)).click($.proxy(function(){
      this.checkAnyChanged("hotel",listIdx);
    },this));
    $(this.formSelector+"_hotel_name_filter_"+listIdx).keyup($.proxy(function(event){
      this.hotelNameFilterChanged(listIdx,event);
    },this));

    // initial values for checkboxes
    this.setCheckAny("city",listIdx,true);
    this.setCheckAny("stars",listIdx,true);
    this.setCheckAny("board",listIdx,true);
    this.setCheckAny("hotel",listIdx,true);

    // some more initialization
    this.hotelNameFilter[listIdx]='';
    this.applyHotelsFilter(listIdx);
  };

  this.getHotelNightsSelect=function(listIdx) {
    return this.formSelector+' span[for_=tab_content2'+(listIdx+1)+'] select';
  }

  this.hotelNightsChanged0=function(listIdx) {
    var hcnt=this.hotelStops.length;
    var select=this.getHotelNightsSelect(listIdx);
    var val=$(select).val();
    var idxToUpdate=listIdx+1;
    if(idxToUpdate==hcnt)
      idxToUpdate=0;
    var n=0;
    var n2=0;
    for(var i=-1;++i<hcnt;) {
      n+=this.hotelNights[i];
      if(i!=idxToUpdate)
        n2+=parseInt($(this.getHotelNightsSelect(i)).val());
    }
    var newVal=n-n2;
    if(isNaN(newVal))
      return;
    var recurse=false;
    if(newVal<1) {
      newVal=1;
      recurse=true; // must update third select too
    }
    var selToUpdate=this.getHotelNightsSelect(idxToUpdate);
    if($(selToUpdate).val()!=newVal) {
      $(selToUpdate).val(newVal);
      $(selToUpdate).change();
      Select().refresh(selToUpdate);
    }
    if(recurse)
      this.hotelNightsChanged0(idxToUpdate);
  }

  this.hotelNightsChanged=function(event) {
    var listIdx=parseInt($(event.target).attr("idx_"));
    this.hotelNightsChanged0(listIdx);
  }

  this.initHotels=function(data)
  {
    this.hotelStops=data.hotelStops;
    var hcnt=data.hotelStops.length;
    this.hotelNameFilter=new Array(hcnt);
    if(hcnt>1) {
      this.hotelNights=data.hotelNights;
      this.hotelNightsFixed=data.hotelNightsFixed;
      var fixedNights=0;
      var fixedNightsHCnt=0;
      var totalNights=0;
      for(var i=-1;++i<hcnt;) {
        totalNights+=this.hotelNights[i];
        if(data.hotelNightsFixed[i]==1) {
          fixedNights+=data.hotelNights[i];
          fixedNightsHCnt++;
        }
      }
      // if only one hotel stop has variable nights, it's incorrect; make it fixed too
      if(hcnt-fixedNightsHCnt==1) {
        for(var i=-1;++i<hcnt;)
          this.hotelNightsFixed[i]=1;
        fixedNights=totalNights;
        fixedNightsHCnt=hcnt;
      }

      var maxVarNights=totalNights-fixedNights-(hcnt-fixedNightsHCnt)+1;
      for(var i=-1;++i<hcnt;) {
        var nightsFixed=(this.hotelNightsFixed[i]==1);
        var tabSel=this.formSelector+' span[for_=tab_content2'+(i+1)+']';
        $(tabSel+' span.city_name').html(this.hotelStops[i].cities[0][1]);

        //var span=$(tabSel+' span.custom_select1');
        var select=this.getHotelNightsSelect(i);

        $(select).empty();

        if(nightsFixed)
          $(select).append('<option value="' +this.hotelNights[i]+ '">' + this.hotelNights[i] + '</option>');
        else {
          for(var j=0;++j<=maxVarNights;)
            $(select).append('<option value="' +j+ '">' + j + '</option>');
          //var _this=this;
          //var _i=i-1;
          //$(select).change(function(){_this.hotelNightsChanged(_i);});
        }
        $(select).val(this.hotelNights[i]);
        $(select).change(); // refresh 'non-cur' span containing num of nights
        Select().refresh(select);
        this.initHotelsList(i);
      }
      var selector=this.formSelector+' span[for_=tab_content23]';
      $(selector).css('display',hcnt==3? 'inline-block':'none');
    }
    else
      this.initHotelsList(0);
  }

  this.applyHotelsFilter=function(listIdx)
  {
    var hotelPrefix=this.formId+"_hotel_"+listIdx;
    var jsp=this.getJSP("#"+hotelPrefix);
    jsp.getContentPane().empty();

    var sel=this.checkAnySelector("city",listIdx);

    var anyCity=$(sel).length? $(sel).prop('checked'):true;
    var anyStars=$(this.checkAnySelector("stars",listIdx)).prop('checked');
    var anyBoard=$(this.checkAnySelector("board",listIdx)).prop('checked');
    var anyHotel=$(this.checkAnySelector("hotel",listIdx)).prop('checked');
    for(var i=-1;++i<this.hotelStops[listIdx].hotels.length;) {
      var hotelAttr=this.hotelStops[listIdx].hotels[i];
      // 0 - id, 1 - name, 2 - cityId, 3,4 - stars (as is/encoded), 5 - boards (array)
      var id=hotelAttr[0];
      var name=hotelAttr[1];
      var boards=hotelAttr[5];
      //alert(anyCity);
      if(!anyCity && !$(this.formSelector+"_city_"+listIdx+"_"+hotelAttr[2]).prop('checked'))
        continue;
      if(!anyStars && !$(this.formSelector+"_stars_"+listIdx+"_"+hotelAttr[4]).prop('checked'))
        continue;
      if(!anyBoard) {
        var boardOk=false;
        for(var j=-1;++j<boards.length;) {
          if($(this.formSelector+"_board_"+listIdx+"_"+boards[j]).prop('checked')) {
            boardOk=true;
            break;
          }
        }
        if(!boardOk)
          continue;
      }

      if(this.hotelNameFilter[listIdx].length
         && name.toUpperCase().indexOf(this.hotelNameFilter[listIdx])<0)
        continue;
      var elId=hotelPrefix+"_"+id;
      var checked=
        (!anyHotel && document.getElementById(hotelPrefix+"_sel_"+id));

      this.addCheckBox(jsp.getContentPane(), hotelPrefix+"_"+id, name, checked);

    }
    this.setupCheckBox("input[id^="+hotelPrefix+"_]");
    jsp.reinitialise();
    $("input[id^="+hotelPrefix+"_]").click($.proxy(function(event){
      this.hotelCheckChanged(listIdx,event);},this));
  };

  this.hotelsFilterCheckChanged=function(filterId,listIdx)
  {
    this.setCheckAny(filterId,listIdx,
      $(this.formSelector+"_"+filterId+"_"+listIdx+" :checkbox:checked").length? false:true);
    this.applyHotelsFilter(listIdx);
  };

  this.refreshHotelAnyCheckState=function(listIdx)
  {
    this.setCheckAny("hotel",listIdx,
      $(this.formSelector+"_hotel_sel_"+listIdx+" :checkbox:checked").length? false:true);
  };

  // checkboxes 'any city', 'any stars', 'any board', 'any hotel'
  this.checkAnyChanged=function(name,listIdx)
  {
    var sel=this.checkAnySelector(name,listIdx);
    if($(sel).prop("checked")) {
      // "any" checked: reset any individual check
      var sel2=this.formSelector+"_"+name+"_"+listIdx+" input:checkbox";
      $(sel2).prop("checked",false);
      $(sel2).change();
      if(name=="hotel") {
        var jsp=this.getJSP(this.formSelector+"_hotel_sel_"+listIdx);
        jsp.getContentPane().empty();
        jsp.reinitialise();
      }
      else
        this.applyHotelsFilter(listIdx);
    }
    else {
      // disable manual reset
      this.setCheckAny(name,listIdx,true);
    }
  };

  this.hotelCheckChanged=function(listIdx,event)
  {
    var cb=event.target;
    var hotelId=this.getHotelIdFromCB(cb);
    var hotelSelPrefix=this.formId+"_hotel_sel_"+listIdx;
    cb=$(cb);
    var cbId=hotelSelPrefix+"_"+hotelId;
    var jsp=this.getJSP("#"+hotelSelPrefix);
    if(cb.prop('checked')) {
      this.addCheckBox(jsp.getContentPane(),cbId,cb.parent().parent().text(),true);
      $("#"+cbId).click($.proxy(function(event){
        this.hotelSelCheckChanged(listIdx,event)},this));
      this.setupCheckBox("#"+cbId);
    }
    else
      this.delSelHotel(listIdx,cbId);
    jsp.reinitialise();

    this.refreshHotelAnyCheckState(listIdx);
  };

  this.hotelSelCheckChanged=function(listIdx, event)
  {
    var cb=event.target;
    var hotelId=this.getHotelIdFromCB(cb);
    this.delSelHotel(listIdx,cb.id);
    var cb2=$(this.formSelector+"_hotel_"+listIdx+"_"+hotelId);
    if(cb2.length) {
      cb2.prop('checked',false);
      cb2.change();
    }
    this.refreshHotelAnyCheckState(listIdx);
  };

  this.hotelNameFilterChanged=function(listIdx,event)
  {
    var v=$(event.target).val();
    if(v==this.hotelNameFilter[listIdx])
      return;
    this.hotelNameFilter[listIdx]=v.toUpperCase();
    this.applyHotelsFilter(listIdx);
  };

  // ----------------   event handlers   ----------------

  this.childsChanged=function()
  {
    var ch=$(this.formSelector+" select[name=childs]").val();
    setInputDisabledState(this.formSelector+" input[name=child1]", ch<1);
    setInputDisabledState(this.formSelector+" input[name=child2]", ch<2);
  };

  this.showSPOdetails=function(elToAlign,wt)
  {
    //Darkbox().setDefaults({"loader_icon":"/_makeup/lbimages/lightbox-ico-loading.gif"});
    var _this=this;
    var url='wtinfo.php?wt='+wt;
    if(this.formType=='combi')
      url+='&type=combi';
    showSPOinfo(url,elToAlign);
  };

  this.showFlightsDetails=function(elem)
  {
    showDarkbox($(elem).parent().parent().attr('flights_'), elem, 460);
  };

  // --------------   refreshForm   -------------

  this.refreshForm=function(elName)
  {
    if(this.refreshDisabled)
      return;
    this.refreshDisabled=true;
    var parms="changed="+elName+"&type="+this.formType;
    if(elName=='init') {
      if(mtst_init_count==0) {
        if(location.search.length)
          parms+="&"+location.search.substr(1);
        if(location.hash.length)
          parms+="&"+location.hash.substr(1);
      }
    }
    else
      parms+="&"+$(this.formSelector).serialize();
    $.ajax({
      type:"GET",
      url:this.dataUrl+"?"+parms,
      dataType:"json",
      context:this,
      success:function(data){
        if(data.dep_cities)
          this.fillCombo(this.formSelector+" select[name=dep_city]",data.dep_cities,data.selDepCity);
        if(data.countries)
          this.fillCombo(this.formSelector+" select[name=country]",data.countries,data.selCountry);
        if(data.arr_cities)
          this.fillCombo(this.formSelector+" select[name=arr_city]",data.arr_cities,data.arr_city);
        if(data.tour_kinds)
          this.fillCombo(this.formSelector+" select[name=tour_kind]",data.tour_kinds,data.tour_kind);
        if(data.webtours)
          this.fillCombo(this.formSelector+" select[name=wt]",data.webtours,data.selWebtour);
        this.datesAvail=data.datesAvail;
        this.initDates();
        if(data.nightsAvail) {
          this.nightsAvail=data.nightsAvail;
          this.initNights();
        }
        if(data.currency)
          this.setCurrency(data.currency);
        if(this.formType=="quick")
          this.fillCombo(this.formSelector+" select[name=hotel0]",data.hotels,0);
        else if(this.formType!="avia")
          this.initHotels(data);
        this.refreshDisabled=false;
        if(this.submitAfterRefresh) {
          this.submitAfterRefresh=false;
          this.submit();
        }
      }
    });

    if(elName=="init" || (this.formType=="cruises" && elName=="country"))
      this.comboIsLoading(this.formSelector+" select[name=dep_city]");
    if(elName=="init" || (this.formType!="cruises" && elName=="dep_city"))
      this.comboIsLoading(this.formSelector+" select[name=country]");
    if(elName=="init" || elName=="dep_city" || elName=="country")
      this.comboIsLoading(this.formSelector+" select[name=arr_city]");
    if(elName=="init" || elName=="dep_city" || elName=="country" || elName=="arr_city")
      this.comboIsLoading(this.formSelector+" select[name=tour_kind]");
    if(elName=="init" || elName=="dep_city" || elName=="country" || elName=="arr_city" || elName=="tour_kind")
      this.comboIsLoading(this.formSelector+" select[name=wt]");
    this.comboIsLoading(this.formSelector+" select[name=hotel0]");

    for(var i=-1;++i<this.hotelStops.length;) {
      this.clearMultichecks(this.formSelector+"_city_"+i,true);
      this.clearMultichecks(this.formSelector+"_stars_"+i,true);
      this.clearMultichecks(this.formSelector+"_board_"+i,true);
      this.clearMultichecks(this.formSelector+"_hotel_"+i,true);
      this.clearMultichecks(this.formSelector+"_hotel_sel_"+i,false);
    }
  };

  // --------------   submit   -------------

  this.getListFromMultiChecks=function(divId,listIdx,fullList)
  {
    var prefix=this.formId+"_"+divId+"_"+listIdx;
    var checked=$("#"+prefix+" input:checkbox"+(fullList? "":":checked"));
    var str='';
    for(var i=-1;++i<checked.length;) {
      if(i)
        str+=",";
      // actual ids are prefixed
      //str+=encodeURIComponent(checked[i].id.substr(divId.length+1));
      str+=checked[i].id.substr(prefix.length+1);
    }
    return str;
  };

  this.doSubmit=function(params)
  {
    this.startBlinking(this.formSelector+" button[type=submit]");
    $("#search_res").empty();
    Darkbox().closeBox();
    var _this=this;
    $("#search_res").load(
      this.submitUrl+"?"+params,
      function(){
        _this.stopBlinking(_this.formSelector+" button[type=submit]");
        $('#search_res table').each(function(){
          $(this).find('tr:odd').addClass('table_odd_row');
        });
        $('#search_res a.info_icon').click(function(){_this.showSPOdetails(this,$(this).attr('wt_'));return false;});
        $('#search_res .flight_forward,#search_res .flight_back').click(function(){
          _this.showFlightsDetails(this);});
        //location.hash=params;
      }
    );
  };

  this.submit=function()
  {
    var d1,d2;
    if(this.formType=="quick") {
      d1=$(this.formSelector+" .datepicker[name=date1]").datepicker("getDate");
      if(!d1) { alert("Некорректная дата вылета"); return; }
      if($(this.formSelector+" select[name=hotel0] option").length<2)
        { alert("Пожалуйста, дождитесь загрузки данных в форму"); return; }
      document.location="/ts/#submit=1&"+$(this.formSelector).serialize();
    }
    else {
      if(this.formType=="avia") {
        if($(this.formSelector+" select[name=arr_city] option").val()==-1)
          { alert("Пожалуйста, дождитесь загрузки данных в форму"); return; }
      }
      else {
        if($("#"+this.formId+'_stars_0 input').length==0)
          { alert("Пожалуйста, дождитесь загрузки данных в форму"); return; }
      }
      d1=$(this.formSelector+" .datepicker[name=date1]").datepicker("getDate");
      if(!d1) { alert("Некорректная начальная дата вылета"); return; }
      d2=$(this.formSelector+" .datepicker[name=date2]").datepicker("getDate");
      if(!d2) { alert("Некорректная конечная дата вылета"); return; }
      if(Math.abs(d2.valueOf()-d1.valueOf())>90*24*3600*1000)
        { alert("Пожалуйста, выберите интервал дат не более 90 дней"); return; }

      if(this.formType!='avia' && this.hotelStops.length>1) {
        // проверим кол-во ночей в отелях
        var n=0;
        var n2=0;
        for(var i=-1;++i<this.hotelStops.length;) {
          n+=this.hotelNights[i];
          n2+=parseInt($(this.getHotelNightsSelect(i)).val());
        }
        if(n2!=n)
          { alert("Сумма количества ночей в отелях должны быть равна "+n); return; }
      }

      var q="type="+this.formType+"&"+$(this.formSelector).serialize();

      if(this.formType!="avia") {
        // собираем параметры, относящиеся к отелям
        q+="&hotelStops="+this.hotelStops.length;
        for(var i=-1;++i<this.hotelStops.length;) {
          var anyHotel=$(this.checkAnySelector("hotel",i)).prop('checked');
          if(anyHotel && this.hotelStops.length==1) {
            var anyCity=$(this.checkAnySelector("city",i)).prop('checked');
            if(!anyCity)
              q+="&city"+i+"="+this.getListFromMultiChecks("city",i);
            var anyStars=$(this.checkAnySelector("stars",i)).prop('checked');
            if(!anyStars)
              q+="&stars"+i+"="+this.getListFromMultiChecks("stars",i);
          }
          else {
            if(this.formType=="combi")
              q+="&hotelStopNights"+i+"="+$(this.getHotelNightsSelect(i)).val();
            q+="&hotel"+i+"=";
            if(anyHotel)
              q+=this.getListFromMultiChecks("hotel",i,true);
            else
              q+=this.getListFromMultiChecks("hotel_sel",i);
          }
          var anyBoard=$(this.checkAnySelector("board",i)).prop('checked');
          if(!anyBoard)
            q+="&board"+i+"="+this.getListFromMultiChecks("board",i);
        }
      }

      this.doSubmit(q);
    }
  };

  // end of constructor
  this.init();
}

