/*
     $Revision$
     $Id$

     File:        mld_edit_melding.js
*/

var finishBeforeSubmit = [];
function isGoodInteger(str)
  {
    var anum=/(^\d+$)/
    return anum.test(str);
  }

function checkInput()
{
  if ($("#melding_omschrijving")[0] && $("#mldOmschrijving").css("display") == "block" && $("#melding_omschrijving").val() != "")
  {
    var s = $("#melding_omschrijving").val();
    if (s.length > 4000)
    {
      s = s.substring(0, 4000);
    }
    $("#melding_omschrijving").val(s);
  }

  if ($("#remark")[0] && $("#remark").val() != "")
  {
    s = $("#remark").val();
    if (s.length > 4000)
    {
      s = s.substring(0, 4000);
    }
    $("#remark").val(s);
  }

  if ($("#respijt").length > 0)
  { // Het respijt veld is aanwezig.
    // Afdwingen van het juiste formaat voor respijt.
    // Lege waarde is ook fout, dan moet er een 0 ingevuld worden.
    var str = $("#respijt").val();
    if (str == "")
      $("#respijt").val(0); // Bij een lege waarde 0 dagen submitten.
  }
  return true
}

function askdoubleCallback(data, text)
{
  if (data.child) // 'Koppelen' gekozen
  {
    iface.button.disable("btn_mld_submit"); // Disable de "Opslaan" button zodat niet nog een keer gesubmit kan worden.
    $("#parent_key").val(data.parent_key);
    $("#forcesave").val(1);
    $.post($("form[name=u2]")[0].action, $("[name=u2]").serialize(), mld_submit_callback, "json"); // Nu definitief
  }
  else
  { // Geen melding aanmaken
    FcltMgr.closeDetail(window, {cancel: true});
  }
}

// Drie  modes
// 1) Dubbele melding van een moedermelding aanmaken (opnieuw laden van save asp met parent_key, maar niet meer controleren op double) [1]
// 2) Nieuwe melding aanmaken (opnieuw laden van save asp, maar niet meer controleren op double) [2]
// 3) Geen melding aanmaken, gewoon terug. [cancel]
function mldDoubleCallback(data, text)
{
  if (data.mode == 2) // Eigen melding gewenst
  {
    iface.button.disable("btn_mld_submit"); // Disable de "Opslaan" button zodat niet nog een keer gesubmit kan worden.
    $("#forcesave").val(1);
    $.post($("form[name=u2]")[0].action, $("[name=u2]").serialize(), mld_submit_callback, "json"); // Nu definitief
  }

  if (data.mode == 1) // Geklikt op een gelijksoortige melding
  {
    var url = "../mld/mld_askdouble.asp?parent_key=" + data.parent_key; // Vraag om te koppelen
    FcltMgr.openModalDetail(url, L("lcl_mld_similarcalls"), {callback: askdoubleCallback});
  }
}

function mld_submit_callback(json)
{
  if (json.doublecheck && !json.template)
  {
    var url = "../mld/mld_double.asp?urole=" + json.urole
                              + "&stdmelding_key=" + json.stdm_key
                              + "&ruimtekey=" + json.ruimtekey
                              + "&verdiepingkey=" + json.verdiepingkey
                              + "&gebouwkey=" + json.gebouwkey
                              + "&locatiekey=" + json.locatiekey
                              + "&ins_str=" + json.obj_arr
                              + "&save=1";
    FcltMgr.openModalDetail(url, L("lcl_mld_save_new_call"), {callback: mldDoubleCallback});
  }
  if (json.success)
  {
    var group_these_mld_keys = $("#mld_grouped_key_arr").val();
    var todo = Promise.resolve();
    if (group_these_mld_keys) {
      todo = new Promise((resolve, reject) => {
        var data = { mldgroup_key: json.mld_key };
        protectRequest.dataToken(data);
        $.when($.post("../mld/mld_group_save.asp?urole=" + ($("#urole").val() || "bo") + "&mld_keys=" + group_these_mld_keys,
                      data,
                      null,
                      "json")).then((data, textStatus, jqXHR) => {
          resolve(jqXHR.status == 200);
        }).fail((response) => {
          reject("Failed $.post to 'mld_group_save.asp' => " + response.statusText + " (" + response.status + ")");
        });
      }).catch((errmsg) => {
        console.error(errmsg);
      });
    }
    todo.then(_ => {
      mld_submit_callback_page(json);
    });
  }
  else
  {
    iface.button.enable("btn_mld_submit");
  }
}

// Hier is de melding al opgeslagen, mag ik de opgeslagen melding zien? Toon dan de show-mode, anders, sluit het venster en toon een  toaster
function mld_submit_callback_page(json) {
  var data = { req_info: "show_after_upd",
                mld_key:  json.mld_key };
  $.getJSON( "../mld/get_mld_info_ajax.asp",
            data,
            function(auth) {
                              if (auth.show)
                              {
                                if (json.autoprint)
                                {
                                  FcltMgr.windowopen('./mld_opdr_xml.asp?mld_key=' + json.mld_key,'pr_rep','resizable=1,scrollbars=1,menubar=1,toolbar=1');
                                }
                                FcltMgr.closeDetail(window, json);
                              }
                              else
                              {
                                FcltMgr.topmanager().window.$.toast({ text: json.noShowToaster, icon: "success", position : "top-center", loaderBg: "#fff"});
                                parent.FcltMgr.closeDetail(window, json);
                              }
                            });
}

async function mld_submit()
{
  document.activeElement.blur(); // trigger laatste onChanges
  $("form[name=u2] input.expression:hidden").val("");
  $('#r_objs:visible>option').prop("selected", "true"); // Zet selected zodat verplicht ze ziet en zodat waarden worden gesubmit

  await Promise.all(finishBeforeSubmit);

  // Standaard checks op verplichte velden, datum formaat, numeriek en float formaat, currency formaat.
  if (!await validateForm("u2"))
    return false;

  // Formulier specifieke checks
  if (!checkInput())
    return false;

  if ($("#time_from_actiondate:visible").length && $("#show_actiondate:visible").length &&
      (($("#time_from_actiondate").val() == "" && $("#show_actiondate").val() != "") ||
       ($("#time_from_actiondate").val() != "" && $("#show_actiondate").val() == "")))
  {
    if ($("#time_from_actiondate").val() == "")
      $("#time_from_actiondate").addClass("bad");
    else
      $("#show_actiondate").addClass("bad");
    return false;
  }

  // Negeer de multi of de suggest, afhankelijk van welke ingevuld (zichtbaar) is
  if ($(".r_objs.nowrap").is(":hidden"))
      $(".r_objs.nowrap").find("input.r_objs").removeAttr("name");
  else
      $("select#r_objs").removeAttr("name");

  if ($("#mldAlg").css("display") == "none")
  { // alg_onrgoed_niveau == "H", De plaatsselector is hidden.
    $("#regiokey").val(-1);
    $("#districtkey").val(-1);
    $("#locatiekey").val(-1);
    $("#gebouwkey").val(-1);
    $("#verdiepingkey").val(-1);
    $("#ruimtekey").val(-1);
  }

  $.post($("form[name=u2]")[0].action, $("[name=u2]").serialize(), FcltCallbackAndThenAlways(mld_submit_callback), "json");
  return true; // disabled button ook
}

function mld_cancel()
{
  FcltMgr.closeDetail(window, { cancel: true } );
}

function loadKenmerk()
{
  var prs_key = (def_kenmerk_link_key > 0? def_kenmerk_link_key : $('#person').val());
  var s = "load_kenmerk.asp?stdm_str=" + $("#stdm").val()
        + "&mld_key=" + (copy ? mld_copy_key : mld_key)
        + "&act_key=" + act_key
        + (copy? "&copy=1" : "")
        + (mld_key > 0 && !canFlexChange? "&reado=1" : "")
        + "&prs_key=" + prs_key
        + "&melder_key=" + melder_key
        + (mld_processing_group_all? "&srtdisc=" + srtdisc_key : "")
        + "&disc=" + disc_key // Initiele waarde primaire Vakgroep/Behandelteam.
        + "&prsautlevel=" + prsautlevel
        + "&show_alg=" + (show_alg? 1 : 0)
        + "&loc_key=" + loc_key;
  finishBeforeSubmit.push(
    new Promise((resolve, reject) => {
      $.when($.get(s, async data => {
        flexReloaded(data);
        if (copy)
          make_attachments_readonly();
        resolve();
      }).fail(() => {
        reject();
      }));
    })
  );
}

function setReferentie(kanverwijzen)
{
  var clearReference = true;
  var labeltext = "";
  switch(kanverwijzen)
  {
    case 1:  // Meldingen
             clearReference = $("#ref_type").val() != "M";
             labeltext = L("lcl_ref_complain");
             break;
    case 2:  // Meldingsopdrachten
             clearReference = $("#ref_type").val() != "O";
             labeltext = L("lcl_shared_order");
             break;
    case 4:  // Reserveringen
             clearReference = $("#ref_type").val() != "R";
             labeltext = L("lcl_reservation");
             break;
    case 8:  // Bestellingen
             clearReference = $("#ref_type").val() != "B";
             labeltext = L("lcl_bes_bestelling");
             break;
    case 16: // Bestelopdrachten
             clearReference = $("#ref_type").val() != "X";
             labeltext = L("lcl_bes_orders");
             break;
    case 32: // Contracten
             clearReference = $("#ref_type").val() != "C";
             labeltext = L("lcl_contract");
             break;
    case 64: // Facturen
             clearReference = $("#ref_type").val() != "F";
             labeltext = L("lcl_fin_invoice");
             break;
    case 128:// Meldingen
             clearReference = $("#ref_type").val() != "M";
             labeltext = L("lcl_ref_complain");
             break;
    default: // Combinatie
             clearReference = false;
             labeltext = L("lcl_reference");
             break;
  }

  if (kanverwijzen == 0)
  {
    sgRef.setValue(-1, "");
    if (typeof sgmldgroup != "undefined")    // Another ref field exists -> Hide only the sgRef field
        sgRef.makeHidden();
    else                                     // Else if this is the only ref-field -> Hide the entire block
    {
        sgRef.makeHidden();
        $("#mldRef").css("display", "none");
    }
  }
  else
  {
    if (clearReference)
      sgRef.setValue(-1, "");
    if (ref_key > 0) {
      sgRef.setValue(ref_key, lreferenceName);
      $("#ref_type").val(kanverwijzen==32?"C":"");
    }
    $('label[for="ref_key"]').text(labeltext);
    sgRef.undoHidden();
    $("#mldRef").css("display", "block");
    $("#filtercode").val(kanverwijzen==128?"M":"O");
  }
}

function process_gebouw_info(data, textStatus)
{
  if (textStatus == "success")
  { // Vervang de kostenplaats indien het gebouw er één heeft anders kostenplaats leegmaken.
    // setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
    if (frontend && !mld_kk) {
      var alg_kostenplaats_key = data.alg_kostenplaats_key || -1;
      $("#account_bld").val(alg_kostenplaats_key)
                       .attr("data-stored-value", alg_kostenplaats_key);
    }
    if (data && data.alg_kostenplaats_key > 0) {
      // lastTry is true zodat suggestbox wordt leeggemaakt indien waarde niet voorkomt (en niet de laatst waarde wordt getoond)
      // In de frontend kan er de gebouwkostenplaats ingevuld worden terwijl de user er geen mandaat op heeft.
      // De kostenplaats in "account_bld" wordt voor de frontend ook mee gequeried indien kostenklan = 0 (Uit). checkExist mag dan ook getest worden.
      sgAccount.setValue(data.alg_kostenplaats_key, data.kostenplaats_omschrijving, true, true, data.kostenplaats_module, true);
    }
  }
  else
    FcltMgr.alert("process_gebouw_info: " + textStatus);
}

function process_kp_info(data)
{
  // setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
  // lastTry is true zodat suggestbox wordt leeggemaakt indien waarde niet voorkomt (en niet de laatst waarde wordt getoond)
  // sgAccount is aanwezig. De functie onChangeKostenklant() heeft aanvraag geinitieerd.
  // Zet eigen (default) kostenplaats van aanvrager alleen als kostenklant AAN. Indien niet aanwezig dan wordt suggestbox automatisch leeg gemaakt.
  // Mocht de kostenplaats verplicht zijn en er is 1 waarden, dan wordt deze automatisch geselecteerd.
  sgAccount.setValue(data.kostenplaats_key, data.kpn_string, true, true, data.kmodule, true);
}

function onChangeKostenklant()
{
  // Kies juiste prs_key/user_key voor de kostenplaats query
  // Stop deze in het urlAdd veld
  // Kostenklant UIT => AAN: Eigen kostenplaats van aanvrager selecteren of leeg maken als onvoldoende autorisatie
  // Kostenklant AAN => UIT: Kostenplaats laten staan of leeg maken als onvoldoende autorisatie
  if ($("#kostenklant").prop("checked"))
  { // Kostenklant UIT => AAN: Zet eigen (default) kostenplaats van de aanvrager. Indien niet aanwezig dan wordt suggestbox automatisch leeg gemaakt.
    //                         urlAdd field op person suggestbox (reloadUrlAdd gebeurt automatisch door FCLTkostenplaatsselector)
    if ($("#person").val() > 0)
    {
      $.getJSON("../prs/get_prs_info_ajax.asp",
                { req_info: "prs_perslid",
                  prs_perslid_key: $("#person").val()
                },
                process_kp_info);
    }
  }
  else
  { // Kostenklant AAN => UIT: Zet eventueel 'ALG kostenplaats'. Indien niet aanwezig dan wordt suggestbox automatisch leeg gemaakt.
    //                         urlAdd field op hiddem account_userkey suggestbox (reloadUrlAdd gebeurt automatisch door FCLTkostenplaatsselector)
    // Zet eventueel 'ALG kostenplaats'
    if (show_alg)
    {
      if ($("#gebouwkey").val() > 0)
      {
        var isGebouw = $("#bttype").val() == "B";
        $.getJSON("../alg/get_alg_info_ajax.asp",
                  { req_info: (isGebouw? "alg_gebouw" : "alg_terrein"),
                    alg_gebouw_key: $("#gebouwkey").val()
                  },
                  process_gebouw_info);
      }
      else
        // Huidige waarde niet zomaar laten staan. Wel checken of het een geldige waarde is.
        sgAccount.setValue($("#account").val(), $("#account_show").val(), false, true, $("#kmodule").val(), true);
    }
    else
      // Huidige waarde niet zomaar laten staan. Wel checken of het een geldige waarde is.
      sgAccount.setValue($("#account").val(), $("#account_show").val(), false, true, $("#kmodule").val(), true);

    // Mocht er maar één waarde voorkomen in de suggesbox dan deze niet selecteren. Kostenplaats is niet verplicht.
    //sgAccount.CheckJustOne();
  }
}

function process_object_info(data, textStatus)
{
  if (textStatus == "success")
  {
    // Valideer of de gekozen objecten nog valide zijn bij deze stdmelding
    if (!$("select#r_objs").hasClass("hidden")) { // De suggest is in process_stdm_info() al gevalideerd, dus hier alleen de multi-mode
      var newObjCount = 0;
      $("select#r_objs > option").each((i, elem) => {
        let ins_key = elem.value;
        for (var i = 0; i < data.length; i++) {
          if (data[i].key == ins_key) {
            newObjCount++;
            return; // (continue de each-loop)
          }
        }
        $(elem).remove();
      });
      $("#r_objs").attr("size", Math.max(newObjCount, 1));
      _toggleObjectPicker(newObjCount);
    }

    if (data && data.length >= 0)
    {
      $("#r_objs_button").val(L("lcl_mld_objects") + " (" + data.length + ")");

      // Selectie niet meer leeg maken. Objecten wegen nu zwaarder dan de plaats.
      if (data.length == 0) {
        // Alsnog readonly maken omdat er geen resultaten zijn (indien leeg)
        _toggleObjects(false);
      }

      if (data.length == 1 && $("#req_r_objs,#r_objs,#r_objs option").hasClass("required") && $("#r_objs option").length == 0)
      {
        var $opt = $("<option>" + data[0].omschrijving + "</option>")
                    .attr("value", data[0].key)
                    .attr("uitvoertijd", data[0].uitvoertijd);
        $("#r_objs").append($opt);
        if (typeof sgObject != "undefined") // setTimeout zodat de onChangeAlg klaar is (met evt. leeg maken van objectSelector)
          setTimeout(function () { sgObject.setValue(data[0].key, data[0].omschrijving); }, 1);

        if (mld_key < 0 && mld_object_filled_in_alert == 1)
          FcltMgr.alert(L("lcl_mld_object_filled_in"));
        // Vul nu ook de plaatsgegevens behorend bij dit object in, voor zover dit mogelijk is.
        if (data[0].alg_ruimte_type == "R" && data[0].changelevel != "R")
          // setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
          // lastTry is true zodat suggestbox wordt leeggemaakt indien waarde niet voorkomt (en niet de laatst waarde wordt getoond)
          sgRoom.setValue(data[0].alg_ruimte_key, data[0].alg_ruimte_nr, true, true, null, true);
        // else: Een object die aan een plaats is gebonden, is in dit geval altijd aan een ruimte gebonden.
      }
    }
    var stdm_info_verplichtstatus = stdm_info.srtinst_verplichtstatus == 2 || (stdm_info.srtinst_verplichtstatus == 21 && data.length > 0);
    // Zet class required op button om deze ook missing te kunnen maken.
    $("#r_objs_button").toggleClass("required", (stdm_info_verplichtstatus && $("#r_objs_button").attr("disabled")=="disabled"));
    $("#r_objs_show").toggleClass("required", (stdm_info_verplichtstatus));
  }
  else
    FcltMgr.alert("process_object_info: " + textStatus);
}

function getObjectInfo(stdmChanged)
{
  setSuggestUrlAdd();
  var alg_onrgoed_obj_niveau = $("#alg_onrgoed_obj_niveau").val();  // Vanaf welk ALG niveau laten we plaatsgebonden objecten zien?
  var prsafdobj = $("#prsafdobj").val();                            // Vanaf welk PRS niveau laten we organisatiegebonden objecten zien?

  if (show_ins && (alg_onrgoed_obj_niveau != "" || prsafdobj > 0))
  { // Alleen als er (plaats- en/of organisatie-gebonden) objecten gekozen worden
    var obj_alg_lvl = $("#suggest_alg_niveau").val(); // Deze neemt het benodigde & beschikbare niveau reeds in acht
    var alg_key;
    switch (obj_alg_lvl) {
      case "H":
        alg_key = -1;
        break;
      case "L":
        alg_key = $("#locatiekey").val();
        break;
      case "G":
        alg_key = $("#gebouwkey").val();
        break;
      case "V":
        alg_key = $("#verdiepingkey").val();
        break;
      case "R":
        alg_key = $("#ruimtekey").val();
        break;
      case "A":
      case "":
        alg_key = -1;
        break;
    }

    var prs_key = -1;
    if (prsafdobj > 0) { // Persoon en/of Afdeling (beiden gebaseerd op deze prs_key)
      prs_key = $("#personFor").length > 0 ? $("#personFor").val() : $("#person").val();
    }

    // De object button grijs weergeven als
    // we geen plaatsgebonden objecten kennen of de plaats niet is ingevuld tot en met het alg_onrgoed_obj_niveau niveau
    // en we geen organisatiegebonden objecten kennen of de persoon is niet ingevuld
    var stdmld_key = $("#stdm").val();
    var disableobjects = !(stdmld_key > 0) || (prs_key == -1 && alg_key == -1 && obj_alg_lvl != "A"); // We hebben niks te zoeken
    _toggleObjects(!disableobjects);

    if (!disableobjects)
    { // De callback functie process_object_info kan automatische een object selecteren.
      // In dat geval moet er een recalcEinddatum() worden uitgevoerd.
      // Zorg ervoor dat eerst de getJSON + callback functie geheel is uitgevoerd (async),
      // zodat eventueel eerst het object wordt ingevuld voordat de recalcEinddatum() aan het eind van deze functie wordt uitgevoerd.
      var data = {
        req_info: "get_objecten",
        alg_key: alg_key,
        alg_niveau: obj_alg_lvl,
        prs_key: prs_key,
        stdmld_key: stdmld_key
      }
      if (JSON.stringify(window._cachedInsData) !== JSON.stringify(data)) {
        window._cachedInsData = data;
        jQuery.ajaxSetup({async: false});
        $.getJSON("../mld/get_mld_info_ajax.asp",
                  data,
                  process_object_info);
        jQuery.ajaxSetup({async: true});
      }
    }
    else // We hoeven niets (opnieuw) op te halen
      process_object_info([], "success");
  }

  // !stdmChanged voorkomt initiële einddatum aanpassing bij bestaande meldingen
  if (stdmChanged && (stdm_info.afhankelijk == 1 || window.stdm_info.regime == 2))
      recalcEinddatum(); // Einddatum kan moeten worden aangepast als uitvoertijd afhankelijk is van srtruimte of object of als regime "openingstijden" is.
}

function onChangeLocatie(locbld_changed)
{
  onChangeAlg(2);
  onChangeGebouw(locbld_changed);
}

// Op de onchange van een gebouw controleren of er misschien een kostenplaats
// automatisch gekozen moet worden
// De functie onChangeGebouw() wordt ook aangeroepen bij wijzigen van melder
function onChangeGebouw(locbld_changed, do_not_change_kp) // sl is de gebouw selectbox
{
  if (locbld_changed)
      onChangeAlg(3);

  if (window.stdm_info.regime == 2 && locbld_changed) // openingstijden
  {
    recalcEinddatum(); // Einddatum kan moeten worden aangepast.
  }

  if ($("#kostenklant").length)
  {
    // Terug en niets doen als:
    // 1) kostenklant vinkje aan is of
    // 2) locatie of gebouw veranderd is en kostenklant vinkje uit is en de kostenplaats niet een ALG kostenplaats is of niet is ingevuld
    if ($("#kostenklant").prop("checked") ||
        (locbld_changed && (!$("#kostenklant").prop("checked") && ($("#kmodule").val() != "ALG" && $("#kmodule").val() != ""))))
    {
      return; // Niets doen bij kostenklant en als GEEN ALG-kostenplaats
    }

    // Zet eventueel 'ALG kostenplaats'
    if (!do_not_change_kp && $("#gebouwkey").length)
    {
      var isGebouw = $("#bttype").val() == "B";
      $.getJSON("../alg/get_alg_info_ajax.asp",
                { req_info: (isGebouw? "alg_gebouw" : "alg_terrein"),
                  alg_gebouw_key: $("#gebouwkey").val()
                },
                process_gebouw_info);
    }
  }
}

function onChangeVerdieping()
{
  onChangeAlg(4);
}

function onChangeRuimte()
{
  onChangeAlg(5);
}

function onChangeAlg(level)
{
    var alg = [];
    var loc = -1;
    var temp = "";
    switch (level) {
        case 5: temp = $("#ruimtekey").val();       if (temp && temp != -1) alg.push(temp);
        case 4: temp = $("#verdiepingkey").val();   if (temp && temp != -1) alg.push(temp);
        case 3: temp = $("#gebouwkey").val();       if (temp && temp != -1) alg.push(temp);
        case 2: temp = $("#locatiekey").val();      if (temp && temp != -1) loc = temp;
            break;
        default: return; // Error
    }

    var stdm_key = $("#stdm").val();
    var ins_disc = $("#disc").val();
    var afd_key = $("#prs_afd_key").val();

    if ((level == 2 && loc && loc > 0) ||
        (level > 2 && alg.length && alg.length == (level - 2)))
    {
        $.getJSON("./get_mld_info_ajax.asp",
                  { req_info: "faq_info",
                    loc_key: loc,
                    alg_key_arr: alg.join(","),
                    changed: level,
                    ins_disc_key: (ins_disc || -1),
                    stdm_key: stdm_key || -1,
                    afd_key: afd_key || -1
                  },
                  callback_faq_info);
    }
    else
        show_fixed_faq("mldFaq", level, {}, faq_max_results_mld);
}

var faq_info_timer;
var cleared = null;
function callback_faq_info(data)
{
  if (data.popup_faq && !fromkb)
  { // Een vertraging om bij meerdere callbacks achter elkaar alleen de laatste uit te voeren.
    if (window.faq_info_timer) {
      clearTimeout(window.faq_info_timer);
    }
    if (data.changed <= 1) {
      if (!window.cleared || window.cleared == 2 || window.cleared == 9) {
        cleared += 1; // Vakgroep/Stdmelding
      }
    } else if (data.changed == 9) {
      if (!window.cleared || window.cleared == 2) {
        cleared += 9; // Afdeling
      }
    } else {
      if (!window.cleared || window.cleared == 1 || window.cleared == 9) {
        cleared += 2; // Plaats
      }
    }
    window.faq_info_timer = setTimeout(callback_faq_info_once.bind(null, data), 1500);
  }
  else
    show_fixed_faq("mldFaq", data.changed, data.fixed_faq, faq_max_results_mld);
}

function callback_faq_info_once(data)
{
  var filledlevel = findFilledLevel();
  if (data.changed < 5 || data.changed == 9 || requiredlevel <= filledlevel)
  {
      var url = "../mld/mld_faq.asp"
              + "?loc_key=" + data.loc_key
              + "&alg_key_arr=" + data.alg_key_arr.join(",")
              + "&stdm_key=" + data.stdm_key
              + "&ins_disc_key=" + data.ins_disc_key
              + "&afdeling_key=" + data.afdeling_key
              + "&changed=" + data.changed;
      // Als dit de eerste en enige call naar mld_faq is, (!window.cleared)
      // of zowel disc/stdm en alg zijn tegelijk -automatisch- ingevuld, (window.cleared == 1+2 = 3)
      // of zowel afd en disc/stdm zijn tegelijk -automatisch- ingevuld, (window.cleared == 1+9 = 10)
      // of zowel afd en alg zijn tegelijk -automatisch- ingevuld, (window.cleared == 2+9 = 11)
      // dan willen we alle kennisbankitems zien, zo niet, dan alleen de items laten zien die gekoppeld zijn aan hetgeen gewijzigd is (plaats of disc/stdm)
      if (!window.cleared || window.cleared == 3 || window.cleared == 10 || window.cleared == 11) {
        url += "&showall=1";
      }
      FcltMgr.openModalDetail(url, L("lcl_mld_faq_stdmanswers"), { height: 200, width: 700, callback: mld_faq_list_callback } );
  }
  show_fixed_faq("mldFaq", data.changed, data.fixed_faq, faq_max_results_mld);
  window.cleared = null;
}

// Process de data die van de melder via Ajax terugkomt.
// Soms zijn velden niet beschikbaar, dan blijven ze gewoon wat ze waren.
function process_melder_info(data)
{
  if (typeof sgDept != "undefined" && (mld_key < 0 || $("#sgDept").val() == -1))
  {
    sgDept.setValue(data.prs_afdeling_key, data.prs_afdeling_naam, true, true, null, true);
  }
  // setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
  // lastTry is true zodat suggestbox wordt leeggemaakt indien waarde niet voorkomt (en niet de laatst waarde wordt getoond)

  if ($("#kostenklant").prop("checked") && (typeof sgAccount != "undefined"))
  {
    // Zet eigen (default) kostenplaats van aanvrager alleen als kostenklant AAN. Indien niet aanwezig dan wordt suggestbox automatisch leeg gemaakt.
    // Mocht de kostenplaats verplicht zijn en er is 1 waarden, dan wordt deze automatisch geselecteerd.
    // Als er maar 1 waarde is en er wordt geprobeerd een kostenplaats te zetten die niet aanwezig, kan het fout gaan bij het terugzetten van de enigste aanwezige waarde.
    // Deze waarde kan dan fout gezet worden (Rood weergegeven). Dit komt door timingproblemen tussen verschillende jquery ajax code!
    // Daarom zorgen dat jquery ajax code van deze kostenplaats suggest asynchroon wordt uitgevoerd.
    jQuery.ajaxSetup({async: false});
    sgAccount.setValue(data.kostenplaats_key, data.kpn_string, true, true, data.kmodule, true);
    // Bij een nieuwe melding als de kostenplaats verplicht is, niet is ingevuld en er is maar 1 waarde, dan deze waarde invullen.
    if (mld_key < 0 && data.kostenplaats_key < 0 && $("input#account_show").hasClass("required"))
      sgAccount.CheckJustOne();
    jQuery.ajaxSetup({async: true});
  }

  if (show_bes)
  { // Als er maar 1 afleveradres is, dan moet deze geselecteerd blijven.
    if ($("#del_address option").length > 1)
    {
      $("#del_address").val(""); // Maak afleveradres selectbox leeg
      if (data.mld_adres_key > 0)
      {
        $("#del_address").val(data.mld_adres_key); // Selecteer het afleveradres dat bij de ingevulde melder hoort
      }
    }
  };

  if (show_alg && typeof sgLoc != "undefined")
  {
    // Erase location if issue did not initiate from object or with a preset default location
    if (frontend && !mld_kk) {
      $("#account_bld").val(-1); // Het veld met de kostenplaats van het gekozen gebouw leegmaken.
    }

    // mld_use_requestor_location is false als we al een vast default hebben, of als we dit expliciet niet willen [S("mld_uses_requestor_location")]
    if (mld_use_requestor_location) { // Moeten we zelf een betere default plaats bepalen adhv de aanvrager?
      if (!plaatsselector.preferWerkplekken(data.werkplekken, data.standplaats)) {
        if ($("#issuer_search").length) {
          $("#issuer_search").prop("checked", false);
          sgLoc.setValue(-1, "", true, false);
        } else {
          cascadePlaatsSelector();
        }
      } else if ($("#issuer_search").length) { // preferWerkplekken cascadeert zelf al
        $("#issuer_search").prop("checked", true);
      }
    }
  }
};

function onChangeMelder(perslid_key, txt)
{
  if (perslid_key > 0) {
    if (mld_allow_for_others == 1) sgPersonFor.setValue(perslid_key, txt);
    GetSetCallInfo(perslid_key);
  }
  if ($("input[name=mld_copy]").val() == "0" && $(".flexsql", "div.block-wrapper.flexblock").length > 0) { // prevent loadKenmerk() from erasing values
    loadKenmerk(); // reload when not copying  and there is a Sql statement involved
  }

  showObjectInfo(false);

  var changed = 9;
  var afd_key = $("#prs_afd_key").val();
  if (afd_key && afd_key > 0) {
    var stdm_key = $("#stdm").val();
    var ins_disc = $("#disc").val();
    var loc = $("#locatiekey").val() || -1;
    var alg_key_arr = [];
    if (loc > 0) {
        var bld = $("#gebouwkey").val();
        if (bld && bld != -1)
            alg_key_arr.push(bld);
        var flr = $("#verdiepingkey").val();
        if (flr && flr != -1)
            alg_key_arr.push(flr);
        var room = $("#ruimtekey").val();
        if (room && room != -1)
            alg_key_arr.push(room);
    }

    $.getJSON("./get_mld_info_ajax.asp",
              { req_info: "faq_info",
                loc_key: loc,
                alg_key_arr: alg_key_arr.join(","),
                changed: changed,
                ins_disc_key: ins_disc,
                stdm_key: stdm_key,
                afd_key: afd_key
              },
              callback_faq_info);
  }
}

function GetSetCallInfo(perslid_key)
{
  if ($("#k_flexsql").val() == 1)
  {
    //changeDisciplineList(); // Mogelijk zijn niet alle disciplines toegestaan
    // Persoon is aangepast. Aangezien stdmelding afhankelijk is van de persoon, kijken of de huidige waarde nog mag
    // setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
    if (window.sgStdm)
        sgStdm.setValue(sgStdm.getValue(), $("#stdm_show").val(), true, true, null, true);
  }

  if (perslid_key > 0)
  {
    $.getJSON("../prs/get_prs_info_ajax.asp",
              { req_info: "prs_perslid",
                prs_werkplek: 1,
                prs_aflever: 1,
                prs_perslid_key: perslid_key
              },
              process_melder_info);
  }

  if (show_alg) { onChangeGebouw(false, true); } // Kostenplaats mag niet aangepast worden.
}

// Prioriteitenmatrix gebruiken om Prioriteit te bepalen
// I | U | Prioriteit
// - | * | 3 (Normaal)
// * | - | 3 (Normaal)
// 1 | 1 | 1 (Kritiek)
// 1 | 2 | 2 (Hoog)
// 1 | 3 | 3 (Normaal)
// 2 | 1 | 2 (Hoog)
// 2 | 2 | 3 (Normaal)
// 2 | 3 | 4 (Laag)
// 3 | 1 | 3 (Normaal)
// 3 | 2 | 4 (Laag)
// 3 | 3 | 4 (Laag)
// Update de Prioriteit na aanpassing van Impact of Urgentie
function onChangeImpactOrUrgentie(mobile)
{
  if ($("#impact").val() && $("#urgentie").val())
  {
    if ($("#impact").val() == 1 && $("#urgentie").val() == 1)
      $("#prio").val(1);
    else if (($("#impact").val() == 1 && $("#urgentie").val() == 2) || ($("#impact").val() == 2 && $("#urgentie").val() == 1))
      $("#prio").val(2);
    else if (($("#impact").val() == 2 && $("#urgentie").val() == 3) || ($("#impact").val() == 3 && $("#urgentie").val() == 2)  || ($("#impact").val() == 3 && $("#urgentie").val() == 3))
      $("#prio").val(4);
    else
      $("#prio").val(3);

    if (mobile == 1)
      $("#prio").change(); // Op mobile staat er nog een <span> met de waarde voor de select. Met de change() van de select wordt de waarde van de select die net is gezet overgenomen.

    onChangePrioriteit();
  }
}

function onChangePrioriteit()
{
  // TODO: in plaats rest van deze functie?
  recalcEinddatum();
  // Eenheid respijt hetzelfde als stdmelding.
  $("#dayshours_resp").val(stdm_info.prioriteiten[$("#prio").val()].eenheid);
}

function onChangeMeldbron()
{
  if ($("#meldbron").length)
  {
    var isextern = $("#meldbron :selected").attr("isextern");
    var externnrIsVisible = $("#externnr").closest("tr").is(":visible");
    $("#externnr").closest("tr").toggle(isextern==1);
    if (externnrIsVisible != (isextern==1)) { // veld is getoggled
      FcltMgr.resized();
    }
  }
}

function callback_stdm_info(data, textStatus, jqXHR)
{
  process_stdm_info(data, true); // Tweede parameter stdmChanged is true.
}

function mld_faq_list_callback(data)
{
  // data.accept zal in praktijk altijd true zijn. Zelf nu dicht.
  FcltMgr.closeDetail(window, { cancel: true } );
}

// Bepaal het alg-scope-niveau voor de object-selector&suggest
// En vul die in, in het hidden veld suggest_alg_niveau
function setSuggestUrlAdd(alg_onrgoed_niveau, alg_onrgoed_obj_niveau)
{
  var alg_niveau = "";
  var algs = { "A": -1, "L": 2, "G": 3, "V": 4, "R": 5 };
  alg_onrgoed_niveau      = alg_onrgoed_niveau      || stdm_info.alg_onrgoed_niveau;
  alg_onrgoed_obj_niveau  = alg_onrgoed_obj_niveau  || stdm_info.alg_onrgoed_obj_niveau;

  if ($("#ruimtekey").val() > -1)
      alg_niveau = "R";
  else if ($("#verdiepingkey").val() > -1)
      alg_niveau = "V";
  else if ($("#gebouwkey").val() > -1)
      alg_niveau = "G";
  else if ($("#locatiekey").val() > -1)
      alg_niveau = "L";
  else if (alg_onrgoed_obj_niveau == "A")
      alg_niveau = "A";

  var alg_std_lvl = algs[alg_onrgoed_niveau];     // Verplicht niveau
  var alg_obj_lvl = algs[alg_onrgoed_obj_niveau]; // Object tonen vanaf dit niveau
  var alg_has_lvl = algs[alg_niveau];             // Ingevuld t/m dit niveau
  var sug_alg_lvl = "";

  if (!show_alg && alg_onrgoed_obj_niveau != "A") {
    sug_alg_lvl = "";                       // Geen plaatsobjecten
  } else if (alg_has_lvl == -1) {           // Als we nog geen plaats hebben ingevuld
    sug_alg_lvl = alg_onrgoed_obj_niveau;   // Gebruik dan het 'Tonen vanaf'-niveau
  } else if (alg_has_lvl >= alg_obj_lvl     // Als het reeds ingevulde niveau specifieker is dan het 'Tonen vanaf'-niveau
          && alg_obj_lvl <  alg_std_lvl     // en het 'Verplichte niveau' specifieker is dan het 'Tonen vanaf'-niveau
          && alg_has_lvl <= alg_std_lvl) {  // en het 'Verplichte niveau' specifieker is dan het reeds ingevulde niveau
      sug_alg_lvl = alg_niveau;             // Gebruik dan het reeds ingevulde niveau
  } else {
    sug_alg_lvl = alg_onrgoed_niveau;       // Gebruik anders het 'Verplichte niveau'
  }

  if (typeof sgObject !== "undefined") {
    switch(sug_alg_lvl)
    {
      case "L": sgObject.editUrlAdd("alg_key", "locatiekey");     break;
      case "G": sgObject.editUrlAdd("alg_key", "gebouwkey");      break;
      case "V": sgObject.editUrlAdd("alg_key", "verdiepingkey");  break;
      case "R": sgObject.editUrlAdd("alg_key", "ruimtekey");      break;
    }
  }

  $("#suggest_alg_niveau").val(sug_alg_lvl);
}

var stdm_info = {}; // globaal onthouden
function process_stdm_info(data, stdmChanged) // stdmChanged is optioneel.
{
  if (stdmChanged) // Alleen bij nieuwe meldingen met een gekozen melding (stdmelding) en bij wijzigen van de melding (stdmelding)
  {
    // Plaatsgegevens wel of niet tonen.
    var hasVisibleAlg = $("#mldAlg").is(":visible");
    if (data.ins_srtdiscipline_alg && data.alg_onrgoed_niveau != "H") {
      if (!hasVisibleAlg) {
        $("#mldAlg").show();
        var last_alg_kostenplaats_key = $("#account_bld").data("stored-value");
        $("#account_bld").val(last_alg_kostenplaats_key);
      }
    } else {
      if (hasVisibleAlg) {
        $("#mldAlg").hide();
        if (($("#account_bld").val() || -1) > 0) {
          $("#account_bld").val(-1); // Het veld met de kostenplaats van het gekozen gebouw leegmaken.
          sgAccount.setValue($("#account").val(), $("#account_show").val(), false, true, $("#kmodule").val(), true);
        }
      }
    }

    // Afleveradres wel of niet tonen.
    if (data.ins_srtdiscipline_bes > 0)
      $("#del_address").closest("tr").show();
    else
      $("#del_address").closest("tr").hide();

    // Objectgegevens wel of niet tonen.
    if (data.ins_srtdiscipline_ins && (data.alg_onrgoed_obj_niveau != "" || data.prsafdobj > 0))
    {
      if (!show_any_ref && !show_groepering) {
        $("#mldIns").show();
      }
      $(".tr_r_objs").show();
    }
    // Niet het hele block meer hiden, want er kunnen referenties of groeperingen in staan
    else
    {
      if (!show_any_ref && !show_groepering) {
        $("#mldIns").hide();
      }
      $(".tr_r_objs").hide();
    }

    // Actiedatum wel of niet tonen.
    $("#actiondate").closest("tr").toggle(data.show_actiedatum);

    if (data.tag_select_html) {
      $(".tr_tag").replaceWith(data.tag_select_html);
    }
  }

  window.stdm_info = data;
  if (!frontend)
    $("#naam_ext, #email_ext, #tel_ext").closest("tr").toggle(window.stdm_info.canholdthirdparty == "1");
  $("#canholdthirdparty").val(window.stdm_info.canholdthirdparty);
  if ((window.stdm_info.mld_stdmelding_key || -1) < 0) { // Als er geen melding (stdmelding) is geselecteerd dan hier stoppen.
    return;
  }

  if (mld_key < 0)
    FcltMgr.setTitle(data.stdmelding_omschrijving, { hot: true });

  if (stdmChanged)
  {
    if (typeof sgRef != "undefined") {
      setReferentie(stdm_info.kanverwijzen);
    }

    // De stdmelding heeft (mogelijk) invloed op de plaats-scope (minstens op het verplichte niveau), dus plaats invullen waar slechts 1 mogelijk
    if (!data.init) {
      cascadePlaatsSelector();
    }

    if (data.objects_allowed == 0) {
      $("#r_objs").parent().parent().addClass("hidden");
    } else {
      $("#r_objs").parent().parent().removeClass("hidden");
    }
  }

  // UWVA#15523: indien frontend, dan is het aan kunnen geven van de prio afhankelijk van de vakgroep
  // (door mld.stdmeldinginfo bepaald uit stdm_info.frontendprio)
  // Bij 1 mag FE kiezen (indien er meer prios zijn), anders is het 2 en readonly (niet onzichtbaar om rust te houden?)
  // Dat is dus alleen bij frontend, anders niet. Als we dat willen mag de waarde naar 2 gereset worden, dan.

  // startdatum is aanwezig, zichtbaar of hidden
  $("#show_startdate").closest("tr").toggle(stdm_info.startdatum);
  if ($("#show_startdate").attr("readOnly") != 'readonly')
  {
    $("#show_startdate").toggleClass("required", stdm_info.startdatum);
  }

  // Mag/Moet ik de prioriteit aanpassen?
  if (!(frontend && hide_prio) && stdmChanged)
  {
    // Vervang de prioriteit selector lijst. Initieel gebeurt nu serverside (stdmChanged toegevoegd).
    // canPrioChange is mede afhankelijk van planbaarheid van gekozen Vakgroep. Hier dus opnieuw bepalen.
    // FO en BO mogen als ze mogen wijzigen ook altijd datums aanpassen
    // FE mag datums aanpassen bij 1) nieuwe melding, 2) status 1 en 2.
    // Als melding planbaar is mag prioriteit nooit aangepast worden.
    var canPrioChange = (stdm_info.planbaarfe == 0 && (canFOwrite || (canFEwrite && stdm_info.frontendprio && (mld_key < 0 || mld_status == 1 || mld_status == 2)))? 1 : 0);
    $("#prio, #prio_ro").closest("td").load("loadPrioriteit.asp?stdm_key=" + stdm_info.mld_stdmelding_key + "&mprio=" + ($("#prio :selected").val() || mprio) + "&readonly=" + (canPrioChange? 0 : 1));
    $(".tr_prio").show();
  }
  else if (!stdmChanged)
  { // Tijdens initialisatie aanroep van process_stdm_info kan de prioriteit hidden moeten zijn
      $(".tr_prio").show();
  }

  if ($("#account_show").length && !$("#account_show")[0].readOnly)
  {
    // Is de kostenplaats nu verplicht?
    if (stdm_info.kpnverplicht)
    { // class required zetten
      $("input#account_show").addClass("required");
      // Indien kostenplaats niet gevuld is dan deze default vullen.
      // Key en string moeten wel een (geldige) waarde hebben. (Dit is bijvoorbeeld niet het geval als process_stdm_info() wordt
      // aangeroepen door de ready functie in mld_edit_melding.asp
      // Als stdm_info.caller_kpn_key == -1 dan mag de (lege) waarde blijven staan
      if ($("#account").val() == -1 && stdm_info.caller_kpn_key && stdm_info.caller_kpn_string &&
          stdm_info.kp_key == null) // Indien er een kostenplaats is gedefinieerd bij de stdmelding, dan wordt deze verderop ingevuld.
        // setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
        sgAccount.setValue(stdm_info.caller_kpn_key, stdm_info.caller_kpn_string, true, true, stdm_info.caller_kpn_module, true);
    }
    else
    { // class required verwijderen
      $("input#account_show").removeClass("required");
    }

    // Indien er een kostenplaats is gedefinieerd bij de stdmelding, dan deze invullen.
    // Dan moet kostenklant niet aangevinkt zijn, anders kan de kostenplaats waarschijnlijk niet geselecteerd worden.
    if (stdmChanged && stdm_info.kp_key > 0)
    {
      $("#kostenklant").prop("checked", false);
      onChangeKk();
      //setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
      setTimeout(function () { sgAccount.setValue(stdm_info.kp_key, stdm_info.kpstring, true, true, stdm_info.kpmodule, true); }, 100);
    }
  }

  // Is er een object verplicht
  var stdm_info_verplichtstatus = stdm_info.srtinst_verplichtstatus == 2 || stdm_info.srtinst_verplichtstatus == 21;
  $("#req_r_objs,#r_objs,#r_objs_button,#r_objs option,#r_objs_show").toggleClass("required", stdm_info_verplichtstatus);

  // Valideer of de gekozen objecten nog valide zijn bij deze stdmelding
  if (stdmChanged) {
    var isSuggest = $("select#r_objs").hasClass("hidden"); // 1 of [n]?
    if (isSuggest) {
      sgObject.setValue(sgObject.getValue(), $("#r_objs_show").val(), false, true);
    } else {
      // Deze checken we verderop pas, in process_object_info()
    }
  }

  // Locatie is niet meer altijd verplicht (required)
  switch( (stdm_info.alg_onrgoed_niveau?stdm_info.alg_onrgoed_niveau:"x"))
  {
    case "x": $("#locatie").removeClass("required");
              $("#gebouw").removeClass("required");
              $("#verdieping").removeClass("required");
              $("#ruimte").removeClass("required");
              window.requiredlevel = 1; // Required level van de plaatsselector aanpassen.
              break;
    case "L": $("#locatie").addClass("required");
              $("#gebouw").removeClass("required");
              $("#verdieping").removeClass("required");
              $("#ruimte").removeClass("required");
              window.requiredlevel = 2; // Required level van de plaatsselector aanpassen.
              break;
    case "G": $("#locatie").addClass("required");
              $("#gebouw").addClass("required");
              $("#verdieping").removeClass("required");
              $("#ruimte").removeClass("required");
              window.requiredlevel = 3; // Required level van de plaatsselector aanpassen.
              break;
    case "V": $("#locatie").addClass("required");
              $("#gebouw").addClass("required");
              if ($("#bttype").val() != "T") // Als er een terrein is geselecteerd dan verdieping niet verplicht maken.
                $("#verdieping").addClass("required");
              $("#ruimte").removeClass("required");
              window.requiredlevel = 4; // Required level van de plaatsselector aanpassen.
              break;
    case "R": $("#locatie").addClass("required");
              $("#gebouw").addClass("required");
              if ($("#bttype").val() != "T")
              { // Als er een terrein is geselecteerd dan verdieping en ruimte niet verplicht maken.
                $("#verdieping").addClass("required");
                $("#ruimte").addClass("required");
              }
              window.requiredlevel = 5; // Required level van de plaatsselector aanpassen.
              break;
  }
  // Show faq when at least required level has a value
  if (levelHasValue(window.requiredlevel)) {
    onChangeAlg(findFilledLevel());
  }

  // Zet de discipline indien niet ingevuld. Voor frontend is id afhankelijk van de setting mld_selector_mode.
  if ($("#disc").val() <= 0 || (frontend && (mld_selector_mode == 1 || mld_selector_mode == 2)))
  {
    if (typeof sgDisc != "undefined")
    {
      sgDisc.setValue(stdm_info.ins_discipline_key, (stdm_info.ins_srtdiscipline_prefix != null ? stdm_info.ins_srtdiscipline_prefix + "-" : "") + stdm_info.discipline_omschrijving, false /*doonChange*/, true /*checkExist*/);
    }
    else
    {
      // PF: is het niet een beetje illegaal om zo direct de show-waarde te zetten?
      $("#disc_show").val((stdm_info.ins_srtdiscipline_prefix != null ? stdm_info.ins_srtdiscipline_prefix + "-" : "") + stdm_info.discipline_omschrijving);
      $("#disc").val(stdm_info.ins_discipline_key);
    }
  }

  $("label[for=show_enddate]").html(((stdm_info.planbaar == 0 && stdm_info.planbaarfe == 1) ? L("lcl_mld_desirable_enddate"): L("lcl_mld_enddate")));

  if (stdmChanged) // Alleen bij nieuwe meldingen met een gekozen melding (stdmelding) en bij wijzigen van de melding (stdmelding)
  {
    // Verifiëren dat Vakgroep mag escaleren naar Behandelteam (srtgroep & 4)
    $.getJSON("./get_mld_info_ajax.asp",
        { req_info: "mld_ins_discipline",
          stdm_ins_discipline_key: stdm_info.ins_discipline_key,
          stdmChanged: stdmChanged },
          toggleBehandelteam);

    if (stdm_info.prioriteiten[mprio in stdm_info.prioriteiten ? mprio : 3].uitvoertijd == "")
    {
      $("#show_startdate").val(""); // $("#startdate") niet leeg maken! recalcEinddatum() heeft hiervoor een geldige datum nodig.
    }
    else
    { // Is startdate ingevuld?. Indien niet ingevuld dan sysdate nemen
      if (!$("#show_startdate").datepicker("getDate"))
      { // Zet startdatum op vandaag
        $("#show_startdate").datepicker("setDate", new Date());
      }
    }

    // Vervang de kalender gereed indien
    // 1) niet planbaar
    // 2) planbaar zowel voor FE als nu voor FO/BO (RWSN#23829)
    // 3) mld_melding.mld_melding_t_uitvoertijd.eenheid == "U" en geen tijd aanwezig (Toevoegen tijdsveld).
    // 4) Tijd moet niet zichtbaar zijn, maar is wel aanwezig (Verwijderen tijdsveld).
    // Einddatum nu ook altijd opnieuw bepalen en dan tonen (recalcEinddatum() waarna processEinddatum() volgt)
    recalcEinddatum();

    if ($("#respijt").length > 0)
    { // Respijt is aanwezig en stdmelding is aangepast. Dan respijt leegmaken en verwijderen.
      // Bij de volgende edit actie is respijt dan weer te wijzigen.
      $("#respijt").closest("tr").css("display", "none");
      $("#respijt").val(0);
    }
  }

  // Moet de omschrijving nu getoond worden en is de omschrijving dan verplicht?
  var toggleomschrijving = (stdm_info.freetext != 0 || stdm_info.subject != 0);
  $("#mldOmschrijving").parent().toggle(toggleomschrijving).toggleClass("block-wrapper", toggleomschrijving); // Anders gaat Masonry hier omheen bouwen

  // Alleen individueel tonen/verstoppen als het blok daadwerkelijk verschijnt.
  if (toggleomschrijving)
  { // Het gehele blok met de velden omschrijving en onderwerp is zichtbaar.
    // Afzonderlijk kijken welke velden zichtbaar zijn.
    // De velden disabelen indien de velden niet zichtbaar zijn, zodat ze dan niet opgeslagen worden.
    $("#melding_omschrijving").toggle(stdm_info.freetext != 0) // verstop de omschrijving
                              .prop('disabled', (stdm_info.freetext == 0))
                              .closest('td').prev().toggle(stdm_info.freetext != 0) // verstop ook het bijbehorende label
                              .closest('tr').toggle(stdm_info.freetext != 0); // hide the tr to preserve table-column width
    var hideSubject = stdm_info.subject == 0 || (stdm_info.subject == 3 && mld_key < 0 && !canFOwrite);
    $("#melding_onderwerp").toggle(!hideSubject) // verstop het onderwerp
                           .prop('disabled', hideSubject)
                           .closest('td').prev().toggle(!hideSubject) // verstop ook bijbehorende label
                           .closest('tr').toggle(!hideSubject); // hide the tr to preserve table-column width
  }
  else
  { // Het gehele blok met de velden omschrijving en onderwerp is onzichtbaar mb.
    // De velden in het blok disabled maken zodat ze niet opgeslagen worden.
    $("#melding_omschrijving").prop('disabled', true);
    $("#melding_onderwerp").prop('disabled', true);
  }

  if (stdm_info.freetext == 2 && !$("#melding_omschrijving").is("[readonly]"))
  { // class required zetten
    $("#melding_omschrijving").addClass("required");
  }
  else
  { // class required verwijderen
    $("#melding_omschrijving").removeClass("required");
  }

  if (   (   stdm_info.subject == 2                  // Verplicht
          || stdm_info.subject == 3 && mld_key > 0)  // Reeds door AI ingevuld
      && !$("#melding_onderwerp")[0].readOnly)
  { // class required zetten
    $("#melding_onderwerp").addClass("required");
  }
  else
  { // class required verwijderen
    $("#melding_onderwerp").removeClass("required");
  }

  // Toggle placeholder onderwerp
  if (stdm_info.subject == 3 && mld_key == -1 && !$("#melding_onderwerp")[0]?.readOnly) {
    $("#melding_onderwerp").attr("placeholder", L("lcl_mld_ai_generate_subject_placeholder"));
  } else {
    $("#melding_onderwerp").attr("placeholder", "");
  }

  // Het niveau van onroerendgoed die geselecteerd moet zijn vanaf waar plaats gebonden objecten gekozen kunnen worden.
  $("#alg_onrgoed_obj_niveau").val(stdm_info.alg_onrgoed_obj_niveau);

  // Het niveau van de organisatie die geselecteerd moet zijn vanaf waar organisatie gebonden objecten gekozen kunnen worden.
  $("#prsafdobj").val(stdm_info.prsafdobj);

  showObjectInfo(stdmChanged);
}

function showObjectInfo(stdmChanged)
{ // Is er voor de stdmelding aangegeven dat ik uberhaubt geen enkel plaats-, afdelings- of persoonsgebonden object wil kunnen selecteren?
  var prs_key = ($("#personFor").length > 0? $("#personFor").val() : $("#person").val());
  var showAlgObjects = stdm_info.alg_onrgoed_obj_niveau != "";
  var showPrsObjects = stdm_info.prsafdobj > 0 && (stdm_info.alg_org_obj_niveau != 9 || prs_key > 0); // Alleen als ik een prs_key heb, kan ik afdelings- en persoonsgebonden objecten bepalen.
  var has_stdm_key = $("#stdm").val() > 0;

  var disableobjects = !showAlgObjects && !showPrsObjects || !has_stdm_key;

  if (has_stdm_key && showAlgObjects && !showPrsObjects)
  { // Ik wil alleen plaatsgebonden objecten willen zien. Maar vanaf welk niveau?
    // Het veld stdm_info.alg_onrgoed_obj_niveau kan alleen de waarden "L", "G", "V", "R" en ""(geen objecten) bevatten.
    switch(stdm_info.alg_onrgoed_obj_niveau)
    {
      case "L": if ($("#locatiekey").val() < 0)
                  disableobjects = true;
                break;
      case "G": if ($("#gebouwkey").val() < 0)
                  disableobjects = true;
                break;
      case "V": if ($("#verdiepingkey").val() < 0)
                  disableobjects = true;
                break;
      case "R": if ($("#ruimtekey").val() < 0)
                  disableobjects = true;
                break;
    }
  }

  _toggleObjects(!disableobjects);

  if (!disableobjects) {
    getObjectInfo(stdmChanged);
  }
}

function onChangeVakgroep(vakgroep_key)
{
  $("#gebouw").removeClass("required");
  $("#verdieping").removeClass("required");
  $("#ruimte").removeClass("required");

  $("#req_r_objs,#r_objs,#r_objs_button,#r_objs option,#r_objs_show").removeClass("required");

  // reset processing team
  if (typeof sgDisc2 != "undefined")
  {
    sgDisc2.setValue(-1, "");
  }

  //sgStdm.setValue($("#stdm").val(), $("#stdm_show").val(), true, true, null, true);
  // Regel hierboven werkt niet goed omdat CheckExist een get call veroorzaakt om te kijken of waarde bestaat.
  // In de tussentijd verstoort CheckJustOne dit process met een $.getJSON()
  // Dus gewoon Melding leegmaken
  sgStdm.setValue(-1, "", true, false, null, true);
  sgStdm.CheckJustOne();
  if (window.sgBehandelaar)
    sgBehandelaar.setValue($("#sBehandel").val(), $("#sBehandel_show").val(), true, true);

  if (vakgroep_key > 0)
  {
    $.getJSON("./get_mld_info_ajax.asp",
              { req_info: "mld_ins_discipline",
                stdm_ins_discipline_key: vakgroep_key },
                toggleBehandelteam);
  }
  else if (vakgroep_key == -1)
    toggleBehandelteam({ "srtgroep": 0 });
}
function findFilledLevel()
{
  var _level = 0;
  if (!!$("#locatie").val())    { _level = 2; } // location has a value
  if (!!$("#gebouw").val())     { _level = 3; } // building has a value
  if (!!$("#verdieping").val()) { _level = 4; } // floor has a value
  if (!!$("#ruimte").val())     { _level = 5; } // room has a value
  return _level;
}
function levelHasValue(level)
{
  switch (level) {
    case 5: return $("#ruimtekey").val();
    case 4: return $("#verdiepingkey").val();
    case 3: return $("#gebouwkey").val();
    case 2: return $("#locatiekey").val();
    default: return undefined;
  }
}

function togglePriomatrix()
{
  if ($("#priomatrix").val() == 1)
    $(".tr_priomatrix").show();
  else
    $(".tr_priomatrix").hide();
}

function onChangeStdMelding(stdmelding_key, txt, params)
{
  var ins_disc = $("#disc").val();
  var loc = $("#locatiekey").val() || -1;
  var changed = 1; // onChangeVakgroep nog niet geimplementeerd.

  if ((changed == 0 && ins_disc && ins_disc > 0) ||
      (changed == 1 && stdmelding_key && stdmelding_key > 0))
  {
      var alg_key_arr = [];
      if (loc > 0)
      {
          var bld = $("#gebouwkey").val();
          if (bld && bld != -1)
              alg_key_arr.push(bld);
          var flr = $("#verdiepingkey").val();
          if (flr && flr != -1)
              alg_key_arr.push(flr);
          var room = $("#ruimtekey").val();
          if (room && room != -1)
              alg_key_arr.push(room);
      }
      var afd_key = $("#prs_afd_key").val();
      $.getJSON("./get_mld_info_ajax.asp",
                { req_info: "faq_info",
                  loc_key: loc,
                  alg_key_arr: alg_key_arr.join(","),
                  changed: changed,
                  ins_disc_key: ins_disc,
                  stdm_key: stdmelding_key,
                  afd_key: afd_key
                },
                callback_faq_info);
  }
  else
      show_fixed_faq("mldFaq", changed, [], faq_max_results_mld);

  params = params || {};
  if (stdmelding_key > 0)
  {
    $.getJSON("./get_mld_info_ajax.asp",
              { req_info: "mld_stdmelding",
                urole: ($("#urole").val() || "fe"),
                mld_stdmelding_key: stdmelding_key,
                mld_key: mld_key,
                copy: params.copy ? 1 : 0,
                init: params.init ? 1 : 0, // Initialisatie OnChange (initOnChange) van FCLTstdmeldingselector.
                caller_key: $("#person").val() },
                callback_stdm_info);
  }
  else
  {
    if (typeof sgRef != "undefined") setReferentie(0);
    stdm_info = {mld_stdmelding_key: -1};
    $("#req_r_objs,#r_objs,#r_objs_button,#r_objs option,#r_objs_show").removeClass("required");
    $(".tr_tag").hide();
  }
  if (!params.init && !params.copy) { loadKenmerk(); } // Bij initialisatie (initOnChange) niet de kenmerken herladen anders worden de waarden gewist.

  togglePriomatrix();
}

function _hasObjects() {
  var isSuggest = $("select#r_objs").hasClass("hidden");
  return !isSuggest || typeof sgObject !== "undefined" && sgObject.getValue() > -1;
}

// Wisselen tussen het al dan niet toestaan van objecten-invoer
function _toggleObjects(enable) {
  if (enable) {
    $("#r_objs_button").attr("disabled", false);
    $("div.r_objs.nowrap").removeClass("disabled");
  } else {
    window._cachedInsData = null;
    $("#r_objs_button").val(L("lcl_mld_objects") + " (0)");
    if (mld_key == -1 && !_hasObjects()) {
      $("#r_objs_button").attr("disabled", true);
      $("div.r_objs.nowrap").addClass("disabled");
    }
  }
}

// Wisselen tussen de suggest of de popup manier van objecten-invoer
function _toggleObjectPicker(count)
{
  if (count == 0)
      $("#r_objs").html("");

  if (typeof sgObject == "undefined")
    return;
  else if (count != 1)
    sgObject.setValue(-1, "");

  var isSuggest = $("select#r_objs").hasClass("hidden");
  if (count == 0 || count == 1)
  { // Make suggest
    if (isSuggest)
        return;
    $("select#r_objs").addClass("hidden");
    $("div.r_objs.nowrap").removeClass("hidden");
    if (count == 1) {
      var $opt = $("#r_objs > option").eq(0);
      var extraParams = {
        "uitvoertijd": $opt.attr("uitvoertijd")
      }
      sgObject.setValue($opt.val(), $opt.text(), null, null, null, null, extraParams);
    }
  }
  else
  {
    if (!isSuggest)
        return;
    $("select#r_objs").removeClass("hidden");
    $("div.r_objs.nowrap").addClass("hidden");
  }
  FcltMgr.resized(window);
}

function cascadePlaatsSelector()
{
    if (!window.sgLoc || !window.sgBld || $("#locatiekey").val() == -1) // Er valt niets te cascaderen
        return;

    if ($("#gebouwkey").val() == -1) {
      sgLoc.setValue($("#locatiekey").val(), $("#locatie").val(), true, true);
    } else if (window.sgFlr) {
        if ($("#verdiepingkey").val() == -1) {
          sgBld.setValue($("#gebouwkey").val(), $("#gebouw").val(), true, true);
        } else if (window.sgRoom && $("#ruimtekey").val() == -1) {
          sgFlr.setValue($("#verdiepingkey").val(), $("#verdieping").val(), true, true);
        }
    }
}

function onChangeObject(objectKey)
{
  if (objectKey == -1) {
      $("#r_objs").html("");
  } else {
      var $suggest = $("div.r_objs.nowrap input.suggest");
      var $opt = $("<option>" + $suggest.attr("sgCurrentValue") + "</option>")
                  .attr("value", $suggest.attr("sgKey"))
                  .attr("uitvoertijd", $suggest.attr("uitvoertijd"));
      $("select#r_objs").html($opt[0]);

      $.getJSON("../mld/get_mld_info_ajax.asp",
          { req_info: "ggd",
            obj_keys: objectKey
          },
          process_GGD_info);
  }

  // Einddatum kan veranderd zijn als er objecten worden toegevoegd of verwijderd.
  recalcEinddatum(false); // Einddatum kan veranderd zijn als uitvoertijd afhankelijk is van srtruimte.
}

async function checkPrerequisite()
{
  var alg_onrgoed_obj_niveau = $("#alg_onrgoed_obj_niveau").val();
  // Melding is altijd verplicht voordat objecten gekozen kunnen worden en locatie alleen als er een alg niveau is gekozen.
  var checkOnly = ["stdm_show"];
  var prsafdobj = $("#prsafdobj").val(); // Vanaf welk PRS niveau laten we organisatiegebonden objecten zien?
  if (!(prsafdobj > 0)) { // Als er geen organisatiegebonden objecten zijn toegestaan, is een plaats verplicht
    if (alg_onrgoed_obj_niveau != "" && alg_onrgoed_obj_niveau != "A") {
      checkOnly.push("locatie"); // Er is een alg niveau gekozen.
    }
  }
  return await validateForm("u2", { checkOnly: checkOnly, noBlur: true });
}

function onChangeBehandelteam(behandelteam_key)
{
  if (typeof sgBehandelaar2 != "undefined")
  {
    if (behandelteam_key == -1) // Efficiënter
      sgBehandelaar2.setValue(-1, "");
    else
      sgBehandelaar2.setValue($("#sBehandel2").val(), $("#sBehandel2_show").val(), true, true);
  }
}

function onChangeAfgerond(checkbox)
{
  var afgerond = !!$(checkbox).prop("checked");
  $("[data-required-completed=1]").toggleClass("required", afgerond)
                                  .attr("required", (afgerond ? "required" : null));
}

function toggleBehandelteam(data)
{
  if (data.srtgroep & 4)
  {
    // Toggle on
    if (show_abh)
      $("#mldProcessing").show();

    // Set new default Behandelteam if there is one and the field ((is currently empty) or (is hidden and was initially empty))
    if (data.stdmChanged && (!($("#mld_ins_discipline").val() > 0) || alwaysSetBht))
    {
      if (stdm_info.default_ins_disc_key > 0)
        // Verifiëren dat Behandelteam ook echt Behandelteam mag zijn (srtgroep & 2)
        $.getJSON("./get_mld_info_ajax.asp",
                  { req_info: "mld_ins_discipline",
                    mld_ins_discipline_key: stdm_info.default_ins_disc_key },
                    setBehandelteam);
      else if (alwaysSetBht)
        setBehandelteam(); // Maak behandelteam en behandelaar leeg.
    }
  }
  else
  {
    // Toggle off
    if (show_abh)
      $("#mldProcessing").hide();

    setBehandelteam(); // Maak behandelteam en behandelaar leeg.
  }
  if (show_abh)
    FcltMgr.resized();
}

function setBehandelteam(data)
{
    if (data != null)
    {
        if (typeof sgDisc2 != "undefined")
            sgDisc2.setValue(data.def_ins_disc_key, data.def_ins_disc_descr, true, true);
        else
            $("input#mld_ins_discipline").val(data.def_ins_disc_key);
    }
    else
    {   // Empty 'Behandelteam' & 'Actieve behandelaar' value
        if (typeof sgDisc2 != "undefined")
        {
            sgDisc2.setValue(-1, "");
            sgBehandelaar2.setValue(-1, "");
        }
        else
        {
            $("input#mld_ins_discipline").val(-1);
            $("input#sBehandel2").val(-1);
        }
    }
}

function onChangeStartdatum()
{ // Startdatum kalender is zichtbaar, want anders geen aanroep van deze functie
  recalcEinddatum(); // die zoekt het verder wel uit?
}

function onChangeActiondate()
{ // Als bij een bestaande melding de startdatum niet planbaar en dus niet zichtbaar is,
  // dan kan het voorkomen dat de startdatum naar het verleden wordt gezet door de actiedatum naar het verleden te zetten.
  // Als dan de actiedatum weer naar de toekomst wordt gezet blijft de startdatum in het verleden staan wat niet de bedoeling is.
  var startdate = parseInt($("#startdate").val()); // Inclusief tijd
  var enddate = parseInt($("#enddate").val());
  if (mld_key > 0 && stdm_info.planbaar == 0 && stdm_info.planbaar_fe == 0 && startdate < melddatum)
  {
    if (enddate < melddatum)
      var nw = enddate; // startdatum wordt einddatum.
    else
      var nw = melddatum; // startdatum wordt melddatum.
    $("#show_startdate").datepicker("setDate", new Date(nw));
    $("#startdate").val(nw);
  }
  // else startdum == melddatum.

  var sysdate = new Date();
  var actiondate = new Date(parseInt($("#actiondate").val(), 10));
  var actiondate_is_today = (actiondate.midnight().getTime() == sysdate.midnight().getTime());
  $("#show_actiondate").toggleClass("today", actiondate_is_today);
}

function onChangeEnddate()
{ // Als bij een bestaande melding de startdatum niet planbaar en dus niet zichtbaar is,
  // dan kan het voorkomen dat de startdatum naar het verleden wordt gezet door de einddatum naar het verleden te zetten.
  // Als dan de einddatum weer naar de toekomst wordt gezet blijft de startdatum in het verleden staan wat niet de bedoeling is.
  var startdate = parseInt($("#startdate").val()); // Inclusief tijd
  var enddate = parseInt($("#enddate").val());
  if (mld_key > 0 && stdm_info.planbaar == 0 && stdm_info.planbaar_fe == 0 && startdate < melddatum)
  {
    if (enddate < melddatum)
      var nw = enddate; // startdatum wordt einddatum.
    else
      var nw = melddatum; // startdatum wordt melddatum.
    $("#show_startdate").datepicker("setDate", new Date(nw));
    $("#startdate").val(nw);
  }
  // else startdum == melddatum.
}

// GGD = grootste gemeenschappelijke deler
function process_GGD_info(data)
{
  if (!data) {
    return;
  }

  // De plaatsselector nu met de juiste waarden vullen.
  // Parameter doonChange = false: Eigen werkplek moet niet automatisch ingevuld worden. (Bij ruimte kan dit wel)
  switch (data.alg_type) {
    case "L": // setValue(key, txt, doonChange, checkExist, extraParam, lastTry);
              // lastTry is true zodat suggestbox wordt leeggemaakt indien waarde niet voorkomt (en niet de laatst waarde wordt getoond)
              window.sgLoc && sgLoc.setValue(data.alg_key, data.alg_oms, false, true, null, true);
              break;
    case "G":
    case "T": window.sgBld && sgBld.setValue(data.alg_key, data.alg_oms, false, true, null, true);
              window.sgLoc && sgLoc.setValue(data.loc_key, data.loc_oms, false, true, null, true);
              break;
    case "V": window.sgFlr && sgFlr.setValue(data.alg_key, data.alg_oms, false, true, null, true);
              window.sgBld && sgBld.setValue(data.geb_key, data.geb_oms, false, true, null, true);
              window.sgLoc && sgLoc.setValue(data.loc_key, data.loc_oms, false, true, null, true);
              break;
    case "R": if ($("#ruimtekey").val() != data.alg_key)
              { // De alg_oms bevat "geb_oms - ver_oms - rui_oms". Daarom verdieping en gebouw legen, anders wordt de ruimte niet ingevuld.
                // Afhankelijk van ingevulde waarden van gebouw en verdieping is de omschrijving van de ruimte namelijk anders
                window.sgFlr && sgFlr.setValue(-1, "");
                window.sgBld && sgBld.setValue(-1, "");
                window.sgRoom && sgRoom.setValue(data.alg_key, data.alg_oms, true, true, null, true);

                // Als er geen ruimte selector is of het was een virtuele ruimte die niet mogen, dan alsnog de Flr en Bld correct invullen.
                (!window.sgRoom || $("#ruimte").val() != data.alg_oms) && window.sgLoc && sgLoc.setValue(data.loc_key, data.loc_oms, false, true, null, true);
                (!window.sgRoom || $("#ruimte").val() != data.alg_oms) && window.sgBld && sgBld.setValue(data.geb_key, data.geb_oms, false, true, null, true);
                (!window.sgRoom || $("#ruimte").val() != data.alg_oms) && window.sgFlr && sgFlr.setValue(data.ver_key, data.ver_oms, false, true, null, true);
              }
              break;
  }
}

function mld_melding_object_callback(data)
{
  $("#r_objs").html(data.obj_html);
  var objCount = $("#r_objs")[0].options.length;

  $("#r_objs").attr("size", Math.max(objCount, 1));
  $("#r_objs > option").removeAttr("selected");

  if (objCount == 1) {
    var $opt = $("#r_objs > option").eq(0);
    var extraParams = {
      "uitvoertijd": $opt.attr("uitvoertijd")
    }
    sgObject.setValue($opt.val(), $opt.text(), null, null, null, null, extraParams);
  }

  _toggleObjectPicker(objCount);

  var obj_keys = $.map($("#r_objs option") , function(option) { return $(option).val(); }); // Levert array met objecten op.
  if (obj_keys.length > 0) {
    $.getJSON("../mld/get_mld_info_ajax.asp",
              { req_info: "ggd",
                obj_keys: obj_keys.join(",")
              },
              process_GGD_info);
  }

  // Einddatum kan veranderd zijn als er objecten worden toegevoegd of verwijderd.
  recalcEinddatum(false); // Einddatum kan veranderd zijn als uitvoertijd afhankelijk is van srtruimte.
}

async function mld_melding_object()
{
  var alg_onrgoed_obj_niveau = $("#alg_onrgoed_obj_niveau").val();
  // Melding is altijd verplicht voordat objecten gekozen kunnen worden en locatie alleen als er een alg niveau is gekozen.
  var checkOnly = ["stdm_show"];
  var prsafdobj = $("#prsafdobj").val(); // Vanaf welk PRS niveau laten we organisatiegebonden objecten zien?
  if (!(prsafdobj > 0)) { // Als er geen organisatiegebonden objecten zijn toegestaan, is een plaats verplicht
    if (alg_onrgoed_obj_niveau != "" && alg_onrgoed_obj_niveau != "A") {
      checkOnly.push("locatie"); // Er is een alg niveau gekozen.
    }
  }
  if (!await validateForm("u2", { checkOnly: checkOnly }))
    return false;

  var obj_alg_lvl = $("#suggest_alg_niveau").val(); // Deze neemt het benodigde & beschikbare niveau reeds in acht
  var alg_key;
  switch (obj_alg_lvl) {
    case "H":
    case "L":
      alg_key = $("#locatiekey").val();
      break;
    case "G":
      alg_key = $("#gebouwkey").val();
      break;
    case "V":
      alg_key = $("#verdiepingkey").val();
      break;
    case "R":
      alg_key = $("#ruimtekey").val();
      break;
    case "A":
    case "":
      alg_key = -1;
      break;
  }

  var prs_key = -1;
  if (prsafdobj > 0) { // Persoon en/of Afdeling (beiden gebaseerd op deze prs_key)
    prs_key = $("#personFor").length > 0 ? $("#personFor").val() : $("#person").val();
  }

  var url = "../mld/mld_object.asp?mld_key=" + mld_key;
  url += "&stdm_key=" + $("#stdm").val();
  url += "&srtdisc=" + srtdisc_key;
  url += "&person=" + prs_key;
  url += "&alg_key=" + alg_key;
  url += "&alg_niveau=" + obj_alg_lvl;

  var isSuggest = $("#r_objs").hasClass("hidden");
  var $suggest = $("div.r_objs.nowrap input.suggest");

  if (isSuggest && $suggest.attr("sgKey") > 0) {
    var $opt = $("<option>" + $suggest.attr("sgCurrentValue") + "</option>")
                .attr("value", $suggest.attr("sgKey"))
                .attr("uitvoertijd", $suggest.attr("uitvoertijd"));
    var obj_html = $opt.get(0);
  } else if (!isSuggest && $("#r_objs")[0].options.length > 0 && $("#r_objs")[0].options[0].value > 0) {
    var obj_html = $("#r_objs").html(); // huidige objecten
  }
  FcltMgr.openModalDetail(url, L("lcl_mld_objects"), { obj_html: obj_html, callback: mld_melding_object_callback, objects_allowed: window.stdm_info.objects_allowed });
}

// einddatum/ calendar aanpassen
function processEinddatum(data, textStatus)
{
  data.einddatum = new Date(data.einddatum); // was nog millisec
  canFOwrite = data.canFOwrite;
  canBOwrite = data.canBOwrite;

  // Bijna goed alternatief alleen kan 'readonly' ook gewijzigd zijn vanwege planbaar?
  // $("#show_enddate").datepicker("setDate", new Date(data.einddatum))
  //                   .datepicker("option", "minDate", new Date(data.einddatum));

  // Bij de frontend zorgen we dat de Einddatum altijd ver genoeg (uitvoertijd) in de toekomst blijven liggen.
  // (bij FO/BO zorgen de calendertjes alleen zelf dat de een voor de ander blijft)

  // canWriteDatums is mede afhankelijk van planbaarheid van gekozen Melding. Hier dus opnieuw bepalen.
  // FO en BO mogen als ze mogen wijzigen ook altijd datums aanpassen.
  // FE mag datums aanpassen bij 1) een nieuwe melding en 2) in status 2. Daarbij moet deze melding planbaar zijn.
  // MGE : Voor canFOwrite geldt eigenlijk ook (mld_status == 0 || mld_status == 1 || mld_status == 2)
  //       Voor canBOwrite geldt eigenlijk ook (mld_status == 3 || mld_status == 7)
  //       Maar het gaat goed omdat bij editen canChange is gecheckt en daardoor wordt het wel afgedwongen (dezelfde rechten voor dezelfde status)
  var canWriteDatums = (stdm_info.planbaar == 0 && stdm_info.planbaarfe == 1 && canFEwrite && (mld_key < 0 || mld_status == 2)) || canFOwrite || canBOwrite;
  // Ook al kan de FE bij nieuwe invoer de einddatum niet aanpassen (readonly), dan moet deze datum wel opgeslagen worden.
  var saveValue = !canWriteDatums && mld_key < 0;
  var prio = $("#prio :selected").val() || 3;
  if (!(prio in stdm_info.prioriteiten)) // load(loadPrioriteit.asp) is hier nog niet klaar en na een stdmChanged kan het voorkomen dat de ingevulde prio niet bestaat
      prio = 3;
  $(".trenddate").toggle(stdm_info.planbaar != 2 && (stdm_info.planbaar == 0 && stdm_info.planbaarfe == 1 && canFEwrite || canFOwrite || canBOwrite));

  FcltMgr.resized(window);
  $("#show_enddate").closest("td").load("../Shared/loadCalendar.asp"
                                        + "?cal_id=enddate"
                                        + "&datum=" + data.einddatum.getTime()
                                        + ((stdm_info.planbaar == 1 && canWriteDatums) ? "&initEmpty=1" : "")
                                        + "&timeField=" + (stdm_info.prioriteiten[prio].eenheid == "U" || (mld_show_endtime == 1 && stdm_info.planbaar != 2 && stdm_info.planbaarfe == 0)? 1 : 0)
                                        + "&timeStep=15" // TODO: Is nog wel erg hard. Zie ook mld_edit_melding.asp
                                        + "&startTime=" + startOfWorkDay
                                        + "&endTime=" + endOfWorkDay
                                        + "&onChangeCode=1" // onChangeEnddate()
                                        + "&minDate=" + (frontend? data.einddatum.getTime() : -1)
                                        + "&readonly=" + (canWriteDatums? 0 : 1) // Met FO/BO rechten mag de datum altijd aangepast worden.
                                        + "&saveValue=" + (saveValue? 1 : 0) // Ondanks readonly moet de waarde toch opgeslagen worden.
                                        + "&required=1"
                                        + "&volgnr=3",
                                        function ()
                                        { // Check of de datums opeenvolgend zijn.
                                          cal_checkVolgnr("enddate", 3);
                                        }
                                       );
}

function recalcEinddatum(recalc_always)
{
    var recalc_always = (recalc_always === undefined ? true : recalc_always);
    // Er zijn twee situaties te onderscheiden:
    // 1) Startdatum is zichtbaar/wijzigbaar,
    //    De tijd van de startdatum is altijd de begintijd van de dag (setting "fac_t_startofworkday" bijvoorbeeld 8:00 uur)
    //    => Startdatum = TRUNC(startdatum) + 8:00 uur
    //    => Einddatum = TRUNC(startdatum) + 8:00 uur + SLA
    //    LET OP!!!: Als je deze setting zet dan wordt eigenlijk verondersteld dat de SLA in dagen is en niet in uren.
    //               Echter als de startdatum vandaag is moet wel voor de begintijd de huidige sysdate tijd genomen worden tijdens het opslaan.
    //               Anders geldt de acceptatietijd (in uren) onterecht al vanaf het begin van de dag.
    //               Voor het bepalen/berekenen van de einddatum laten de startdatum gewoon aan het begin van de dag beginnen.
    // 2) Startdatum is niet zichtbaar/wijzigbaar
    //    De tijd van de startdatum is de tijd van de huidige waarde of van de sysdate, COALESCE(huidige waarde, sysdate).
    //    => Startdatum = COALESCE(huidige waarde, sysdate)
    //    => Einddatum = COALESCE(huidige waarde, sysdate) + SLA
    // Of de startdatum wel of niet zichtbaar/wijzigbaar is, is in te stellen bij vakgroep door de setting "Startdatum te bepalen" (mld_disc_params_startdatum)

    // Hoort de melding bij een reservering.
    if ($("#rsv_ruimte_key").length > 0)
    { // De melding hoort bij een reservering. De class "mldres" toevoegen aan de einddatum kalender.
      $("#show_enddate").addClass("mldres");
      return; // De datum en tijd van de kalender niet aanpassen.
    }

    // Indien nieuwe reservering behorend bij een toekomstige reservering dan bij planbare meldingen de einddatum niet aanpassen.
    if (stdm_info.planbaar == 0 && stdm_info.planbaarfe == 1 && withFutureRes)
      return;

    // var startdate = $("#show_startdate").datepicker("getDate"); // bij nieuwe melding is er nog geen datepicker van gemaakt
    var startdate = new Date(parseInt($("#startdate").val(),10));
    var sysdate = new Date();

    var startwerkdag_uur = Math.floor(startOfWorkDay);
    var startwerkdag_min = (startOfWorkDay - Math.floor(startOfWorkDay)) * 60;
    var startdatebegin = new Date(startdate.getFullYear(), startdate.getMonth(), startdate.getDate(), startwerkdag_uur, startwerkdag_min);

    if (stdm_info.startdatum == 1)
    { // Situatie 1: Einddatum = TRUNC(startdatum) + 8:00 uur + SLA
      // LET OP!!!: Als setting "mld_disc_params_startdatum" is gezet dan wordt eigenlijk verondersteld dat de SLA in dagen is en niet in uren.
      //            Echter als de startdatum vandaag is moet wel voor de begintijd de huidige sysdate tijd genomen worden tijdens het opslaan.
      //            Anders geldt de acceptatietijd (in uren) onterecht al vanaf het begin van de dag.
      //            Voor het bepalen/berekenen van de einddatum laten de startdatum gewoon aan het begin van de dag beginnen.
      var startdate_is_today = (startdate.midnight().getTime() == sysdate.midnight().getTime());
      startdatum = (startdate_is_today? sysdate.getTime() : startdatebegin.getTime());
    }
    else
    { // Situatie 2: Einddatum = COALESCE(huidige waarde, sysdate) + SLA
      if (mld_key < 0)
        var startdatum = sysdate.getTime(); // Nieuwe melding, nu/sysdate
      else
        var startdatum = startdate.getTime(); // Wijziging melding, huidige opgeslagen waarde
    }

    // srtdisc: De srtdiscipline is gegarandeerd een vaste waarde.
    var disc_key = $("#disc").val();
    var stdm_key = $("#stdm").val();
    var prio = $("#prio :selected").val() || 3;
    var geb_key = $('#gebouwkey').val();
    var rui_key = $('#ruimtekey').val();

    // Bepaal het object met de laagste uitvoertijd (Als deze er is)
    var minValue;
    var ins_key = -1;
    $('#r_objs option').each(function(j, selected)
                             {
                               var okey = $(this).val();
                               var uitvoertijd = $(this).attr('uitvoertijd');
                               if (uitvoertijd)
                               {
                                 uitvoertijd = parseFloat(String(uitvoertijd).replace(',', '.'));
                                 if (!minValue || minValue > uitvoertijd)
                                 {
                                   minValue = uitvoertijd;
                                   ins_key = okey;
                                 }
                               }
                             });
    if (!$("#r_objs").length || ($("#r_objs").length && ins_key != -1 && !recalc_always) || recalc_always) // Alleen opnieuw de eindtijd bepalen als er een object met uitvoertijd is.
    {
        // daarmee kan ik de database de einddatum laten bepalen
        var params = { req_info: "calc_einddatum",
                       startdatum: startdatum,
                       srtdisc: srtdisc_key,
                       disc: disc_key,
                       stdm_key: stdm_key,
                       prio: prio,
                       geb_key: geb_key,
                       rui_key: rui_key,
                       ins_key: ins_key
                     }

        // Bepalen van de datum en het vervangen van de einddatum kalender moet synchroon (na elkaar) uitgevoerd worden.
        // Er kunnen anders problemen ontstaan als in de plaatsselector automatisch een ruimte wordt ingevuld na het invullen van een ander plaats veld.
        // In de gevallen dat de tweede aanroep eerder klaar is dan de eerste kan een verkeerde datum worden ingevuld (PCHA#54803).
        jQuery.ajaxSetup({async: false});
        $.getJSON("./get_mld_info_ajax.asp",
                  params,
                  processEinddatum);
        jQuery.ajaxSetup({async: true});
    }
}