<% /*
    $Revision$
    $Id$

    File:        notes.inc
    Description: Generieke functies die door modules gebruikt worden op notities te tonen, wijzigen en aan te maken.
    Parameters:
    Context:     Vanuit xxx_show_note2 asp bestanden
    Note:

*/ %>
<!-- #include file="../Shared/FlexFiles.inc" -->
<!-- #include file="../Shared/selector.inc" -->
<!-- #include file="../Shared/persoonselector.inc" -->
<%
notes =
{
    note_toggles: function _note_toggles(pmodule, params)
    {
        params = params || {}; // params.pkey is sowieso nodig maargoed
%>
        <script>
            var S_mld_note_hidden_action2FE = <%=S("mld_note_hidden_action2FE")%>;
            function notificatie_detail(noti_key)
            {
                FcltMgr.openDetail("appl/mgt/fac_notificatie.asp?mode=wrap&id=" + noti_key);
            }
            function notificatie_detail2(pkey, srtkey)
            {
                FcltMgr.openDetail("appl/mgt/fac_notificatie.asp?mode=search&fac_notificatie_refkey=" + pkey+  "&fac_srtnotificatie_key=" + srtkey);
            }
        </script>
<%
        Response.Write("<div class='note-options'>");

        // Wie ben ik? (BO = FOBO)
        // MELDING: FE &1 / BO &2
        // OPDR:    FE &1 / BO &2 / UITV &4
        var BITROLE = { "EXT":  0,
                        "FE":   1,
                        "BO":   2,
                        "Geen": 3, // Ik heb geen specifieke rechten maar mag toch notities maken, public melding ofzo?
                        "UITV": 4 };

        // Ja, deze is andersom ..
        var BITACTIONROLE = { "FE":   2,
                              "BO":   1,
                              "UITV": 4 };

        // Attentie bitwaardes.
        var BITATTENTION = { "BO":   128,   // 128 (1 x 128)
                             "FE":   256,   // 256 (2 x 128)
                             "UITV": 512 }; // 512 (4 x 128)

        // Defaults (Die kunnen we net zo goed hier bepalen, de objecten met info zijn vaak al aangemaakt en server-side 'globaal' benaderbaar)
        if (pmodule === "MLD")
        {
            var this_mld = params.this_mld || mld.func_enabled_melding(params.pkey);

            var mld_info = params.mld_info || mld.mld_melding_info(params.pkey);

            params.note_zichtbaarExt    = mld_info.canholdthirdparty && mld_info.email_ext;
            params.haschild             = mld_info.haschild;
            params.publiek              = mld_info.publiek;
            params.eigenMelding         = user_key == mld_info.melder_key;
            params.myRole               = "myRole" in params
                                            ? params.myRole
                                            : ( this_mld.haveOnlyFErights ||
                                                (!(mld_info.stdm_notes & BITROLE["BO"]) && params.eigenMelding) // Als de Backoffice niet meedoet bij notities, dan gaan we aanvragers primair als FE-er zien
                                                ? 1
                                                : (this_mld.canFOread || this_mld.canBOread || this_mld.canChangeKenmerkBlok
                                                    ? 2
                                                    : 3));
            params.fobo_prskey          = (("mld_ins_discipline_key" in mld_info && mld_info.mld_ins_discipline_key > 0) ? mld_info.behandel2_key : mld_info.behandel_key);
        }

        if (pmodule === "OPDR")
        {
            var this_opdr = params.this_opdr || mld.func_enabled_opdracht(params.pkey);

            var mld_info = params.mld_info || mld.mld_melding_info(this_opdr.mld_opdr.mld_key);

            params.myRole               = "myRole" in params ? params.myRole : this_opdr.myRole;
            params.opdr_actiecode       = this_opdr.mld_opdr.actiecode;
            params.uitv_naam            = this_opdr.mld_opdr.uitv_naam;
            params.fobo_prskey          = this_opdr.mld_opdr.contactpers_key;
        }

        // Voor zowel MLD als OPDR
        params.mld_actiecode    = mld_info.actiecode;
        params.stdm_notes       = mld_info.stdm_notes;
        params.mld_fenotes      = mld_info.fenotes;
        params.fe_key           = mld_info.melder_key;
        params.fe_ext_name      = (mld_info.naam_ext ? mld_info.naam_ext : mld_info.email_ext);

        if (!("note_key" in params))
            params.note_key = -1;

        if (pmodule === "MLD" && !(params.stdm_notes & params.myRole))
        {
            Response.Write("</div>");
            return;
        }

        var _fnTogglesHtml = function (more_params)
        {
            // Combineer de parameters van note_toggles en note_toggle_html in 1 object
            var combined_params = {};
            for (x in params)
                combined_params[x] = params[x];
            for (x in more_params)
                combined_params[x] = more_params[x];

            // Defaults
            combined_params.from = params.myRole;
            if (more_params.to === 1 && "fe_key" in params && params.fe_key > -1 && typeof combined_params.to_name === "undefined")
                combined_params.to_name = new Perslid(params.fe_key).naam();

            if (more_params.to === 2)
            {
                if (params.fobo_prskey && params.fobo_prskey > -1)
                    combined_params.to_name = new Perslid(params.fobo_prskey).naam();
                else
                    combined_params.to_name = L("lcl_mld_behandelaar");
            }

            if (params.note_key > -1)
                combined_params.has = combined_params.has & 1; // Overige bitjes kunnen bij een bestaande notitie niet meer gewijzigd worden

            if (pmodule === "OPDR" && S("mld_opdr_actiecode") != 1) {
                combined_params.has = combined_params.has & (127 - 8); // Geen opdr_actiecode
            }

            return notes.note_toggle_html(pmodule, combined_params);
        }

        /* has & val = Bitwise:
            &1  = Zichtbaarheid
            &2  = Notificeren
            &4  = Melders van kinder-meldingen notificeren
            &8  = Reactie vragen / Actie !
            &16 = E-mail - FUTURE USE
        */
        /* params.stdm_notes: notities bij meldingen als:
            &0 geen notities
            &1 FE
            &2 FOBO
            &4 UITV
        */

        params.note_flag = params.note_flag || 0;
        if (params.myRole === BITROLE["FE"] && pmodule === "MLD") { // Ik ben de aanvrager
            // FE toggles
            Response.Write(_fnTogglesHtml({ to: params.myRole, has: 0, val: 1 })); // Altijd zichtbaar voor mijzelf

            // BO toggles;
            var mld_actie_bij_BO = params.mld_actiecode & BITACTIONROLE["BO"]; // Stond actie al bij backoffice? FE mag nooit terugpakken
            if (!mld_actie_bij_BO && (params.publiek != 1 || user.isCollega(mld_info.melder_key))) {
                // actie staat bij melder of diens collega
                var mld_afgemeld = (mld_info.mld_status == 5);
                var has = 0; // welke bits zie ik
                var val = 1; // welke bits staan default aan, al dan niet zichtbaar
                if (params.stdm_notes & BITROLE["BO"]) { // behandelaar mag notities maken
                    if (!mld_afgemeld) {
                        has += 8;  // melder kan behandelaar om reactie vragen
                    }
                }
                if (!mld_afgemeld) {
                    val += 10; // melding nog niet afgemeld: notificeren en reactie vragen aanzetten.
                }
                Response.Write(_fnTogglesHtml({ to: BITROLE["BO"], has: has, val: val }));
            }

            // UITV toggles;
            if (params.stdm_notes & BITROLE["UITV"]) {
                var openVraagRequired = (params.stdm_notes & BITROLE["BO"]);
                var sql = "SELECT DISTINCT o.mld_opdr_key opdr_key,"
                        + "                o.mld_opdr_bedrijfopdr_volgnr opdr_nr,"
                        + "                u.mld_uitvoerende_key uitv_key,"
                        + "                u.naam"
                        + "  FROM mld_opdr         o,"
                        + (openVraagRequired
                            ? "       mld_opdr_note    n,"
                            : "")
                        + "       mld_v_uitvoerende u"
                        + " WHERE o.mld_melding_key = " + params.pkey /* = mld_key want pmodule === "MLD" */
                        + (openVraagRequired
                            ? "   AND n.mld_opdr_key = o.mld_opdr_key"
                            + "   AND BITAND (n.mld_opdr_note_flag, 32) = 32" // = Openstaande vraag van uitvoerder
                            : "")
                        + "   AND u.mld_uitvoerende_key = o.mld_uitvoerende_keys"
                        + " ORDER BY 1, 2";
                var oRs = Oracle.Execute(sql);
                var uitvoerders = [];
                while (!oRs.EoF) {
                    uitvoerders.push({
                        opdr_key:       oRs("opdr_key").Value,
                        opdr_volgnr:    oRs("opdr_nr").Value,
                        uitv_key:       oRs("uitv_key").Value,
                        uitv_naam:      oRs("naam").Value
                    });
                    oRs.MoveNext();
                }
                oRs.Close();

                var _hasUitv = function(key, this_i) {
                    for (obj in uitvoerders) {
                        if (this_i !== obj && uitvoerders[obj].uitv_key === key) {
                            return true;
                        }
                    }
                    return false;
                }

                if (params.mobile && uitvoerders.length) { // Mobile alleen een tooltip
                    Response.Write("<div class='note-hint-m'>" + L("lcl_note_invis_uitv").format(safe.html(uitvoerders[0].uitv_naam), I("fa-reply")) + "</div>");
                } else {
                    for (var i in uitvoerders) {
                        var u = uitvoerders[i];
                        if (_hasUitv(u.uitv_key, i)) { // Hebben we 2 opdrachten met dezelfde uitvoerder -> dan prefixen met opdracht_nr
                            u.uitv_naam = L("lcl_shared_order") + " " + u.opdr_volgnr + ": " + u.uitv_naam;
                        }
                        Response.Write(_fnTogglesHtml({ to: BITROLE["UITV"], to_name: u.uitv_naam, opdr_key: u.opdr_key, uid: u.opdr_volgnr, has: 8, val: (i == 0 ? 8 : 0) }));
                    }
                }
            }
        } else if (params.myRole === BITROLE["BO"]) { // Ik ben de behandelaar
            // FE toggles
            if (params.stdm_notes & BITROLE["FE"])
            {
                var has = 0; val = 0;
                var to_name;
                if (pmodule === "MLD")
                {
                    if (params.mld_fenotes > 1  || params.eigenMelding) {
                        has += 1;
                    }
                    if (   (params.note_key > -1 && params.note_flag & 1 && pmodule === "MLD") // Bij OPDR niet automatisch zichtbaar voor FE
                        || (params.note_key == -1 && (params.mld_fenotes == 1 || params.mld_fenotes == 3 || params.eigenMelding))) {
                        val += 1;
                    }
                    if (params.mld_fenotes > 0 && !params.eigenMelding)
                    {
                        if ((val & 1) && (params.mld_actiecode & BITACTIONROLE["FE"] || S("mld_note_default_notifyFE") >= 1)) {
                            val += 2;
                        }
                        has += 2;
                        if (params.mld_actiecode & BITACTIONROLE["BO"]) { // De actie staat bij BO
                            has += 8;
                            if (val & 1 && S("mld_note_default_notifyFE") == 1) {
                                val += 8;
                            }
                        }

                        if (params.haschild)
                        {
                            has += 4;
                            if (val & 2)
                                val += 4;
                        }
                    }
                    if (params.eigenMelding)
                        to_name = ""; // Ik ben BO en het is mijn eigen melding, laat mijn naam dan maar weg
                }
                Response.Write(_fnTogglesHtml({ to: BITROLE["FE"], to_name: to_name, has: has, val: val }));

                // Externe FE Notificatie toggles
                if (params.note_zichtbaarExt)
                    Response.Write(_fnTogglesHtml({ to: BITROLE["EXT"], to_name: params.fe_ext_name, has: 2, val: (val & (127 - 8)) }));
            }

            // BO toggles
            var selfOptions = { to: params.myRole, has: 0, val: 1 }; // Altijd zichtbaar voor mijzelf
            if (    pmodule === "MLD" && !(params.mld_actiecode & BITACTIONROLE["BO"])
                 || pmodule === "OPDR" && !(params.opdr_actiecode & BITACTIONROLE["BO"])) {
                selfOptions.has += 8;
            }
            Response.Write(_fnTogglesHtml(selfOptions));

            // UITV toggles
            if (pmodule === "OPDR")
            {
                has = 3; val = 0;
                if (params.note_key == -1 || params.note_flag & 4)
                    val += 1;
                if (!(params.opdr_actiecode & 4)) { // De actie staat niet bij UITV
                    has += 8;
                }
                Response.Write(_fnTogglesHtml({ to: BITROLE["UITV"], to_name: params.uitv_naam, has: has, val: val }));
            }
        }
        else if (params.myRole === BITROLE["UITV"] && pmodule === "OPDR") // Ik ben de uitvoerder
        {
            // FE toggles
            if (params.stdm_notes & BITROLE["FE"] && params.stdm_notes & BITROLE["UITV"]) // Als de FE of ik (de uitvoerder) niet mee doe met de notities vd melding, heeft deze toggle ook geen zin
            {
                var has = 10;
                var val = 0;
                if (params.note_flag & 1) // Bestaande notitie: Zichtbaar voor FE
                    val += 1;
                Response.Write(_fnTogglesHtml({ to: BITROLE["FE"], has: has, val: val }));
            }

            // BO toggles
            if (params.stdm_notes & BITROLE["BO"]) { // Alleen als de backoffice meedoet (volgens de stdmelding-instellingen)
                var has = 2;
                var val = 1;
                if (params.opdr_actiecode & 4)
                    has += 8;
                if (S("mld_opdr_note_default_notifyBO") & 1)
                    val += 2;
                if (S("mld_opdr_note_default_notifyBO") & 2)
                    has -= 2;
                Response.Write(_fnTogglesHtml({ to: BITROLE["BO"], has: has, val: val }));
            }

            // UITV toggles
            Response.Write(_fnTogglesHtml({ to: params.myRole, has: 0, val: 1 })); // Altijd zichtbaar voor mijzelf
        }

        if (S("mld_assume_ok_days") > 0 && params.eigenMelding && (params.mld_actiecode & BITATTENTION["FE"]) == BITATTENTION["FE"] && mld_info.mld_status == 5)
        {
          Response.Write("<div class='note-option-group anySelected' title='" + L("lcl_mld_not_agree") + "'>");
          if (params.mobile)
          {
            var resultHtml = CHB_FIELD_HTML("assume_not_ok", L("lcl_mld_not_agree"), false, {twocols: true, boxfirst: true});
            Response.Write(resultHtml);
          }
          else
            RWCHECKBOXTR("assume_not_ok", "fld_assume_not_ok", L("lcl_mld_not_agree"), false, {twocols: true, boxfirst: true});
          Response.Write("</div>");
        }

        Response.Write("</div>"); // </div>.note-options
    },

    note_toggle_html: function (pmodule, params)
    {
        params = params || {};
        var resultHtml = "";
        var self = params.myRole === params.to;
        var note_option_icons = [(params.myRole === 2 && params.eigenMelding) ? "fa-unlock" : "fa-eye", // &1   Zichtbaarheid
                                 "fa-bell-on",                                                          // &2   Notificeren
                                 "fa-bells",                                                            // &4   Kinders notificeren
                                 (self ? "fa-hand-point-up" : "fa-hand-point-right"),                   // &8   Vraag reactie / Actie
/*                                 "fa-envelope"                                                          // &16  E-mail */
        ];

        var idPostfix;
        switch (params.to) {
            case 0: idPostfix = "EXT"; break;
            case 1: idPostfix = "FE"; break;
            case 2: idPostfix = "BO"; break;
            case 4: idPostfix = "UITV"; break;
        }

        var note_option_ids = ["zichtbaar" + idPostfix,         // VIS
                               "notify" + idPostfix,            // NOTI
                               "notify" + idPostfix + "child",  // NOTI CHILD
                               "action2" + idPostfix];          // ACTION

        var note_option_tooltips = [];
        note_option_tooltips = [
            (params.to === 1 ? L("lcl_mld_zichtbaar_FE")                        // &1 Zichtbaarheid
                             : params.to === 4 ? L("lcl_mld_zichtbaar_UITV")
                                               : null),
            L("lcl_mld_notify_FE").format(params.to_name),                      // &2 Notificeren
            L("lcl_mld_notify_FEchild").format(params.to_name)                  // &4 Kinders notificeren
        ];
        switch (params.to) { // Vraag reactie / Actie
            case 0:
                note_option_tooltips[3] = L("lcl_mld_noti_ext").format(params.to_name);
                break;
            case 1:
                note_option_tooltips[3] = L("lcl_mld_toekennen_FE").format(params.to_name);
                break;
            case 2:
                note_option_tooltips[3] = (self ? L("lcl_mld_toekennen").format(L("lcl_me")) : L("lcl_mld_toekennen_BO"));
                break;
            case 4:
                note_option_tooltips[3] = (pmodule === "OPDR" ? L("lcl_mld_toekennen_UITV") : L("lcl_note_reply_to")).format(params.to_name);
                break;
        }

        var form_attr = (params.formid ? ' form="' + params.formid + '"' : '');
        for (i in note_option_icons)
        {
            var bit = 1 << i;
            if (params.has & bit || // We hebben (has) deze optie
                bit === 1 ||        // Zichtbaarheid altijd, al dan niet hidden
                bit === 2 && params.to === 2 && (S("mld_opdr_note_default_notifyBO") & 2) ||  // Notificeren altijd indien S("mld_opdr_note_default_notifyBO") & 2, al dan niet hidden
                bit === 8 && params.val & bit)                                                // Actie altijd indien gezet (val & 8), al dan niet hidden
            {
                if (params.mobile)
                {
                    var actiecode;
                    if (pmodule == "MLD")
                    {
                      var sqlt = "SELECT mld_melding_actiecode"
                               + "  FROM mld_melding"
                               + " WHERE mld_melding_key = " + params.pkey;
                      var oRs = Oracle.Execute(sqlt);
                      actiecode = oRs("mld_melding_actiecode").Value;
                      oRs.Close();
                    }
                    if (params.has & bit)
                        resultHtml += CHB_FIELD_HTML(note_option_ids[i], safe.html(note_option_tooltips[i]), (params.val & bit ? 1 : 0),
                                                    { html: "data-toggle-type=" + bit
                                                          // De volgende 3 attributen nodig voor de onclick functie noteOptionToggled
                                                          // en zijn op deze manier voor de functie toegankelijk.
                                                          + " module=" + pmodule
                                                          + " mld_note_hidden_action2FE=" + S("mld_note_hidden_action2FE")
                                                          + " actiecode=" + (actiecode != null? actiecode : 0),
                                                      pclass: "note-option-toggle-m",
                                                      onclick: "noteOptionToggled.call(this, " + bit + ")" });
                    else
                        resultHtml += '<input type="hidden" name="' + note_option_ids[i] + '" id="' + note_option_ids[i] + '" value="' + (params.val & bit ? "on" : "off") + '"' + form_attr + '>';
                }
                else
                {
                    resultHtml += '<label class="fa-stack'
                                + (params.val & bit ? ' on' : ' off')
                                + (!(params.has & bit) ? " hidden" : "") + '"'
                                + ' data-toggle-type="' + bit + '"'
                                + ' title="' + safe.htmlattr(note_option_tooltips[i]) + '"'
                                + ' for="' + note_option_ids[i] + ("uid" in params ? params.uid : '') + '"'
                                + form_attr
                                + '>'
                                +   I(note_option_icons[i] + " fa-stack-1x fa-xl", { fastyle: "far" })
                                + I("fa-" + (note_option_icons[i] == "fa-unlock" ? "lock" : "slash") + " fa-stack-1x fa-xl", { fastyle: "far" }) /* De fa-slash krijgt in de default.css een fa-flip-horizontal hardcoded */
                                + '</label>'
                                + '<input type="checkbox" id="' + note_option_ids[i] + ("uid" in params ? params.uid : '') + '" name="' + note_option_ids[i] + '"' + (params.val & bit ? " checked" : "") + form_attr + '>'
                                + (params.has & bit ? '<input type="hidden" name="has_' + note_option_ids[i] + '" value="1"' + form_attr + '>' : '');
                }
            }
        }

        // Wrap de resultaten (per persoon)
        if (params.mobile)
        {
            if (resultHtml && (params.has & 127) > 0) // Anders geen -zichtbare- opties, dan ook geen controlgroup-wrapper
            {
                resultHtml = '<div class="ui-field-contain">'
                           + '    <fieldset data-role="controlgroup" class="note-option-group-m" data-toggle-subject-role="' + params.to + '"' + form_attr + '>'
                           +          resultHtml
                           + '    </fieldset>'
                           + '</div>';
            }
        }
        else
        {
            resultHtml = '<div class="note-option-group'
                       + (params.val > 0 || params.to === 2 ? " anySelected" : "")
                       + (params.has === 0 ? " hidden" : "") + '"'
                       + ' title="' + safe.htmlattr(params.to_name) + '"'
                       + ("opdr_key" in params ? ' data-opdr-key="' + params.opdr_key + '"' : '')
                       + ' data-toggle-subject-role="' + params.to + '">'
                       +      resultHtml
                       + '    <span class="name no-select">' + safe.html(params.to_name) + '</span>'
                       + '</div>';
        }
        return resultHtml;
    },

    note_actions_html: function (actions)
    {
        if (!actions.length)
            return "";

        var _single_action = function(action)
        {
            return "<span class='note-button-" + safe.htmlattr(action.name) + " default-clickable-icon'"
                +       " onclick='" + safe.htmlattr(action.action) + "'"
                +       " title='" + safe.htmlattr(action.label) + "'>"
                +     I(action.icon)
                +  "</span>";
        }

        var not_in_submenu_list = ["edit"]; // Setting?
        var result = "";

        for (x in actions)
        {
            if (inArray(actions[x].name, not_in_submenu_list))
            {
                result += _single_action(actions[x]);
                actions.splice(x, 1);
            }
        }

        if (actions.length === 1)
        {
            result += _single_action(actions[0]);
        }
        else if (actions.length > 1)
        {
            var ddMenu = "<div class='note-action-menu'>";
            for (x in actions)
            {
                var action = actions[x];
                ddMenu += "<div class='note-button-" + safe.htmlattr(action.name) + "'"
                        +      " onclick='" + safe.htmlattr(action.action) + "'>"
                        +       I(action.icon)
                        +       safe.html(action.label)
                        + "</div>";
            }
            ddMenu += "</div>";

            result += "<span class='note-button-more default-clickable-icon' onclick='$(this).toggleClass(\"open\")'>"
                    +       I("fa-chevron-down")
                    +       ddMenu
                    +  "</span>";
        }
        return result;
    },

    note_VIPs: function _note_VIPs (pkey, pnote_key, pmodule, params)
    {
        var key_arr = [];
        var _pushUnique = function (val) {
            if (typeof val != "undefined" && val !== null && !inArray(val, key_arr))
                key_arr.push(val);
        }
        var mod_table = "";
        switch (pmodule) {
            case "MLD":
                var mld_info = params.mld_info || mld.mld_melding_info(pkey);
                _pushUnique(mld_info.melder_key);
                _pushUnique(mld_info.behandel2_key);
                _pushUnique(mld_info.behandel_key);
                break;
            case "OPDR":
                var mld_opdr = (params.this_opdr ? params.this_opdr.mld_opdr : mld.mld_opdr_info(pkey));
                _pushUnique(mld_opdr.uitvoerende_key);
                _pushUnique(mld_opdr.contactpers_key);
                _pushUnique(mld_opdr.melding_user_key);
                break;
        }
        // Alle notitie & tracking deelnemers;
        var sql = "SELECT prs_perslid_key"
                + "  FROM (SELECT prs_perslid_key"
                + "          FROM " + params.note_tabel
                + "         WHERE " + params.mod_tabel + "_key = " + pkey
                + "        UNION"
                + "        SELECT tr.prs_perslid_key"
                + "          FROM fac_tracking tr, fac_srtnotificatie str"
                + "         WHERE     tr.fac_srtnotificatie_key = str.fac_srtnotificatie_key"
                + "               AND tr.fac_tracking_refkey = " + pkey
                + "               AND str.fac_srtnotificatie_xmlnode = " + safe.quoted_sql(params.xmlnode) + ")"
                + " WHERE prs_perslid_key IS NOT NULL";
        var oRs = Oracle.Execute(sql);
        while (!oRs.EOF)
        {
            _pushUnique(oRs("prs_perslid_key").Value);
            oRs.moveNext();
        }
        oRs.Close();
        return key_arr;
    },

    note_common_js: function _note_common_js(note_key) {
        // Common (desktop & mobile) clientside javascript
%>      var draft_notes_enabled = <%=note_key == -1 && S("note_draft_history_days") > 0 ? "true" : "false"%>;

        var notes_draft = localStorage.getObject("notes_draft") || {};
        var lastCleanup = notes_draft?.lastCleanup || 0;
        var today = new Date(new Date().toDateString()).getTime();
        if (today != lastCleanup) {
            // Verwijder concept notities ouder dan S(note_draft_history_days) dagen
            var threshold = new Date().getTime() - <%=S("note_draft_history_days")%> * 24 * 60 * 60 * 1000;
            for (var module in notes_draft) {
                for (var key in notes_draft[module]) {
                    if (notes_draft[module][key].timestamp < threshold) {
                        delete notes_draft[module][key];
                    }
                }
            }
            notes_draft.lastCleanup = new Date(new Date().toDateString()).getTime();
            localStorage.setObject("notes_draft", notes_draft);
        }

<%      // Onderstaande functie pas aanroepen nadat window.module gedefinieerd is
%>      function load_note_draft() {
<%          if (note_key == -1) { %>
            if (draft_notes_enabled && window.module_key > 0) { // Laad een opgeslagen notitie (draft) in
                var notes_draft = localStorage.getObject("notes_draft");
                $("#note").val(notes_draft?.[window.module]?.[window.module_key]?.note).trigger("keyup");
            }
<%          } %>
        }

        function draft_note(module, module_key, note) {
            if (!draft_notes_enabled || !(module_key > 0)) {
                return;
            }
            var notes_draft = localStorage.getObject("notes_draft") || {};
            if (!note) {
                delete notes_draft?.[module]?.[module_key];
            } else {
                notes_draft[module] = notes_draft[module] || {};
                notes_draft[module][module_key] = {
                    note: note,
                    timestamp: new Date().getTime()
                };
            }
            localStorage.setObject("notes_draft", notes_draft);
        }
<%  },

    note_field: function _note_field(pkey, pnote_key, pmodule, params)
    {
        Response.write("</table>"); /* Tables zijn zo 2020 */
%>      <script>
<%          notes.note_common_js(pnote_key); %>
        </script>
<%      var authparams = user.checkAutorisation("WEB_PHSRCH", true);
        var canMention = authparams && authparams.PRSreadlevel < 9 && !(pnote_key > -1) &&
                         (Session("locked_user_allowed") || []).length === 0; // LOCKED_USER's maar gewoon niet
        // Suggest om een persoon te vinden voor @mentions
        if (canMention) {
            Response.write("<div style='display: none;'>");
            FCLTpersoonselector("mention_key", "sgMention", {
                sgType: "mention",
                preferredKeys: notes.note_VIPs(pkey, pnote_key, pmodule, params),
                perslidKey: -1,
                filtercode: "PHB",
                idadd: 9999,
                onChange: "mentionCallback",
                autlevel: authparams.PRSreadlevel
            });
            Response.write("</div>");
        }
        var timestamp_notes = new Date();
        var fac_note_group_key;
        var parent_key = -1;
        // == Verder met de nieuwe/bestaande notitie

        // In tegenstelling tot meldingen heeft mld_opdr_note geen flag veld.
        // Opdracht, factuur, contracten en objecten notes zijn dus altijd zichtbaar

        var note_oms = "";
        if (pnote_key > -1)
        { // Bestaande net toegevoegde note voor re-edit: gegevens uit record gebruiken.
            sql = "SELECT " + params.note_tabel + "_omschrijving"
                + ( pmodule == "MLD" || pmodule == "OPDR" ? ", fac_note_group_key" : "" )
                + ( pmodule == "MLD" || pmodule == "OPDR" ? ", " + params.note_tabel + "_parent_key parent_key" : "" )
                + "  FROM " + params.note_tabel
                + " WHERE " + params.note_tabel + "_key = " + pnote_key;
            var oRs = Oracle.Execute(sql);
            note_oms = oRs(params.note_tabel + "_omschrijving").value;
            fac_note_group_key = ( pmodule == "MLD" || pmodule == "OPDR" ? oRs("fac_note_group_key").value : null );
            if (pmodule == "MLD" || pmodule == "OPDR")
                parent_key = oRs("parent_key").value || -1;
            oRs.Close();
        }

        // Voeg eventueel weer toe wat er voor de reload als gevolg van upload bijlage stond.
        note_oms = (params.tmp_note != "" ? params.tmp_note : note_oms);
        if ((pmodule == "MLD" || pmodule == "OPDR") && params.tracking) // Voor nu alleen voor MLD
        {
            var sql = "SELECT sn.fac_srtnotificatie_code,"
                    + "       sn.fac_srtnotificatie_key,"
                    + "       MIN(q.fac_notificatie_receiver_email) fac_notificatie_receiver_email,"
                    + "       MIN(q.fac_notificatie_systeemadres) fac_notificatie_systeemadres,"
                    + "       MIN(q.prs_bedrijfadres_key) prs_bedrijfadres_key,"
                    + "       MIN(b.prs_bedrijf_naam) prs_bedrijf_naam,"
                    + "       COUNT(*) aantal,"
                    + "       MIN(q.fac_notificatie_datum) fac_notificatie_datum,"
                    + "       MIN(q.fac_notificatie_key) fac_notificatie_key,"
                    + "       MIN(q.fac_notificatie_failcount) fac_notificatie_failcount,"
                    + "       MIN(q.fac_notificatie_notbefore) fac_notificatie_notbefore"
                    + "  FROM fac_notificatie q, "
                    + "       fac_srtnotificatie sn, "
                    + "       prs_bedrijfadres ba, "
                    + "       prs_bedrijf b"
                    + " WHERE q.fac_srtnotificatie_key = sn.fac_srtnotificatie_key(+)"
                    + "   AND (q.fac_notificatie_systeemadres IS NOT NULL OR "
                    + "        q.prs_bedrijfadres_key IS NOT NULL OR "
                    + "        BITAND(fac_notificatie_status, 2) = 2)" // email
                    + "   AND  ba.prs_bedrijfadres_key(+)= q.prs_bedrijfadres_key"
                    + "   AND  b.prs_bedrijf_key(+)= ba.prs_bedrijf_key"
                    + "   AND sn.fac_srtnotificatie_xmlnode = '{0}'".format({'MLD':'melding', 'OPDR':'opdracht'}[pmodule])
                    + "   AND q.fac_notificatie_refkey = " + pkey
                    + " GROUP BY sn.fac_srtnotificatie_code,"
                    + "          sn.fac_srtnotificatie_key"
                    + " ORDER BY fac_notificatie_datum, "
                    + "          fac_notificatie_key"
            var oRs = Oracle.Execute(sql);
            while (!oRs.EOF)
            {
                var code = oRs("fac_srtnotificatie_code").Value;
                var aantal = oRs("aantal").Value;
                var email = oRs("fac_notificatie_receiver_email").Value;
                var systeemadres = oRs("fac_notificatie_systeemadres").Value;
                var prs_bedrijfadres_key = oRs("prs_bedrijfadres_key").Value;
                var failcount = oRs("fac_notificatie_failcount").Value;
                var notbefore = new Date(oRs("fac_notificatie_notbefore").Value);
                // Het volgende lijkt leuk maar MLDNOB heeft bijvoorbeeld geen lcl in status.inc omdat hij
                // wel wordt gebruikt voor notificatie maar nooit voor tracking
                // var srtnotitxt = "<span title='{0}'>{1}</span>".format(code, status.getsrtnotificatietext(code));
                var srtnotitxt = code;
                var title = toDateTimeString(new Date(oRs("fac_notificatie_datum").Value));
                if (systeemadres)
                {
                    var safebody  = L("lcl_puo_willsendsystem").format(srtnotitxt) + (aantal > 1 ? " ({0}x)".format(aantal): "");
                }
                else if (prs_bedrijfadres_key > 0)
                {
                    var safebody  = L("lcl_puo_willsendkanaal").format(srtnotitxt) + (aantal > 1 ? " ({0}x)".format(aantal): "");
                    title += " ({0})".format(safe.htmlattr(oRs("prs_bedrijf_naam").Value));
                }
                else
                    var safebody  = L("lcl_puo_willsendnoti").format(srtnotitxt, safe.html(email) + (aantal>1?L("lcl_puo_willsendnotimore").format(aantal-1):""));
                if (user.has("WEB_FACTAB")) // edit button
                {
                    if (aantal == 1)
                    {
                        var onclick = "notificatie_detail(" + oRs("fac_notificatie_key").Value + ")";
                    }
                    else
                    {
                        var onclick = "notificatie_detail2(" + pkey + ", " + oRs("fac_srtnotificatie_key").Value + ")";
                    }
                    var editbutton = "<span title='Edit (FACTAB only)' style='cursor:pointer;' "
                                   + "             onclick='{0}'>".format(safe.htmlattr(onclick))
                                   + "&nbsp;" + I("fa-fclt-edit") + "</span>";
                    safebody = safebody + editbutton;
                }
                Response.Write("<div class='noti-info' title='{0}'><i>".format(title) + safebody + "</i></div>");
                if (failcount)
                    Response.Write("<div><i>" + L("lcl_puo_failsendsystem").format(failcount, toDateTimeString(notbefore)) + "</i></div>");
                oRs.MoveNext();
            }
            oRs.Close();
        }

        // Response.Write("<div class='note-notification'>" + L("lcl_puo_willsendnoti").format("test", safe.html("tst@facilitor.nl") + L("lcl_puo_willsendnotimore").format(3e54)) + "</div>");

        if (params.showNote && (!("writeNote" in params) || params.writeNote))
        {
            if (pnote_key < 0 && params.afgehandeld)
            {
              if (S("mld_assume_ok_days") > 0 && pmodule === "MLD" && (mld_info.actiecode & 256) == 256 && mld_info.melder_key == user_key)
                // Melding afgemeld en attentie bij de melder.
                ROFIELDTR("mldshowactie fclt-info", "", L("lcl_mld_actiecodeATTFE"), {ishtmlsafe: true, suppressEmpty: true});
              else
                Response.Write("<div class='mldshowactie fclt-warning'> " + L("lcl_" + pmodule.toLowerCase() + "_edit_note_completed") + "</div>");
            }
            var form_action = pmodule.toLowerCase() + "_edit_note_save.asp"
                            + "?" + pmodule.toLowerCase() + "_key=" + pkey
                            + (pmodule == "ALG" ? "&alg_typ=" + params.alg_typ : "")
                            + "&note_key=" + pnote_key;
            var form_attr = params.formid ? ' form="' + params.formid + '"' : '';
%>
            <form name="u2" method="post" action="<%=form_action%>"<%=form_attr%>>
                <section class="edit-note">
                    <input type="hidden" name="notestamp" id="notestamp" value="<%=timestamp_notes.getTime()%>"<%=form_attr%>>
                    <input type="hidden" name="module" id="module" value="<%=pmodule.toLowerCase()%>"<%=form_attr%>>
                    <input type="hidden" name="<%=pmodule.toLowerCase()%>_key" id="<%=pmodule.toLowerCase()%>_key" value="<%=pkey%>"<%=form_attr%>>
                    <input type="hidden" name="note_key" id="note_key" value="<%=pnote_key%>"<%=form_attr%>>
                    <input type="hidden" name="parent_key" id="parent_key" value="<%=parent_key%>"<%=form_attr%>>
                    <div class="warning-wrapper">
                        <div id="lock-warning" style="display: none"></div>
                    </div>
                    <%=BB_BUTTONS_HTML("note", true, { "module": (pmodule === "OPDR" ? "ORD" : pmodule) + "N", "refkey": pnote_key, "formid": (params.formid || undefined) })%>
                    <div class="note-textarea<%=(pnote_key > -1 ? " note-edit" : "")%>">
<%              if (pnote_key > -1 && parent_key > -1)
                {
                Response.Write(notes.inlineReplyNote(parent_key, (pmodule == "MLD" ? "M" : "O"), { "editmode": 1 }));
                }
%>                      <textarea id='note' name='note' class='bb_enabled bb_upload_enabled <%=(S("note_sort_ascending") == 0 ? " top" : "")%>' rows='4' maxlength='4000'
                                  placeholder='<%=L("lcl_" + pmodule.toLowerCase() + "_note_new")%>'<%=form_attr%> aria-controls='<%=(pmodule === "OPDR" ? "ORD" : pmodule) + "N"%>_bijlagen'
                        ><%=safe.textarea(note_oms)%></textarea>
                    </div>
                    <%=BB_ATTACHMENTS_HTML((pmodule === "OPDR" ? "ORD" : pmodule) + "N", pnote_key, "note", "edit")%>
                    <div class="note-options-groups-wrapper">
<%
            // Voor MLD geldt het volgende:
            // Er zijn notes die voor iedereen (relevant) zichtbaar zijn en notes die alleen voor FOBO
            // zichtbaar zijn. Dat hangt af van mld_melding_note_flag. Die zichtbaarheid is hierboven geregeld.
            //
            // Dan kunnen er notes worden toegevoegd. Dat kan altijd en door iedereen (relevant)
            // alleen *niet* door de FE indien params.mld_fenotes==0
            //   dus wel door FOBO zelfs indien params.mld_fenotes==0
            //   dus wel door FE indien params.mld_fenotes>0
            // Let op: fenotes is geen bitwise codering (meer), gewoon 0-3
            if (pmodule == "MLD" || pmodule == "OPDR")
            {
                params.pkey = pkey;
                params.note_key = pnote_key;
                notes.note_toggles(pmodule, params);
                var pmod_obj = { "MLD": "melding", "OPDR": "opdracht" };
                var selector_sql = "SELECT fac_note_group_key, fac_note_group_naam, fac_note_group_omschrijving"
                                  + "  FROM fac_note_group"
                                  + " WHERE fac_note_group_xmlnode = " + safe.quoted_sql(pmod_obj[pmodule])
                                  + "   AND fac_note_group_vervaldatum IS NULL"
                                  + " ORDER BY fac_note_group_xmlnode, fac_note_group_volgnr";
                var selector_oRs = Oracle.Execute(selector_sql);
                if (!selector_oRs.Eof)
                {
%>
                        <div class="note-groups">
                            <input type="hidden" name="fac_note_group_key" id="fac_note_group_key" value="-1"<%=form_attr%>>
                            <div>
                                <label for="fac_note_group_naam_-1">
                                    <input type="radio" name="fac_note_group_naam" value="-1" id="fac_note_group_naam_-1" checked="checked"<%=form_attr%>>
                                    <%=L('lcl_note_group_default')%>
                                </label>
                            </div>
<%
                    while(!selector_oRs.Eof)
                    {
%>
                            <div>
                                <label for="fac_note_group_naam_<%=selector_oRs("fac_note_group_key").Value%>" title="<%=safe.htmlattr(selector_oRs("fac_note_group_omschrijving").Value)%>">
                                    <input type="radio" name="fac_note_group_naam" value="<%=selector_oRs("fac_note_group_key").Value%>" id="fac_note_group_naam_<%=selector_oRs("fac_note_group_key").Value%>"<%=form_attr%>>
                                    <%=safe.html(selector_oRs("fac_note_group_naam").Value)%>
                                </label>
                            </div>
<%
                        selector_oRs.MoveNext();
                    }
%>
                        <script>
                            function fac_note_group_click() {
                                $("#fac_note_group_key").val($(this).val());
                            }
                            $("input[name=fac_note_group_naam]").on("click", fac_note_group_click);
                            $(function()
                            {
                                $("div#note_div").addClass("has_note_group");
                                if ($("div.has_note_group textarea").height() < $("div.note-fac-group").height()) {
                                    $("div.has_note_group textarea").css("min-height", $("div.note-fac-group").height() + "px")
                                }
<%
                    if (fac_note_group_key)
                    {
%>
                            $("#fac_note_group_naam_<%=fac_note_group_key%>").click();
<%
                    }
%>
                            });
                        </script>
                        </div>
<%
                }
                selector_oRs.Close();
            }
%>
                        <div class="note-submit-wrapper">
<%                  if (pnote_key > -1) { %>
                            <div class="note-icon close" title="<%=L("lcl_cancel")%>" onClick="cancel_note_edit()" tabindex="0"><%=I("fa-times fa-xl", { fastyle: "fal", fa_fw: false })%></div>
<%                  } %>
                            <div class="note-icon submit" title="<%=L("lcl_submit")%>" onClick="<%=(params.note_submit_func ? safe.htmlattr(params.note_submit_func) : "note_submit")%>(<%=params.formid ? "'" + params.formid + "'" : null%>)" tabindex="0">
                                <%=I("fa-paper-plane fa-xl", { fastyle: "fal", fa_fw: false })%>
                            </div>
                        </div>
<%              IFACE.FORM_END(params); %>
                    </div>
                </section>
            </form>
<%
        }
    },

    inlineReplyNote: function (note_key, mod, params)
    {
        params = params || {};
        var mod = mod || "O";
        var tables = {  "M": "mld_melding_note",
                        "O": "mld_opdr_note" };
        var note_table = tables[mod];
        var result = "";
        var class_postfix = (params.mobile ? "-m" : "");
        if (note_key > -1)
        {
            var sql = "SELECT note." + note_table + "_omschrijving"
                    + "     , prs.prs_perslid_key"
                    + "     , prs.prs_perslid_naam_friendly"
                    + "  FROM prs_v_perslid_fullnames_all prs"
                    + "     , " + note_table + " note"
                    + " WHERE note.prs_perslid_key = prs.prs_perslid_key"
                    + "   AND note." + note_table + "_key = " + note_key;
            var oRs = Oracle.Execute(sql);
            var parent_note_oms = oRs(note_table + "_omschrijving").Value;
            var parent_note_fullname_html = params.mobile ? safe.html(oRs("prs_perslid_naam_friendly").Value) : notes.fnPerslidNaamFull(oRs, true);
            oRs.Close();

            var safe_parent_note_oms = safe.html(shared.stripbbcodes(parent_note_oms));
            var author_html     = "<span class='note-author"+class_postfix+"'>{0}</span>".format(parent_note_fullname_html);
            var close_icon_html = params.editmode ? "<span class='default-clickable-icon' onClick='removeReply()'>" + I("fa-times", { fastyle: "fal" }) + "</span>" : "";
            var note_uid_prefix = (mod == "M" ? "1" : (mod == "O" ? "2" : "")); // Melding-notities worden met een '1' geprefixed, Opdr met een '2', overige modules (nog) niet
            var parent_note = "<span class='reply-body"+class_postfix+"' data-target='note-{0}{1}'>{2}</span>".format(note_uid_prefix, note_key, safe_parent_note_oms);
            result = "<div class='reply-wrapper"+class_postfix+"'><div class='reply-container"+class_postfix+"'><div class='reply-header"+class_postfix+"'>{0}{1}</div>{2}</div></div>".format(author_html, close_icon_html, parent_note);
        }
        return result;
    },

    fnPerslidNaamFull: function (oRs, inReply)
    {
        if (!oRs("prs_perslid_key").Value) return "";
        if (outputmode != 0)
            return safe.html(oRs("prs_perslid_naam_friendly").Value);

        if (oRs("prs_perslid_key").Value == user_key) {
            var html = ""
            if (inReply)
            {
                var html = "<span class='details' onclick='persoonDetails(event,"+ oRs("prs_perslid_key").Value +")'>"
                        + L("lcl_You")
                        + "</span>";
            }
            else { /* Mijn eigen naam hoeft niet meer als mijn eigen tekst rechts staat. */ }
        } else {
            var html = "<span class='details' onclick='persoonDetails(event,"+ oRs("prs_perslid_key").Value +")'>"
                      + safe.html(oRs("prs_perslid_naam_friendly").Value)
                      + "</span>";
        }
        return html;
    },

    note_save: function (pkey, params)
    {
        var params = params || {};
        if (params.note != "")
        {
            var note_key = params.note_key;
            var fields =  [ { dbs: params.table + "_key",               typ: "key",     val: pkey },
                            { dbs: "prs_perslid_key",                   typ: "key",     val: user_key },
                            { dbs: params.table + "_note_omschrijving", typ: "varchar", val: params.note, len: 4000 }
                          ];
            if (params.module == "ALG")
            {
                fields.push( { dbs: params.table + "_typ", typ: "varchar", val: params.typ });
            }

            if (params.module === "MLD") // Opdracht- of Melding notitie
            {
                fields.push({ dbs: "fac_note_group_key", typ: "key", val: (params.fac_note_group_key ? params.fac_note_group_key : null) });
                if (params.note_parent_key > 0) {
                    fields.push({ dbs: params.table + "_note_parent_key", typ: "key", val: params.note_parent_key });
                    if (params.flag & 5) { // Serverside checken of we niet zichtbaarder zijn geworden dan dat de note waarop we replyen is
                        var sql = "SELECT " + params.table + "_note_flag"
                                + "  FROM " + params.table + "_note"
                                + " WHERE " + params.table + "_note_key = " + params.note_parent_key;
                        var oRs = Oracle.Execute(sql);
                        var parent_flag = oRs(params.table + "_note_flag").Value || 0;
                        oRs.Close();
                        params.flag = params.flag - (params.flag & 7) + (params.flag & parent_flag & 39);
                    }
                }
                else if (note_key > -1) // Maak hem dan leeg
                    fields.push({ dbs: params.table + "_note_parent_key", typ: "key", val: null });
                fields.push({ dbs: params.table + "_note_flag", typ: "number", val: params.flag });
            }

            if (note_key > -1)
            {
                var sql = buildUpdate(params.table + "_note", fields)
                        + " " + params.table + "_note_key = " + note_key
                        + " AND prs_perslid_key = " + user_key; // Voorkom dat er een notitie van een ander aangepast wordt.
                Oracle.Execute(sql);
            }
            else
            {
                fields.push({ dbs: params.table + "_note_key", typ: "key", seq: params.module.toLowerCase() + "_s_" + params.table + "_note_key" });

                var noteIns = buildInsert(params.table + "_note", fields, { noValidateToken: params.noValidateToken });
                note_key = noteIns.sequences[params.table + "_note_key"];
                Oracle.Execute(noteIns.sql);
                var note_module = (params.table == "mld_opdr" ? "ORD" : params.module) + "N";
                if (!params.noValidateToken) { // Uit API, we kunnen hier getFParam niet meer gebruiken (en is deze functie uberhaupt nvt)
                    move_new_bb_files(note_module, note_key, getFParamStringArray("bb_files", []));
                }

                // Alleen bij nieuwe notities, notificaties van 'mentions' versturen
                var mentionRegexpStr = "\\[mention\\](\\d+)\\|(.+?)\\[\\/mention\\]";
                var mentions = ( params.module == "ALG"
                               ? []  // Doen we hier niet aan.
                               : params.note.match(new RegExp(mentionRegexpStr, "gi")) || []
                               );

                for (var i = 0; i < mentions.length; i++)
                {
                    var groups = mentions[i].match(new RegExp(mentionRegexpStr, "i")) // Zonder de 'g'lobal-flag
                    if (groups)
                    {   // groups[1] = prs_key
                        // groups[2] = prs_name
                        var prs_key = parseInt(groups[1], 10);

                        // Tamper check, omdat je de key textueel kan aanpassen
                        var prs_func = user.func_enabled2("PRS", { prs_key: prs_key });
                        if (prs_func && prs_func.canRead("WEB_PHSRCH"))
                        {
                            var srt_noti = (params.table == "mld_opdr" ? "ORD" : params.module) + "MEN";
                            // putnotificationsrtprio doet geen vertaling van andere vars dan ##KEY## (notify_tracking zou dat wel doen)
                            // dus doen we het hier zelf maar.
                            var omssql = "SELECT fac_srtnotificatie_oms"
                                       + "  FROM fac_srtnotificatie"
                                       + " WHERE fac_srtnotificatie_code = " + safe.quoted_sql(srt_noti);
                            var oRs = Oracle.Execute(omssql);
                            // '{0} heeft je genoemd bij [entiteit]'
                            var oms = L(oRs("fac_srtnotificatie_oms").Value, { autolcl: true }).format(user.naam());
                            oRs.Close();
                            var sprintf = "";
                            var xref_key = "NULL";
                            switch (srt_noti) { // Bepaal de te gebruiken vertaal-functie
                                case "CNTMEN": sprintf = "cnt.sprintf";     break;
                                case "FINMEN": sprintf = "fin.sprintf";     break;
                                case "INSMEN": sprintf = "ins.sprintf";     break;
                                case "MLDMEN": sprintf = "mld.mldsprintf";  xref_key = note_key; break;
                                case "ORDMEN": sprintf = "mld.opdrsprintf"; xref_key = note_key; break;
                            }

                            Oracle.Execute("BEGIN fac.putnotificationsrtprio("
                                         + user_key
                                         + ", " + prs_key
                                         + ", " + safe.quoted_sql(srt_noti)
                                         + ", " + pkey
                                         + ", " + sprintf + "(" + safe.quoted_sql(oms) + ", " + pkey + ")"
                                         + ", NULL, NULL, NULL, " + xref_key + ", 2, NULL); END;");
                        }
                    }
                }
            }
        }
        return note_key;
    },

    show_note2: function (pmodule, pkey, pkenmerk_key, pthis_mod, pafgehandeld, pupload_url, pparams)
    {
        var tracking      = getQParamInt("tracking", 1) == 1; // tracking erbij tonen? Onderdrukken met 0
        var tmp_note      = getQParam("tmp_note", "");
        var parent_reload = getQParamInt("parent_reload", 0);
        var note_key      = getQParamInt("note_key", -1);
        var verynew       = getQParamInt("verynew", 0) == 1;
        var alg_typ       = (pparams && pparams.alg_typ ? pparams.alg_typ : "");

        // prefix 'fin' or 'cnt' or 'ins' or 'alg'
        var mod_prefix    = pmodule.toLowerCase();

        var note_params = { tmp_note: tmp_note
                          , showNote: pthis_mod.canReadNotes
                          , afgehandeld: pafgehandeld
                          }
        switch (pmodule)
        {
            case "FIN":  note_params.xmlnode = "factuur";
                         note_params.mod_tabel = "fin_factuur";
                         break;
            case "CNT":  note_params.xmlnode = "contract";
                         note_params.mod_tabel = "cnt_contract";
                         break;
            case "INS":  note_params.xmlnode = "deel";
                         note_params.mod_tabel = "ins_deel";
                         break;
            case "MLD":  note_params.xmlnode = "melding";
                         note_params.mod_tabel = "mld_melding";
                         break;
            case "OPDR": note_params.xmlnode = "opdracht";
                         note_params.mod_tabel = "mld_opdr";
                         break;
            case "ALG":  switch (alg_typ)
                         {
                            case "R": note_params.xmlnode = "ruimte" ;    break;
                            case "V": note_params.xmlnode = "verdieping"; break;
                            case "G": note_params.xmlnode = "gebouw";     break;
                            case "L": note_params.xmlnode = "locatie";    break;
                         };
                         note_params.mod_tabel = "alg_onroerendgoed";
                         note_params.alg_typ = alg_typ;
                         break;
        }
        note_params.note_tabel = note_params.mod_tabel + "_note";
%>
        <html>
            <head>
<%            FCLTHeader.Generate({outputmode: outputmode}); %>
              <script>
                  // De functie note_submit is aanwezig in LocalScripts/notes.js.
                  // Elke module heeft een eigen callback functie note_submit_callback.
                  function note_submit_callback(json)
                  {
                      if (window.noteediting && FcltMgr.stopEdit(window))
                      {
                          window.noteediting = false;
                      }
                      var alg_typ = "<%=alg_typ%>";
                      window.location.href = "<%=mod_prefix%>" + "_show_note2.asp?"
                                           + "<%=mod_prefix%>" + "_key=<%=pkey%>"
                                           + (alg_typ != "" ? "&alg_typ=" + alg_typ : "")
                                           + "&tracking=<%=tracking?1:0%>"
<%                    if (parent_reload == 1) { %>
                          window.parent.FcltMgr.reload();
<%                    } %>
                  }

                  $(function ()
                  {
                      init_note(<%=note_key%>);
                  });
              </script>
            </head>

            <body class="notesmode"><%
            SUBFRAME_START();
            var buttons =  [];
            buttons.push({ icon: "fa-fclt-refresh", title: L("lcl_refresh"), action: "FcltMgr.stopEdit(window);FcltMgr.reload()"});
            buttons.push({ icon: "fa-print", title: L("lcl_print"), action: "doPrint(" + pkey + ", '" + mod_prefix + "')" });
            if (pkenmerk_key != -1)
                buttons.push({ icon: "fa-folder-open", title: L("lcl_appendixes"), action: "Upload('" + pupload_url + "')", showAlways: true });

            IFRAMER_HEADER(L("lcl_" + mod_prefix + "_behandeling"), buttons, { inhamburger: true });
            BLOCK_START(mod_prefix + "Historie",  (tracking? L("lcl_" + mod_prefix + "_behandeling") : L("lcl_" + mod_prefix + "_frame_notes")),
                        { detailToggle: true, wide: true, nopadding: true, icon: "fa-clipboard-list-check" });

            var any_att_sql = "SELECT COUNT(*) attachment_count"
                            + "  FROM fac_bijlagen fb"
                            + "     , " + note_params.note_tabel + " n"
                            + " WHERE fb.fac_bijlagen_refkey = n." + note_params.note_tabel + "_key"
                            + "   AND fb.fac_bijlagen_module = " + safe.quoted_sql(pmodule + "N")
                            + "   AND n." + note_params.mod_tabel + "_key = " + pkey
                            + (pmodule == "ALG" ? " AND n." + note_params.mod_tabel + "_typ = " + safe.quoted_sql(alg_typ) : "");
            var any_att_oRs = Oracle.Execute(any_att_sql);
            var has_any_attachments = any_att_oRs("attachment_count").Value > 0;
            any_att_oRs.Close();

            if (S("note_sort_ascending") == 0)
            {
                notes.note_field(pkey, note_key, pmodule, note_params);
            }

            var sql_n = "SELECT n." + note_params.note_tabel + "_aanmaak  note_aanmaak"
                      + "     , n." + note_params.note_tabel + "_key  note_key"
                      + "     , n." + note_params.note_tabel + "_omschrijving  note_omschr"
                      + "     , pf.prs_perslid_key"
                      + "     , pf.prs_perslid_naam_friendly"
                      + "     , NULL fac_srtnotificatie_code"
                      + "  FROM " + note_params.note_tabel + " n"
                      + "     , prs_v_perslid_fullnames_all pf"
                      + " WHERE n.prs_perslid_key = pf.prs_perslid_key (+)"
                      + "   AND n." + note_params.mod_tabel + "_key = " + pkey
                      + (pmodule == "ALG" ? " AND n." + note_params.mod_tabel + "_typ = " + safe.quoted_sql(alg_typ) : "");

            var sqls = [sql_n];

            var sql_t = "SELECT tr.fac_tracking_datum  note_aanmaak"
                        + "     , tr.fac_tracking_key  note_key"
                        + "     , tr.fac_tracking_oms  note_omschr"
                        + "     , tr.prs_perslid_key"
                        + "     , pf.prs_perslid_naam_friendly"
                        + "     , str.fac_srtnotificatie_code"
                        + "  FROM fac_tracking tr"
                        + "     , fac_srtnotificatie str"
                        + "     , prs_v_perslid_fullnames_all pf"
                        + " WHERE tr.fac_srtnotificatie_key = str.fac_srtnotificatie_key"
                        + "   AND tr.prs_perslid_key = pf.prs_perslid_key (+)"
                        + "   AND (tr.fac_tracking_refkey = " + pkey
                        + "   AND str.fac_srtnotificatie_xmlnode = '" + note_params.xmlnode + "')";
            sqls.push(sql_t);

            // var desc = (S("note_sort_ascending") == 0 ? " DESC " : "");
            var sql = "SELECT * FROM (" + sqls.join(" UNION ") + ") ORDER BY 1"
                    + (S("note_sort_ascending") == 0
                      ? " DESC "
                      : "")
                    + ", 2"; // ook bij gelijktijdigheid chronologisch

            var oRs = Oracle.Execute(sql);
            var lasttime = null;
            var lastuser = null;
            var firstrec = true;
            Response.Write("<div class='notes-wrapper'>");
            while(!oRs.Eof)
            {
                var thisuser = oRs("prs_perslid_naam_friendly").Value;
                var prs_key = oRs("prs_perslid_key").Value;
                var thistime = new Date(oRs("note_aanmaak").Value);
                var timestr = toTimeString(thistime);
                var srtnoti = oRs("fac_srtnotificatie_code").Value;
                var note_oms = oRs("note_omschr").Value;
                var fullname_html = notes.fnPerslidNaamFull(oRs);
                var last_note_key = oRs("note_key").Value;
                var notechange_url = mod_prefix + "_show_note2.asp?" + mod_prefix + "_key=" + pkey
                                                                     + (pmodule == "ALG" ? "&alg_typ=" + alg_typ : "")
                                                                     + "&note_key=" + last_note_key
                                                                     + "&tracking=" + (tracking? 1 : 0);
                var note_wrapper_class = "note-wrapper";
                var note_container_class = "note-container note-module-" + mod_prefix;

                oRs.MoveNext();
                var newestIsNote = false;
                var newestIsSelfNote = false;
                if ((firstrec && S("note_sort_ascending") == 0) ||  // first in descending sort
                    (oRs.Eof && S("note_sort_ascending") == 1))     // last in ascending sort
                {
                    firstrec = false;
                    newestIsNote = !srtnoti;
                    newestIsSelfNote = newestIsNote && user.isCollega(prs_key);
                }

                if (prs_key == user_key)
                    note_wrapper_class += " note-type-self";
                // Bij user of dag switch altijd kopje. Ik zou graag systeemmeldingen niet als user-switch zien,
                // dus die bij het voorgaande kopje laten horen door die te skippen bij lastuser

                if (newestIsSelfNote && last_note_key == note_key)
                    continue; // uit de while-loop

                var dedatum = toDateString(thistime, false, true);
                if (lasttime== null || (S("note_sort_ascending")? thistime.midnight() > lasttime.midnight() : thistime.midnight() < lasttime.midnight()))
                    Response.Write("<div class='note-date-wrapper'><div class='note-date'>{0}</div></div>".format(toDateString(thistime, false, true) ));

                var sameevent = (srtnoti && lastuser == thisuser && lasttime && Math.abs(thistime.getTime() - lasttime.getTime()) < 60000);

                lasttime = thistime;
                if (thisuser != null)
                    lastuser = thisuser;   // de laatste echte user

                var safehtml = "";

                note_container_class += (srtnoti ? " note-type-tracking" : "");
                if (note_oms) // Notitie of tracking met opgeslagen tekst
                {
                    safehtml = safe.notehtml(note_oms, pmodule, last_note_key);

                    var note_header_left = "";
                    if (!sameevent)
                    {
                        note_header_left += "<span class='note-author'>{0}</span>".format(fullname_html);
                        note_header_left += "<span class='note-timestamp' title='{0}'>{1}</span>".format(dedatum, timestr == "00:00" ? "" : (fullname_html != "" ? " - " : "") + timestr);
                    }
                    note_header_left = "<span class='note-header-left-wrapper'>{0}</span>".format(note_header_left);

                    var note_header_right = "";
                    var note_actions = [];
                    if (newestIsSelfNote)
                    {
                        note_actions.push({ "name"  : "edit",
                                            "label" : L("lcl_change"),
                                            "icon"  : "fa-fclt-edit",
                                            "action": "notechange('" + notechange_url + "')" });
                    }
                    if (note_actions.length >= 1)
                        note_header_right += notes.note_actions_html(note_actions);
                    note_header_right = "<span class='note-header-right-wrapper'>{0}</span>".format(note_header_right);

                    var note_header = "<div class='note-header'>{0}{1}</div>".format(note_header_left, note_header_right);

                    var autocollapse = (S("note_autocollapse") != "") && note_oms.match(new RegExp(S("note_autocollapse"))) && note_oms.split("\n").length > 2;
                    var collapse_class = "";
                    if (!newestIsNote)
                    {
                        if (autocollapse) /* ingeklapt tot 2 regels */
                            collapse_class += " note-autocollapse";
                        else if (safehtml.length > S("rs_maxchar") * 5) /* ingeklapt tot 5 regels */
                            collapse_class += " note-collapsed";
                    }
                    var toggler = "";
                    if (autocollapse || safehtml.length > S("rs_maxchar") * 5)
                        toggler += "<div class='note-toggler'>{0}</div>".format(newestIsNote ? L("lcl_rs_truncate") : L("lcl_rs_truncated"));

                    var note_text = "<div class='note-body'><div class='note-text{0}'>{1}</div>{2}</div>".format(collapse_class, safehtml, toggler);

                    var note_attachments = "";
                    if (has_any_attachments && !srtnoti) {
                        note_attachments = BB_ATTACHMENTS_HTML((pmodule === "OPDR" ? "ORD" : pmodule) + "N", last_note_key, "note");
                    }

                    /* Nu hebben we alles om de notitie te printen; */
                    Response.Write("<div class='{0}'><div class='{1}'>{2}{3}{4}</div></div>"
                        .format(note_wrapper_class, note_container_class, note_header, note_text, note_attachments));
                }
                else if (srtnoti)
                {
                    safehtml = status.getsrtnotificatietext(srtnoti); // default tracking tekst

                    var note_header = "";
                    if (!sameevent)
                    {
                        note_header += "<span class='note-author'>{0}</span>".format(fullname_html);
                        note_header += "<span class='note-timestamp' title='{0}'>{1}</span>".format(dedatum, timestr == "00:00" ? "" : (fullname_html != "" ? " - " : "") + timestr);
                    }
                    var note_text = "<div class='note-text" + (thisuser == null ? " note-type-system" : "") + "'>{0}</div>".format(safehtml);

                    if (srtnoti == pmodule + 'UPD')
                    {
                        var arr = safehtml.split("<br>");
                        arr.shift(); // Verwijder de tekst 'Factuur/Contract/Object xxx is gewijzigd'
                        for (var i = 0; i < arr.length; i++) // Eerste woord tot ':' vet maken
                        {
                            arr[i] = arr[i].replace(/^([\w]+)\:/, "<span class='bold'>$1:</span>")
                        }
                        safehtml = arr.join("<br>");
                    }

                    /* Nu hebben we alles om de notitie te printen; */
                    Response.Write("<div class='{0}'><div class='{1}'>{2}{3}</div></div>".format(note_wrapper_class, note_container_class, note_header, note_text));
                }
                // De MoveNext hebben we al eerder gehad
            }
            Response.Write("<div class='note-top-button' onclick='$(document.documentElement).animate({ scrollTop: 0 }, 150);'>" + I("fa-chevron-up fa-2x") + "</div>");
            Response.Write("</div>"); /* .notes-wrapper */
            oRs.Close();

            if (S("note_sort_ascending") != 0) { notes.note_field(pkey, note_key, pmodule, params); }
            BLOCK_END();
            SUBFRAME_END();
%>
            </body>
        </html>
<%
    }
}
%>