<% /*
     $Revision$
     $Id$

     File:    fac/fac_menu.inc.asp
     Context:

     Levert de div "menutabs" op met alle voor deze user beschikbare opties
     (en niets meer dan dat)
     Deze div heeft de nesting
       <div id="menutabs">
         <ul></ul>
         <div id="ProfFAC"></div>
         <div id="PersFAC"></div>
         <div id="MgtFAC"></div>
       </div>
*/
%>
<!--#include file="fac.inc" -->
<!--#include file="../Shared/FlexFiles.inc" -->
<%

var MENU = { PERS: 0, PROF: 1, MGT: 2, MOB: 3, TAB: 5, FAV: 6, APP: 7, WGT_PAGE: 8, WGT: 9 };

// Maak een lijstje met items onder een kopje
// Als er meer dan 1 items meer dan max_lines zijn verschijnt een More...-regel
// Het aantal zichtbare regels is dus altijd maximaal max_lines+1.

// voeg voor intern gebruik tellertje over laatste 100 dagen toe
// Let op: vooral zinvol vlak na het verversen van een database. Als dat 100 dagen geleden is dan is de telling niet zo significant meer
if (Application("otap_environment") == "O") {
    var sql = "SELECT * FROM fac_v_rap_gui_usage_last100 WHERE fclt_f_action = 'menu'";
    var oRs = Oracle.Execute(sql);
    var guiarr = {};
    while (!oRs.EOF)
    {
        guiarr[oRs("techdetail").Value] = oRs("total").Value;
        oRs.MoveNext()
    }
    oRs.Close();
}

/* Kunnen we personaliseren? En zo ja; op welk niveau? */
var statLevel = 0;
var sql = "SELECT *"
        + "  FROM fac_gui_counter"
        + " WHERE fac_gui_counter_group = 'menu'"
        + "   AND fac_gui_counter_date > TRUNC (SYSDATE - 100)";
if (S("fac_gui_counter_menu_daily") == 0 || S("fac_gui_counter_menu_daily") == 1) {
    var oRs = Oracle.Execute(sql + " AND prs_perslid_key = " + user_key);
    if (!oRs.EoF) {
        statLevel = 2;
    }
    oRs.Close();
}
if (!statLevel) {
    oRs = Oracle.Execute(sql); // Anonieme stats dan?
    if (!oRs.EoF) {
        statLevel = 1;
    }
    oRs.Close();
}

/* Return the onclick attribute for the <a>nchor */
function getClickAttribute(item) {
    if (!item || !item.href) {
        return "";
    }
    var newWindow = false;
    var result = "";
    var url = item.href;
    if (url.slice(0, 1) === "*") {
        newWindow = true;
        url = url.slice(1);
    }
    var protocol = url.split(":");
    var externUrl = protocol.length > 1 && protocol[0].match(/^(http|https|mailto|tel|qr)$/);
    if (externUrl || newWindow) {
        if (!externUrl)
            url = "../../" + url;
        result = " onclick=\"FcltMgr.stopPropagation(event);FcltMgr.windowopen('" + safe.jsstring(url) + "')\"";
    }
    else if (url.slice(0, 11) == "javascript:")
        result = " onclick=\"FcltMgr.stopPropagation(event);" + safe.htmlattr(url) + "\"";
    else {
        if (url.match(/[\?\\\/:]/g) === null) { // Als het een geupload bestand is, is er nog een (map-)prefix nodig
            url = HTTP.urlzelfnoroot() + S("menu_image_url_path") + url;
        }
        result = " onclick=\"menu(event,'" + safe.jsstring(url) + "', '" + safe.jsstring(item.name || item.label) + "', " + (item.menu_key || -1) + ");\"";
    }
    return result;
}

// params = {
//  menuItems: menuKop.Items,
//  pmode: pmode,
//  start_collapsed: boolean,
//  optional_class: string,
//  max_lines: number
// }
function CreateItems(params)
{ %>
    <ul class="<%=params.optional_class ? params.optional_class : ''%>" id="ul_<%=(params.menuItems.length ? String(params.menuItems[0].orggroep) + params.menuItems[0].menu_key : shared.random(8, "base32"))%>"<%=params.start_collapsed ? ' style="display:none"':''%>>
<%
    for (var j=0; j < params.menuItems.length; j++)
    {
        var itm = params.menuItems[j];
        if (itm.orggroep == MENU.TAB && params.pmode == 1) // pinned tabs not under favs on desktop portal
            continue;
        var ttl = "";
        if (itm.info)
            ttl=" title='"+safe.htmlattr(itm.info)+"'";
        var infomsg = "";
        if (itm.infomsg)
            infomsg = " infomsg='" + safe.htmlattr(itm.infomsg) + "'";
        var showtxt = ""; // Het zichtbare deel
        showtxt = (itm.level < 1? itm.name : safe.html(itm.name));

        if (Application("otap_environment") == "O")
        {
            if (itm.href && itm.href in guiarr)
                showtxt += " <span class='guicnt'>({0})</span>".format(guiarr[itm.href]);
        }
        var show_fav = itm.orggroep == MENU.FAV && params.pmode != 3; // Niet op portal
        var unpin = (show_fav
                    ? "<span class='menupinned' title='" + safe.htmlattr(L("lcl_current_fav_unsave")) + "'"
                        + " onclick='FcltMgr.stopPropagation(event);FcltMgr.saveFavMenu(this);'"
                        + " data-menu-key='" + (itm.menu_key || -1) + "'"
                        + " fav_ttl='" + safe.htmlattr(itm.name) + "'>"
                        + I("fa-thumbtack")
                        + "</span>"
                    : "");
%>
        <li tabindex="0" onkeypress="this.click()" class="mi<%=itm.level>0?" mi"+itm.level:""%><%=show_fav ? " fav" : ""%>"<%=ttl+infomsg%> <%=j>=params.max_lines&&params.max_lines!=params.menuItems.length-1?"style='display:none'":""%><%=getClickAttribute(itm)%><%=(params.pmode == 3 ? " data-value='" + safe.htmlattr(itm.name) + "'" : "")%>>
            <%=unpin%><%=showtxt%>
        </li>
<%
    }
    if (j > params.max_lines&&params.max_lines!=params.menuItems.length-1)
    {
%>      <li class="mi more" onclick="$('li', $(this).closest('ul')).show();$(this).hide();FcltMgr.resized();"><%=L("lcl_rs_truncated")%></li><%
    }
%>  </ul><%
}

// nog verfijnen? diepere levels?
function CreateMenuGroep(Koppen, pmode)
{
    function groepHeeftItems(pkop, pmode)
    {
        var heeft_items = false;
        if (pmode == 1)
        {
            for (var i=0; i<pkop.Items.length; i++)
            {
                if ((pkop.Items[i].group == pkop.Items[i].orggroep) ||
                    (pkop.Items[i].group == 0 && inArray(pkop.Items[i].orggroep, [MENU.FAV, MENU.WGT_PAGE]))) // In desktop komen ook widgetpagina's onder favorieten terecht
                    heeft_items = true;
            }
        }
        else
            heeft_items = true;
        return heeft_items;
    }

%>  <ul><%
    if (Koppen.length > S("menu_collapse_threshold"))
        menu_start_collapsed = 1; else menu_start_collapsed = 0;

    for (var i = 0; i<Koppen.length; i++)
    {
        var menuKop = Koppen[i];
        var ttl = "";
        if (menuKop.info)
            ttl=' title="'+safe.htmlattr(menuKop.info)+'"';
        // Gaat het hier om een hoofdmenuitem met submenuitems of om een image link (logo) als menu item?
        // Een hoofdmenuitem heeft submenuitems (en heeft geen url)
        if (menuKop.Items.length > 0 && groepHeeftItems(menuKop, pmode))
        { // Hoofdmenuitems met submenuitems
            var start_collapsed = !menuKop.startopen && menu_start_collapsed == 1;
%>          <li class="mk"<%=ttl%> tabindex="0"
                aria-expanded="<%=start_collapsed ? "false" : "true"%>"
                aria-controls="ul_<%=(menuKop.Items.length ? String(menuKop.Items[0].orggroep) + menuKop.Items[0].menu_key : shared.random(8, "base32"))%>"><%
            if (S("menu_use_menuicons") == 1)
            {
                if (menuKop.image && menuKop.image != "")
                {
                    Response.Write("<span class='micon'>"
                                 +    SYMBOL(menuKop.image, { "module": "MENU" })
                                 + "</span>");
                }
                else
                {
%>                  <span class="nomicon"></span><% // invisible but take up the same space as an image
                }
            } %>
            <span class="menukop"><%= safe.html(menuKop.label) %></span>
        <% var params = {
            menuItems: menuKop.Items,
            pmode: pmode,
            start_collapsed: start_collapsed,
            optional_class: menuKop.label == L("lcl_current_fav") ? 'favorites' : ''
        }
        CreateItems(params); %>
        </li>
        <% }
        else
        {   // Gaat het hier om een image link (logo) als menu item?
            // Een logo als menuitem als
            // 1) Menuitem moet een hoofdmenuitem zijn (Instelling "Topniveau" moet aan staan) die geen enkele submenu item heeft
            // 2) Met plaatje/logo
            // 3) Met een url naar de pagina
            if (menuKop.image && menuKop.image != "" && menuKop.href && menuKop.href != "")
            { // Het gaat hier over een image als menu item
                var iconImg = menuKop.image.indexOf("fa-") == 0;
%>          <li class="mk"<%=ttl%><%=getClickAttribute(menuKop)%>>
                <span class="micon"><%=SYMBOL(menuKop.image, { "module": "MENU" })%></span>
<%              if (iconImg) { %>
                <span class="menukop"><%= safe.html(menuKop.label) %></span>
<%              } %>
            </li>
<%          }
        }
    }
%>    </ul><%
}

function generatePortalmenu(koppen, asWidget)
{
    if (koppen.length == 0)
        return;
%>
    <div class="container-fluid"><%
    var col = 0;
    // Hoeveel procent per kolom igv volle breedte
    var cols_per_row = S("portalmenucols") || 2;
    for (var i = 0; i < koppen.length; i++)
    {
        var menuKop = koppen[i];
        // Gaat het hier om een hoofdmenuitem met submenuitems of om een image link (logo) als menu item?
        // Een hoofdmenuitem heeft submenuitems (en heeft geen url)
        var isCol = menuKop.Items.length > 0 || (menuKop.image && menuKop.image != "" && menuKop.href && menuKop.href != "");
        if (isCol && col == 0)
        { %>
        <div class="row">
<%      }
        if (menuKop.Items.length > 0)
        { // Hoofdmenuitems met submenuitems
            var hasOneItem = S("portalmenu_combine_single")>0 && menuKop.Items.length == 1;
%>
            <div class="col">
                <div id="mk<%=menuKop.menu_key || "0"%>" class="menu-kop-content<%=hasOneItem ? " withaction" : ""%>"
                <%=hasOneItem ? getClickAttribute(menuKop.Items[0]) : ""%>
                >
<%
            var ttl = "";
            if (menuKop.info)
                ttl=" title='"+safe.htmlattr(menuKop.info)+"'";

            if (!hasOneItem)
            { %>
                    <span class="menuimg"<%=ttl%>>
                        <%=SYMBOL(menuKop.image, { "module": "MENU" })%>
                    </span>
<%          } %>
                    <div class='<%=(asWidget ? "widget-menu-kop" : "portalmenukop" + (menuKop.Items[0].href && hasOneItem ? " withimg" : ""))%>'>
                        <span class="menukop"<%=ttl%>>
                            <%=safe.html(hasOneItem && S("portalmenu_combine_single") == 2 && menuKop.Items[0].orggroep == MENU.FAV ? menuKop.Items[0].name : menuKop.label)%>
                        </span>
<%          if (hasOneItem)
            { %>
                        <span class="menuimg<%=(menuKop.Items[0].href && !hasOneItem ? " withaction" : "")%>"<%=ttl%><%=hasOneItem ? "" : getClickAttribute(menuKop.Items[0])%>>
                        <%=SYMBOL(menuKop.image, { "module": "MENU", "alt": menuKop.Items[0].label })%>
                        </span>
<%          }
            if (!hasOneItem || S("portalmenu_combine_single")<2) {
                var params = {
                    menuItems: menuKop.Items,
                    pmode: 3,
                    start_collapsed: false,
                    max_lines: S("portalmenulines")
                }
                CreateItems(params);
            }
%>                  </div>
                </div>
            </div>
<%          col++;
        }
        else if (menuKop.image && menuKop.image != "" && menuKop.href && menuKop.href != "") // Menu*kop* met directe link
        {
%>
            <div class="col">
                <div id="mk<%=menuKop.menu_key%>" class="menu-kop-content">
<%
            var ttl = "";
            if (menuKop.info)
                ttl=" title='"+safe.htmlattr(menuKop.info)+"'";
%>
                    <div class='widget-menu-image'>
                        <a<%=getClickAttribute(menuKop)%>>
                            <%=SYMBOL(menuKop.image, { "module": "MENU" })%>
                        </a>
                    </div>
                </div>
            </div>
<%          col++;
        }
        if (isCol && col == cols_per_row)
        { %>
        </div>
<%          col = 0;
        }
    }
    while (!asWidget && col != 0 && col != cols_per_row) // Aanvullen met lege columns om grid te behouden
    { %>
            <div class="col"></div>
<%      col++;
    }

    if (col != 0) // Dan moet de row nog afgesloten worden
    { %>
        </div>
<%  } %>
    </div>
<%
}

/* Genereert 1 menuitem met 1 plaatje erboven */
function generatePortalmenuitem(kop)
{
    var item = kop.Items[0];
%>
    <div id="mi<%=item.menu_key%>" class="menu-item-content<%=(item.href ? " withaction" : "")%>"<%=getClickAttribute(item)%>>
<%
    var ttl = "";
    if (item.info)
        ttl=" title='"+safe.htmlattr(item.info)+"'";
%>
        <div class='widget-menu-item'>
            <span class="menulabel"<%=ttl%>>
                <%=safe.html(item.name)%>
            </span>
            <span class="menuimg"<%=ttl%>>
                <%=SYMBOL(item.img, { "module": "MENU" })%>
            </span>
        </div>
    </div>
<%
}

// Vul het op te leveren object met menuitems volgens mode;
// 0/null = Alles behalve Mobile/App
// 1 = Desktop groepen PERS: 0, PROF: 1, MGT: 2 (of; Zelfservice, Service & Admin)
// 2 = Mobile
// 3 = Mobile + App

// Additionele parameters;
// sqlOnly:    Levert alleen de SQL op
// portalOnly: Levert alleen menuitems op die op de portal moeten komen (vinkje)
// level:      Levert alleen (hoofd)menukoppen (1) of (sub)menuitems (2) op
function fillMenuArray(mode, params)
{
    mode = mode || 0;
    // Levert een tweedimensionaal menu-array op met alle opties, in de juiste volgorde,
    // waarbij 0=personal, 1=professional, 2=management, 3=mobile, 4=?, 5=pinned tab, 6=favoriten menu, 7=App
    // als er nog niet is ingelogd, wordt null opgeleverd.
    params = params || {};

    var tmp = fac.myfunctionssqlstring(user_key);
    var lmyreadfacfunctiekeys = tmp.read;
    var lmywritefacfunctiekeys = tmp.write;

    var portalOnlySql = (params.portalOnly
                            ? " AND (fac_menu_portal = 1"
                                + (S("favorites_on_portal_menu")    // Display FAV(6) on desktop portal
                                    ? " OR fac_menu_altgroep = 6"
                                    : "")
                                + ")"
                            : "");

    // Deze querie levert de geldende menu-opties op, dat zijn:
    // die uit fac_menu
    // - waarvoor ik de juiste autorisatie heb (functie + read of write)
    // - geen autorisatie gegevens is ook altijd goed
    // - waar aangegeven (draft) vermenigvuldigd met de module-srt/disciplines waarvoor ik rechten heb (functie +read of write)
    // Voor de functies MET disciplines-autorisaties kunnen we beter direct bijjoinen, vond ik.
    // TODO: (in menufunctions.inc): de diepere levels beter/anders supporten (openklapbaar)
    var stats_select = " , NULL visits";
    var stats_from = "";
    var stats_where = "";
    if (statLevel > 0) { // Verzamel statistieken
        stats_select = " , stats.visits visits";
        stats_from = " , (SELECT fgc.fac_gui_counter_refkey"
                   + (statLevel == 2 && S("fac_gui_counter_menu_daily") == 0
                       ? "     , COUNT (*)"
                       : "     , SUM (fgc.fac_gui_counter_count)") + " visits"
                   + "      FROM fac_gui_counter fgc"
                   + "     WHERE fgc.fac_gui_counter_group = 'menu'"
                   + "       AND fgc.fac_gui_counter_date > TRUNC (SYSDATE - 100)"
                   + (statLevel == 2
                       ? "   AND fgc.prs_perslid_key = " + user_key
                       : "")
                   + "  GROUP BY fgc.fac_gui_counter_refkey"
                   + "   ) stats";
        stats_where = " AND stats.fac_gui_counter_refkey(+) = m.fac_menu_key";
    }

    var sql = "SELECT * FROM ("
            + " SELECT fac_menu_key"
            + "      , " + lcl.xsql2('COALESCE (fac_menu_altlabel, fac_menuitems_label)', 'FAC_MENU_ALTLABEL', 'fac_menu_key') + " label"
            + "      , to_char(null) exploded "
            + "      , REPLACE(REPLACE(COALESCE (fac_menu_alturl, fac_menuitems_url) "
            + "        || CASE WHEN m.ins_discipline_key IS NOT NULL THEN CASE WHEN INSTR(COALESCE (fac_menu_alturl, fac_menuitems_url), '?') > 0 THEN '&' ELSE '?' END || 'dis_key='|| m.ins_discipline_key END "
            + "        || CASE WHEN m.ins_srtdiscipline_key IS NOT NULL THEN CASE WHEN INSTR(COALESCE (fac_menu_alturl, fac_menuitems_url), '?') > 0 THEN '&' ELSE '?' END || 'srtdisc='|| m.ins_srtdiscipline_key END, '{0}', m.ins_srtdiscipline_key), '{1}', m.ins_discipline_key) "
            + "        url "
            + "      , fac_menu_filter  filter"
            + "      , fac_menu_advfilter advfilter"
            + "      , COALESCE (fac_menu_image, fac_menuitems_image) image"
            + "      , COALESCE (fac_menu_altgroep, fac_menuitems_groep) groep"
            + "      , fac_menu_level "
            + "      , fac_menu_portal"
            + "      , " + lcl.xsqla('fac_menu_info', 'fac_menu_key')
            + "      , fac_menu_message"
            + "      , fac_menu_volgnr"
            + "      , COALESCE (m.fac_functie_key, mi.fac_functie_key) fac_functie_key"
            + "      , COALESCE (mi.fac_menuitems_rw, 'R')"
            + "      , 0 depth"
            + stats_select
            + " FROM fac_menu m"
            + "    , fac_menuitems mi"
            + stats_from
            + " WHERE m.fac_menuitems_key = mi.fac_menuitems_key(+)"
            + stats_where
            // Systeemautorisatie
            + " AND (mi.fac_functie_key IS NULL"    /* niet-explodeerbare opties zonder autorisaties */
                + " OR (COALESCE (mi.fac_menuitems_rw, 'R') = 'R' AND mi.fac_functie_key IN (" + lmyreadfacfunctiekeys + "))"   /* niet-explodeerbare opties met read-autorisatie */
                + " OR (COALESCE (mi.fac_menuitems_rw, 'R') = 'W' AND mi.fac_functie_key IN (" + lmywritefacfunctiekeys + "))"  /* niet-explodeerbare opties met write-autorisatie */
                + " )"
            // Extra autorisatie
            + " AND (m.fac_functie_key IS NULL"    /* niet-explodeerbare opties zonder autorisaties */
                + " OR (COALESCE (mi.fac_menuitems_rw, 'R') = 'R' AND m.fac_functie_key IN (" + lmyreadfacfunctiekeys + "))"    /* niet-explodeerbare opties met read-autorisatie */
                + " OR (COALESCE (mi.fac_menuitems_rw, 'R') = 'W' AND m.fac_functie_key IN (" + lmywritefacfunctiekeys + "))"   /* niet-explodeerbare opties met write-autorisatie */
                + " )"

    sql +="   AND COALESCE (mi.fac_menuitems_disc, 0) = 0"
        + "   AND COALESCE (mi.fac_menuitems_srtdisc, 0) = 0"
        + portalOnlySql
        + ("level" in params ? " AND m.fac_menu_level = " + safe.quoted_sql(params.level) : "")
        // Extra autorisatie met een gekozen ins_discipline of ins_srtdiscipline
        + " AND ((m.ins_discipline_key IS NULL AND m.ins_srtdiscipline_key IS NULL)"
            + " OR (m.ins_discipline_key IS NOT NULL AND EXISTS "
                + "(SELECT ''"
                + " FROM fac_groeprechten g, fac_gebruikersgroep gg"
                + " WHERE g.fac_groep_key = gg.fac_groep_key"
                + " AND (g.ins_discipline_key = m.ins_discipline_key OR g.ins_discipline_key IS NULL)"
                + " AND g.fac_functie_key = m.fac_functie_key"
                + " AND fac_gebruiker_prs_level_read < 9"
                + " AND fac_gebruiker_alg_level_read < 9"
                + " AND gg.prs_perslid_key = " + user_key
            + "))"
            + " OR (m.ins_srtdiscipline_key IS NOT NULL AND EXISTS "
                + "(SELECT ''"
                + " FROM fac_groeprechten g, fac_gebruikersgroep gg, ins_tab_discipline d"
                + " WHERE g.fac_groep_key = gg.fac_groep_key"
                + " AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
                + " AND d.ins_srtdiscipline_key = m.ins_srtdiscipline_key"
                + " AND g.fac_functie_key = m.fac_functie_key"
                + " AND fac_gebruiker_prs_level_read < 9"
                + " AND fac_gebruiker_alg_level_read < 9"
                + " AND gg.prs_perslid_key = " + user_key
            + "))"
        + ")"

    if (mode == 0 || mode == 1) // !Mobile
    {
        sql +=" UNION ALL" // BES artikelcatalogi zonder een afzonderlijke vermelding
            + " SELECT fac_menu_key"
            + "      , " + lcl.xsql2('COALESCE (fac_menu_altlabel, fac_menuitems_label)', 'FAC_MENU_ALTLABEL', 'fac_menu_key') + " label"
            + "      , CASE WHEN sd.ins_srtdiscipline_omschrijving IS NULL " // geen lcl.xsql; veronderstelt: geen basistaal, dan ook geen vertaling
            + "        THEN ''"
            + "        ELSE " + lcl.xsql('sd.ins_srtdiscipline_omschrijving', 'sd.ins_srtdiscipline_key') + "||' '"
            + "        END || "
            +          lcl.xsql('d.ins_discipline_omschrijving', 'd.ins_discipline_key')
            + "        exploded "
            + "      , REPLACE(COALESCE (fac_menu_alturl, fac_menuitems_url) "
            + "        ||  CASE WHEN d.ins_discipline_key IS NOT NULL THEN CASE WHEN INSTR(COALESCE (fac_menu_alturl, fac_menuitems_url), '?') > 0 THEN '&' ELSE '?' END || 'dis_key=' || d.ins_discipline_key END, '{1}', d.ins_discipline_key)"
            + "        url"
            + "      , fac_menu_filter  filter"
            + "      , fac_menu_advfilter advfilter"
            + "      , COALESCE (fac_menu_image, fac_menuitems_image) image"
            + "      , COALESCE (fac_menu_altgroep, fac_menuitems_groep) groep"
            + "      , fac_menu_level "
            + "      , fac_menu_portal"
            + "      , " + lcl.xsql('d.ins_discipline_opmerking', 'd.ins_discipline_key') + " fac_menu_info"   // info per discipline
            + "      , fac_menu_message"
            + "      , fac_menu_volgnr"
            + "      , COALESCE (m.fac_functie_key, mi.fac_functie_key) fac_functie_key"
            + "      , COALESCE (mi.fac_menuitems_rw, 'R')"
            + "      , 2 depth"
            + stats_select
            + " FROM fac_menu m"
            + "    , fac_menuitems mi"
            + "    , ins_tab_discipline d"
            + "    , ins_srtdiscipline sd "
            + stats_from
            + " WHERE m.fac_menuitems_key = mi.fac_menuitems_key(+)"
            + stats_where
            + "   AND d.ins_discipline_module = mi.fac_menuitems_module"
            + "   AND d.ins_discipline_verwijder IS NULL"
            + "   AND d.ins_srtdiscipline_key = sd.ins_srtdiscipline_key(+)"
            + "   AND COALESCE (mi.fac_menuitems_disc, 0) = 1"
            + portalOnlySql
            + ("level" in params ? " AND m.fac_menu_level = " + safe.quoted_sql(params.level) : "")
            + (params.sqlOnly && params.level == 2 ? " AND COALESCE (mi.fac_menuitems_disc, 0) = 0" : "") // widget-type menuitem (nog) niet compatible met exploderende menuitems
            + "   AND d.ins_discipline_key NOT IN ("     /* sluit items met een afzonderlijke vermelding uit */
            + "       SELECT mm.ins_discipline_key"
            + "         FROM fac_menu mm "
            + "        WHERE mm.fac_functie_key = mi.fac_functie_key" // Alleen bij extra autorisatie kun je fac_menu.ins_discipline_key hebben
            + "          AND mm.ins_discipline_key IS NOT NULL"
            + "       )"
            + "   AND (COALESCE (m.fac_functie_key, mi.fac_functie_key) IS NULL"    /* disc-explodeerbare opties zonder autorisaties */
            + "        OR (COALESCE (mi.fac_menuitems_rw, 'R') = 'R'"
            + "            AND EXISTS"
            + "                 (SELECT ''"
            + "                    FROM fac_groeprechten g, fac_gebruikersgroep gg"
            + "                   WHERE g.fac_groep_key = gg.fac_groep_key"
            + "                     AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                     AND g.fac_functie_key = mi.fac_functie_key"
            + "                     AND fac_gebruiker_prs_level_read < 9"
            + "                     AND fac_gebruiker_alg_level_read < 9"
            + "                     AND gg.prs_perslid_key = " + user_key
            + "                  )"
            + "            AND (EXISTS"
            + "                  (SELECT ''"
            + "                     FROM fac_groeprechten g, fac_gebruikersgroep gg"
            + "                    WHERE g.fac_groep_key = gg.fac_groep_key"
            + "                      AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                      AND g.fac_functie_key = m.fac_functie_key"
            + "                      AND fac_gebruiker_prs_level_read < 9"
            + "                      AND fac_gebruiker_alg_level_read < 9"
            + "                      AND gg.prs_perslid_key = " + user_key + ")"
            + "                 OR m.fac_functie_key IS NULL)"
            + "           )"
            + "        OR (COALESCE (mi.fac_menuitems_rw, 'R') = 'W'"
            + "            AND EXISTS"
            + "                 (SELECT ''"
            + "                    FROM fac_groeprechten g, fac_gebruikersgroep gg"
            + "                   WHERE g.fac_groep_key = gg.fac_groep_key"
            + "                     AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                     AND g.fac_functie_key = mi.fac_functie_key"
            + "                     AND fac_gebruiker_prs_level_write < 9"
            + "                     AND fac_gebruiker_alg_level_write < 9"
            + "                     AND gg.prs_perslid_key = " + user_key
            + "                  )"
            + "            AND (EXISTS"
            + "                  (SELECT ''"
            + "                     FROM fac_groeprechten g, fac_gebruikersgroep gg"
            + "                    WHERE g.fac_groep_key = gg.fac_groep_key"
            + "                      AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                      AND g.fac_functie_key = m.fac_functie_key"
            + "                      AND fac_gebruiker_prs_level_write < 9"
            + "                      AND fac_gebruiker_alg_level_write < 9"
            + "                      AND gg.prs_perslid_key = " + user_key + ") "
            + "                 OR m.fac_functie_key IS NULL)"
            + "           )"
            + "       )"

            + " UNION ALL" // MLD srtdisciplines zonder een afzonderlijke vermelding
            + " SELECT m.fac_menu_key"
            + "      , " + lcl.xsql2('COALESCE (fac_menu_altlabel, fac_menuitems_label)', 'FAC_MENU_ALTLABEL', 'fac_menu_key') + " label"
            + "      , " + lcl.xsql('sd.ins_srtdiscipline_omschrijving', 'sd.ins_srtdiscipline_key') + " exploded"
            + "      , COALESCE (m.fac_menu_alturl, mi.fac_menuitems_url) || CASE WHEN INSTR(COALESCE (fac_menu_alturl, fac_menuitems_url), '?') > 0 THEN '&' ELSE '?' END || 'srtdisc='|| sd.ins_srtdiscipline_key url "
            + "      , fac_menu_filter  filter"
            + "      , fac_menu_advfilter advfilter"
            + "      , COALESCE (m.fac_menu_image, mi.fac_menuitems_image) image"
            + "      , COALESCE (m.fac_menu_altgroep, mi.fac_menuitems_groep) groep"
            + "      , m.fac_menu_level "
            + "      , m.fac_menu_portal"
            + "      , "+lcl.xsql('sd.ins_srtdiscipline_opmerking', 'sd.ins_srtdiscipline_key')+" fac_menu_info"   // info per srtdiscipline
            + "      , m.fac_menu_message"
            + "      , m.fac_menu_volgnr"
            + "      , COALESCE (m.fac_functie_key, mi.fac_functie_key)"
            + "      , mi.fac_menuitems_rw"
            + "      , 1 depth"
            + stats_select
            + " FROM fac_menu m"
            + "    , fac_menuitems mi"
            + "    , ins_srtdiscipline sd "
            + stats_from
            + " WHERE m.fac_menuitems_key = mi.fac_menuitems_key(+)"
            + stats_where
            + "   AND sd.ins_srtdiscipline_module = mi.fac_menuitems_module "
            + "   AND sd.ins_srtdiscipline_verwijder IS NULL "
            + portalOnlySql
            + ("level" in params ? " AND m.fac_menu_level = " + safe.quoted_sql(params.level) : "")
            + (params.sqlOnly && params.level == 2 ? " AND COALESCE (mi.fac_menuitems_srtdisc, 0) = 0" : "") // widget-type menuitem (nog) niet compatible met exploderende menuitems
            + "   AND COALESCE (mi.fac_menuitems_srtdisc, 0) = 1 "
            + "   AND mi.fac_menuitems_module != 'RES' " // Voor MLD heeft ins_srtdiscipline (vakgroeptype) alleen een waarde
            + "   AND sd.ins_srtdiscipline_key <> "+ S("kto_srtdiscipline_key")   // die tonen we niet in het menu
            + "   AND sd.ins_srtdiscipline_key IN "
            + "            (SELECT   d.ins_srtdiscipline_key "
            + "               FROM   ins_tab_discipline d "
            + "                    , mld_disc_params mdp "
            + "              WHERE   d.ins_discipline_verwijder IS NULL "
            + "                 AND  mdp.mld_ins_discipline_key = d.ins_discipline_key"
            + "                 AND  BITAND(mdp.mld_disc_params_srtgroep, 5) > 0"  /* sluit behandelteams-only vakgroepen uit */
            + "                      AND d.ins_srtdiscipline_key NOT IN "    /* sluit items met een afzonderlijke vermelding uit */
            + "                               (SELECT mm.ins_srtdiscipline_key "
            + "                                  FROM fac_menu mm "
            + "                                 WHERE mm.fac_functie_key = mi.fac_functie_key" // Alleen bij extra autorisatie kun je fac_menu.ins_discipline_key hebben
            + "                                       AND mm.ins_srtdiscipline_key IS NOT NULL) "
            + "                      AND (COALESCE (m.fac_functie_key, mi.fac_functie_key) IS NULL "        /* srtdisc-explodeerbare opties zonder autorisaties */
            + "                           OR (mi.fac_menuitems_rw = 'R'"
            + "                               AND EXISTS " // Systeemautorisatie
            + "                                    (SELECT '' "
            + "                                       FROM fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                      WHERE g.fac_groep_key = gg.fac_groep_key "
            + "                                        AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                        AND g.fac_functie_key = mi.fac_functie_key "
            + "                                        AND fac_gebruiker_prs_level_read < 9 "
            + "                                        AND fac_gebruiker_alg_level_read < 9 "
            + "                                        AND gg.prs_perslid_key = " + user_key
            + "                                    )"
            + "                               AND (EXISTS " // Extra autorisatie
            + "                                     (SELECT '' "
            + "                                        FROM fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                       WHERE g.fac_groep_key = gg.fac_groep_key "
            + "                                        AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                        AND g.fac_functie_key = m.fac_functie_key"
            + "                                        AND fac_gebruiker_prs_level_read < 9 "
            + "                                        AND fac_gebruiker_alg_level_read < 9 "
            + "                                        AND gg.prs_perslid_key = " + user_key + ")"
            + "                                      OR m.fac_functie_key IS NULL)"
            + "                              )"
            + "                           OR (mi.fac_menuitems_rw = 'W'"
            + "                               AND EXISTS " // Systeemautorisatie
            + "                                    (SELECT '' "
            + "                                       FROM fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                      WHERE g.fac_groep_key = gg.fac_groep_key "
            + "                                        AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                        AND g.fac_functie_key = mi.fac_functie_key "
            + "                                        AND fac_gebruiker_prs_level_write < 9 "
            + "                                        AND fac_gebruiker_alg_level_write < 9 "
            + "                                        AND gg.prs_perslid_key = " + user_key
            + "                                    ) "
            + "                               AND (EXISTS " // Extra autorisatie
            + "                                     (SELECT '' "
            + "                                        FROM fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                       WHERE g.fac_groep_key = gg.fac_groep_key "
            + "                                         AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                         AND g.fac_functie_key = m.fac_functie_key"
            + "                                         AND fac_gebruiker_prs_level_write < 9 "
            + "                                         AND fac_gebruiker_alg_level_write < 9 "
            + "                                         AND gg.prs_perslid_key = " + user_key + ")"
            + "                                    OR m.fac_functie_key IS NULL)"
            + "                           ))) "

            + " UNION ALL" // RES: srtactiviteiten
            + " SELECT DISTINCT m.fac_menu_key"
            + "      , " + lcl.xsql2('COALESCE (fac_menu_altlabel, fac_menuitems_label)', 'FAC_MENU_ALTLABEL', 'fac_menu_key') + " label"
            + "      , " + lcl.xsql('sa.res_srtactiviteit_omschrijving', 'sa.res_srtactiviteit_key') + " exploded"
            + "      , COALESCE (m.fac_menu_alturl, mi.fac_menuitems_url) || '&srtact=' || sa.res_srtactiviteit_key url "
            + "      , fac_menu_filter  filter"
            + "      , fac_menu_advfilter advfilter"
            + "      , COALESCE (m.fac_menu_image, mi.fac_menuitems_image) image"
            + "      , COALESCE (m.fac_menu_altgroep, mi.fac_menuitems_groep) groep"
            + "      , m.fac_menu_level "
            + "      , m.fac_menu_portal"
            + "      , " + lcl.xsql('sa.res_srtactiviteit_opmerking', 'sa.res_srtactiviteit_key') + " fac_menu_info"   // info per srtdiscipline
            + "      , m.fac_menu_message"
            + "      , m.fac_menu_volgnr"
            + "      , COALESCE (m.fac_functie_key, mi.fac_functie_key)"
            + "      , mi.fac_menuitems_rw"
            + "      , 1 depth"
            + stats_select
            + "   FROM fac_menu m"
            + "      , fac_menuitems mi"
            + "      , res_srtactiviteit sa"
            + stats_from
            + "   WHERE m.fac_menuitems_key = mi.fac_menuitems_key(+)"
            + stats_where
            + "     AND sa.res_srtactiviteit_verwijder IS NULL"
            + portalOnlySql
            + ("level" in params ? " AND m.fac_menu_level = " + safe.quoted_sql(params.level) : "")
            + (params.sqlOnly && params.level == 2 ? " AND COALESCE (mi.fac_menuitems_srtdisc, 0) = 0" : "") // widget-type menuitem (nog) niet compatible met exploderende menuitems
            + "     AND COALESCE (mi.fac_menuitems_srtdisc, 0) = 1"
            + "     AND mi.fac_menuitems_module = 'RES' "
            + "     AND sa.res_srtactiviteit_key IN "
            + "         (SELECT   ra.res_srtactiviteit_key "
            + "            FROM   ins_tab_discipline d, res_activiteitdiscipline ad, res_activiteit ra "
            + "           WHERE       d.ins_discipline_module = mi.fac_menuitems_module "
            + "                   AND d.ins_discipline_verwijder IS NULL "
            + "                   AND ra.res_activiteit_verwijder IS NULL "
            + "                   AND ad.res_activiteit_key = ra.res_activiteit_key "
            + "                   AND d.ins_discipline_key = ad.res_discipline_key "
            + "                   AND d.ins_srtdiscipline_key NOT IN "        /* sluit items met een afzonderlijke vermelding uit */
            + "                            (SELECT   mm.ins_srtdiscipline_key "
            + "                               FROM   fac_menu mm "
            + "                              WHERE   mm.fac_functie_key = mi.fac_functie_key" // Alleen bij extra autorisatie kun je fac_menu.ins_discipline_key hebben
            + "                                      AND mm.ins_srtdiscipline_key IS NOT NULL) "
            + "                   AND (COALESCE (m.fac_functie_key, mi.fac_functie_key) IS NULL "    /* srtact-explodeerbare opties zonder autorisaties */
            + "                        OR (mi.fac_menuitems_rw = 'R' "
            + "                            AND EXISTS " // Systeemautorisatie
            + "                                 (SELECT   '' "
            + "                                    FROM   fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                   WHERE       g.fac_groep_key = gg.fac_groep_key "
            + "                                           AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                           AND g.fac_functie_key = mi.fac_functie_key "
            + "                                           AND fac_gebruiker_prs_level_read < 9 "
            + "                                           AND fac_gebruiker_alg_level_read < 9 "
            + "                                           AND gg.prs_perslid_key = " + user_key
            + "                                 )"
            + "                            AND (EXISTS " // Extra autorisatie
            + "                                  (SELECT   '' "
            + "                                     FROM   fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                    WHERE       g.fac_groep_key = gg.fac_groep_key "
            + "                                            AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                            AND g.fac_functie_key = m.fac_functie_key"
            + "                                            AND fac_gebruiker_prs_level_read < 9 "
            + "                                            AND fac_gebruiker_alg_level_read < 9 "
            + "                                            AND gg.prs_perslid_key = " + user_key + ")"
            + "                                   OR m.fac_functie_key IS NULL)"
            + "                       )"
            + "                        OR (mi.fac_menuitems_rw = 'W' "
            + "                            AND EXISTS " // Systeemautorisatie
            + "                                 (SELECT   '' "
            + "                                    FROM   fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                   WHERE       g.fac_groep_key = gg.fac_groep_key "
            + "                                           AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                           AND g.fac_functie_key = mi.fac_functie_key "
            + "                                           AND fac_gebruiker_prs_level_write < 9 "
            + "                                           AND fac_gebruiker_alg_level_write < 9 "
            + "                                           AND gg.prs_perslid_key = " + user_key
            + "                                 ) "
            + "                            AND (EXISTS " // Extra autorisatie
            + "                                  (SELECT   '' "
            + "                                     FROM   fac_groeprechten g, fac_gebruikersgroep gg "
            + "                                    WHERE       g.fac_groep_key = gg.fac_groep_key "
            + "                                            AND (g.ins_discipline_key = d.ins_discipline_key OR g.ins_discipline_key IS NULL)"
            + "                                            AND g.fac_functie_key = m.fac_functie_key"
            + "                                            AND fac_gebruiker_prs_level_write < 9 "
            + "                                            AND fac_gebruiker_alg_level_write < 9 "
            + "                                            AND gg.prs_perslid_key = " + user_key + ")"
            + "                                 OR m.fac_functie_key IS NULL)"
            + "                    ))) ";
        if (S("fac_usrrap_mode") == 1)
        {
        sql +=" UNION ALL " // Widgetpagina's
            + " SELECT fac_widget_page_key fac_menu_key" // Om het makkelijk te maken
            + "      , fac_widget_page_name label"
            + "      , to_char(null) exploded"
            + "      , './appl/fac/fac_widget_page.asp?wgt_page_key=' || fac_widget_page_key url "
            + "      , NULL filter"
            + "      , NULL advfilter"
            + "      , NULL image"
            + "      , " + MENU.WGT_PAGE + " groep"
            + "      , 2 fac_menu_level "
            + "      , NULL fac_menu_portal"
            + "      , NULL fac_menu_info"
            + "      , NULL fac_menu_message"
            + "      , NULL fac_menu_volgnr" // Deze komen als eerste onder de 'Favorieten' terug
            + "      , NULL fac_functie_key"
            + "      , NULL fac_menuitems_rw"
            + "      , 1 depth" // unused ?
            + "      , NULL visits"
            + "   FROM fac_widget_page fwp"
            + "  WHERE fac_widget_page_key <> " + S("widgetportal")
            + "    AND fwp.fac_groep_key IS NOT NULL"
            + "    AND fwp.fac_groep_key IN (SELECT fgg.fac_groep_key"
            + "                                FROM fac_gebruikersgroep fgg"
            + "                               WHERE fgg.prs_perslid_key = " + user_key + ")"
            + "    AND (fwp.prs_perslid_key IS NULL"
            + "         OR fwp.prs_perslid_key = " + user_key + ")"
        }
    }
    else // if (mode == 2 || mode == 3) // Mobile || App
    {
        sql += " AND fac_menu_altgroep = 3"
             + (mode == 2 ? " AND (fac_menu_portal <> 1 OR fac_menu_portal IS NULL)" : ""); // fac_menu_portal = 1 betekent app (en app is mode == 3)
    }
    sql += " )";
    sql += " WHERE groep IS NOT NULL"; // Veiligheidje
    sql += (mode == 1 ? " AND groep IN (0, 1, 2)" : "");
    sql += "   AND ("
         + "          (groep = " + MENU.WGT_PAGE
         + "             AND fac_menu_key IN (SELECT fac_widget_page_key"
         + "                                   FROM fac_widget_page"
         + "                                  WHERE prs_perslid_key IS NULL OR prs_perslid_key = " + user_key + "))"
         + "        OR fac_menu_key IN (SELECT fac_menu_key"
         + "                              FROM fac_menu"
         + "                             WHERE prs_perslid_key IS NULL OR prs_perslid_key = " + user_key + ")"
         + "       )";

    // Favorieten (groep=6) *voor* de rest van de zelfservice (groep=0)
    sql += " ORDER BY DECODE(groep, " + MENU.WGT_PAGE   + ", 1, "
                                      + MENU.TAB        + ", 2, "
                                      + MENU.FAV        + ", 3, "
                                      + /* ELSE */        "  9)"
        + "         , fac_menu_volgnr, label, exploded ";

    if ("sqlOnly" in params && params.sqlOnly)
        return sql;

    var loRs = Oracle.Execute( sql );

    // Verwerk de opties tot menu-array. Het is van belang dat er geen nodeloze
    // items (zoals kop zonder items) in voorkomen, omdat zichtbaarheid
    // van de groep op lengte>0 wordt bepaald
    // Groepen --> Koppen --> Items
    var Groepen = [];
    while( !loRs.eof )
    {
        var groepnr = loRs("groep").Value;
        if (groepnr == MENU.MOB)
            groepnr = loRs("fac_menu_portal").Value ? MENU.APP : MENU.MOB; // fac_menu_portal = 1 betekent APP
        var orggroep = groepnr;
        if (groepnr == MENU.WGT_PAGE) // 'Gepubliceerde' widgetpagina's komen onder favorieten
            groepnr = MENU.FAV;
        if (groepnr == MENU.TAB) // Pinned tabs gaan onder favorieten in non-desktop mode
            groepnr = MENU.FAV;
        if (groepnr == MENU.FAV)
            groepnr = MENU.PERS; // Daar stoppen we de favorieten onder
        if (mode == 0 || mode == 1) // !Mobile
        {
            var mlabel = fac.localstring(loRs("label").Value);
            if (loRs("exploded").Value)
                mlabel += " " + loRs("exploded").Value;

            if (!Groepen[groepnr])
                Groepen[groepnr] = { Koppen: []};
            var grp = Groepen[groepnr];

            // De allereerste van iedere groep MOET een kop worden
            if (loRs("fac_menu_level").Value == 1)
            {
                grp.Koppen.push({   Items:      [],
                                    label:      mlabel,
                                    info:       loRs("fac_menu_info").Value,
                                    image:      loRs("image").Value,
                                    menu_key:   loRs("fac_menu_key").Value,
                                    menu_level: 1,
                                    href:       loRs("url").Value,
                                    visits:     loRs("visits").Value || 0
                                });
            }
            else
            {
                if (!grp.Koppen.length)
                {   // Deze eerste is geen kop; verzin er zelf eentje bij.
                    var fav = orggroep == MENU.FAV || orggroep == MENU.TAB || orggroep == MENU.WGT_PAGE;
                    var kop_label = fav ? L("lcl_current_fav") : "...";
                    var image = fav ? "fa-star" : "fa-minus";
                    grp.Koppen.push({   Items:      [],
                                        label:      kop_label,
                                        startopen:  true,
                                        info:       null,
                                        image:      image, // null,
                                        href:       null
                                    });
                }
                var kop = grp.Koppen[grp.Koppen.length-1];
                var url = loRs("url").Value;
                if (kop.Items.length && url && kop.Items[kop.Items.length-1].href == url && kop.Items[kop.Items.length-1].name == loRs("label").Value)
                {
                    // skip it
                }
                else
                {
                    var xurl = "";
                    var filters = loRs("filter").Value;
                    var advfilter = loRs("advfilter").Value;
                    if (url)
                    {
                        url = url.replace(/\?$/, "");
                        url = url.replace(/\&$/, "");
                        xurl = url;
                        if (url && (filters || advfilter))
                            xurl += (url.indexOf("?") > -1 ? "&" : "?") + "has_filters=1&tab_menu_key=" + loRs("fac_menu_key").Value;
                    }
                    kop.Items.push({    name:       mlabel,
                                        href:       xurl,
                                        info:       loRs("fac_menu_info").Value,
                                        infomsg:    loRs("fac_menu_message").Value,
                                        depth:      loRs("depth").Value,
                                        img:        loRs("image").Value,
                                        menu_key:   loRs("fac_menu_key").Value,
                                        menu_level: loRs("fac_menu_level").Value,
                                        group:      groepnr,
                                        orggroep:   orggroep,
                                        visits:     loRs("visits").Value || 0
                                    });
                }
            }
        }
        else // if (mode == 2 || mode == 3) // Mobile || App
        {
            var mlabel = fac.localstring(loRs("label").Value);
            var murl = loRs("url").Value;

            // merge MENU.MOB items with MENU.APP items in case of building the app menu
            if (mode == 3 && groepnr == MENU.MOB) // mode == 3 = Mobile + App
                groepnr = MENU.APP; // use mobile app-group for app specific menu items

            // Alleen de eerste keer een groep aanmaken voor mobile/app menu.
            if (!Groepen[groepnr])
                Groepen[groepnr] = {Koppen: []};

            var grp = Groepen[groepnr];

            // Voor elk record een kop en item aanmaken
            if (grp.Koppen.length && murl && grp.Koppen[grp.Koppen.length-1].Items[0].href == murl)
            {
                // skip it
            }
            else
            {
                grp.Koppen.push({   Items: [],
                                    label: mlabel
                                });
                var kop = grp.Koppen[grp.Koppen.length-1];
                kop.Items.push({    name:       mlabel,
                                    info:       loRs("fac_menu_info").Value,
                                    href:       murl,
                                    img:        loRs("image").Value,
                                    menu_key:   loRs("fac_menu_key").Value,
                                    menu_level: loRs("fac_menu_level").Value,
                                    group:      groepnr,
                                    orggroep:   orggroep,
                                    visits:     loRs("visits").Value || 0
                                });
            }
        }
        loRs.MoveNext();
    }
    loRs.close();

    // In 'traditional desktop'-mode printen we geen tabjes onder de favorieten kop
    // Als die kop dus alleen tabjes bevat, dan mag die hele kop weg
    if (params.pmode && params.pmode === 1 &&
        (MENU.PERS in Groepen) &&
        Groepen[MENU.PERS].Koppen.length &&
        Groepen[MENU.PERS].Koppen[0].label === L("lcl_current_fav")) {
        var delFav = true;
        for (var item in Groepen[MENU.PERS].Koppen[0].Items) {
            delFav = Groepen[MENU.PERS].Koppen[0].Items[item].orggroep === 5; // Als alles gepinde tabjes zijn, dan mag de kop weg
            if (!delFav) {
                break;
            }
        }
        if (delFav) {
            Groepen[MENU.PERS].Koppen.splice(0, 1);
        }
    }

    // Loopje om lege Groepen/Koppen te verwijderen
    for (var grp in Groepen)
    {
        for (var kop = 0; kop < Groepen[grp].Koppen.length; kop++)
        {
            if (!Groepen[grp].Koppen[kop].Items.length && !Groepen[grp].Koppen[kop].href)
            {
                Groepen[grp].Koppen.splice(kop, 1);
                kop --;
            }
        }
    }

    // Sorteer op populariteit
    if ((groepnr in Groepen) && (mode == 2 || mode == 3) && statLevel) {
        var groupedKoppen = [];
        var j = -1;
        for (var i = 0; i < Groepen[groepnr].Koppen.length; i++) {  // 1 Array per hoofd-menu-item (mogelijk dus incl. submenu-items)
            if (Groepen[groepnr].Koppen[i].Items[0].menu_level == 1) {
                j++;
                groupedKoppen[j] = [];
            }
            if (j >= 0) {
                groupedKoppen[j].push(Groepen[groepnr].Koppen[i]);
            }
        }
        groupedKoppen.sort(function (a, b) {    // Sorteer de hoofdmenu-items op het aantal bezoeken (DESC)
            return b[0].Items[0].visits - a[0].Items[0].visits;
        });
        Groepen[groepnr].Koppen = [].concat.apply([], groupedKoppen);
    }

    return Groepen;
}

// Genereer het menu volgens mode pmode
// 1 = traditional
// 2 = tablet like
// 3 = portal style ("loket")
// 4 = mobile style
// 5 = app style

// Additionele parameters;
// menukop_key: Toon het submenu onder deze menukop_key
// groep:       Alleen voor pmode == 3, toon alleen deze menu-groep
function generateMenu (pmode, params) // Groep alleen voor mode 3
{
    params = params || {};
    params.result = { "success": true };
    if (pmode == 1)
    {
        params.pmode = pmode;
        var menuitems = fillMenuArray(0, params);
        if (menuitems)
        {
            var menuTitleLength = 0;
            var menuTitleString = "";

            if ((menuitems[MENU.PERS] && menuitems[MENU.PERS].Koppen.length > 0) || (menuitems[MENU.FAV] && menuitems[MENU.FAV].Koppen.length > 0))
            {
                menuTitleLength++;
                menuTitleString += '<li><a href="#PersFAC"><span class="menutab">' + L("lcl_menu_pers") + '</span></a></li>';
            }
            if ((menuitems[MENU.PROF] && menuitems[MENU.PROF].Koppen.length > 0))
            {
                menuTitleLength++;
                menuTitleString += '<li><a href="#ProfFAC"><span class="menutab">' + L("lcl_menu_prof") + '</span></a></li>';
            }
            if ((menuitems[MENU.MGT] && menuitems[MENU.MGT].Koppen.length > 0))
            {
                menuTitleLength++;
                menuTitleString += '<li><a href="#MgtFAC"><span class="menutab">' + L("lcl_menu_config") + '</span></a></li>';
            }

            var disp = menuTitleLength == 1 ? " noToggle\" style=\"display:none" : "";
            // ui-helper-clearfix wordt er straks door jQuery opgezet bij $("#menutabs").tabs();
            // CONN#19264 Door het alvast zelf te doen wordt een reproduceerbare crash voorkomen!
%>
            <ul class="ui-tabs-nav ui-helper-clearfix<%=disp%>"><%
                Response.write(menuTitleString);
%>          </ul>
            <div class="menuHeadSpacer">&nbsp;</div>
            <div class="ui-layout-content">
<%
            if ((menuitems[MENU.PERS] && menuitems[MENU.PERS].Koppen.length > 0))
            {   %>
                <div id="PersFAC" class="ui-tabs-panel ui-tabs-hide">
                    <div class='filtermenukop'><%=L("lcl_menu_pers")%></div>
<%                  CreateMenuGroep(menuitems[MENU.PERS].Koppen, pmode);  // Zelfservice
%>              </div><%
            }
            if ((menuitems[MENU.PROF] && menuitems[MENU.PROF].Koppen.length > 0))
            {   %>
                <div id="ProfFAC" class="ui-tabs-panel">
                    <div class='filtermenukop'><%=L("lcl_menu_prof")%></div>
<%                  CreateMenuGroep(menuitems[MENU.PROF].Koppen, pmode);
%>              </div><%
            }
            if ((menuitems[MENU.MGT] && menuitems[MENU.MGT].Koppen.length > 0))
            {   %>
                <div id="MgtFAC" class="ui-tabs-panel ui-tabs-hide">
                    <div class='filtermenukop'><%=L("lcl_menu_config")%></div>
<%                  CreateMenuGroep(menuitems[MENU.MGT].Koppen, pmode);
%>              </div><%
            }   %>
            </div>
            <input id="menufilter" type="text" placeholder="<%=L("lcl_menufilter")%>">
<%      }
    }
    if (pmode == 2)
    {
        var menuitems = fillMenuArray(0, params);
        if (menuitems)
        {
            if (S("widgetportal") > 0)
                var firstPage = "fac_widget_page.asp?touch=1&fp=1&wgt_page_key=" + S("widgetportal");
            else
                var firstPage = "myfacilitor.asp?touch=1";

%>          <ul class="ui-tabs-nav ui-helper-clearfix">
                <li><a href="#tabletmenu"><span class="menutab"><%=L("lcl_body_portal")%></span></a></li>
<%          if (menuitems[MENU.PERS] && menuitems[MENU.PERS].Koppen.length > 0)
            {   %>
                <li><a href="#tPersFAC"><span class="menutab"><%=L("lcl_menu_pers")%></span></a></li>
<%          }
            if (menuitems[MENU.PROF] && menuitems[MENU.PROF].Koppen.length > 0)
            {   %>
                <li><a href="#tProfFAC"><span class="menutab"><%=L("lcl_menu_prof")%></span></a></li>
<%          }
            if (menuitems[MENU.MGT] && menuitems[MENU.MGT].Koppen.length > 0)
            {   %>
                <li><a href="#tMgtFAC"><span class="menutab"><%=L("lcl_menu_config")%></span></a></li>
<%          }   %>
            </ul>
            <div class="ui-layout-content">
                <div id="tabletmenu">
                    <script>
                        function gototab(t)
                        {
                            $("[href='"+t+"']").trigger("click");
                        }
                    </script>
                    <iframe src="<%=firstPage%>" id="myactionsframe" name="myactionsframe" autorefresh="1"
                        width="100%" marginwidth="0" marginheight="0" frameborder="0" scrolling="auto" onload="FcltMgr.iframeLoaded(this)">
                    </iframe>
                </div>
<%          if (menuitems[MENU.PERS] && menuitems[MENU.PERS].Koppen.length > 0)
            {   %>
                <div id="tPersFAC">
                    <div id="portalmenu">
<%                      generatePortalmenu(menuitems[MENU.PERS].Koppen); %>
                    </div>
                </div>
<%          }
            if (menuitems[MENU.PROF] && menuitems[MENU.PROF].Koppen.length > 0)
            {   %>
                <div id="tProfFAC">
                    <div id="portalmenu">
<%                      generatePortalmenu(menuitems[MENU.PROF].Koppen); %>
                    </div>
                </div>
<%          }
            if (menuitems[MENU.MGT] && menuitems[MENU.MGT].Koppen.length > 0)
            {   %>
                <div id="tMgtFAC">
                    <div id="portalmenu">
<%                      generatePortalmenu(menuitems[MENU.MGT].Koppen); %>
                    </div>
                </div>
            </div>
<%          }
        }
    }
    if (pmode == 3)
    {
        params.portalOnly = true;
        var menuitems = fillMenuArray(0, params);
        if (menuitems && menuitems[params.groep] && menuitems[params.groep].Koppen)
        {   %>
            <div id="portalmenu">
                <h2><%=L("lcl_facilitor_portalwelcome"+params.groep)%></h2>
<%              generatePortalmenu(menuitems[params.groep].Koppen); %>
            </div>
<%      }
    }
    if (pmode == 4 || pmode == 5)
    {
        var menuitems = (pmode == 4 ? fillMenuArray(2, params) : fillMenuArray(3, params)); // Mobile : App
        var menugroep = (pmode == 4 ? MENU.MOB : MENU.APP);
        var kop = [];
        if (menuitems && menuitems[menugroep])
            kop = menuitems[menugroep].Koppen;
        var ITEMS_PER_ROW = 4;

        var _hasSubmenuItem = function (index) {
            if (kop.length > index + 1 &&                                           // Ik ben niet het laatste item
                kop[index].Items[0].menu_level < kop[index+1].Items[0].menu_level)  // Mijn niveau is hierarchisch hoger dan het volgende item
            {
                if (kop[index+1].Items[0].href &&                                           // Het volgende item heeft een url
                    kop[index].Items[0].menu_level == kop[index+1].Items[0].menu_level - 1) // Het volgende item is van 1 hierarchisch menu-niveau lager dan de mijne
                    return 1
                else
                    return _hasSubmenuItem(index+1);
            }
            else
                return 0;
        }

        var inSubmenu = false;

        var menuHtml = "<div class='icon-grid container-fluid'>";
        var colcnt = 0;

        for (var i = 0; i < kop.length; i++)
        {
            itm = kop[i].Items[0];
            if (params.menukop_key > 0)
            {
                if (itm.menu_key == params.menukop_key)
                {
                    inSubmenu = true;
                    continue; // volgende in de loop
                }
                else
                {
                    if (!inSubmenu)
                        continue;
                }
                if (inSubmenu && itm.menu_level != 2) {
                    break; // we zijn klaar met dit menu
                }
            }

            if (!inSubmenu && itm.menu_level == 2)
                continue; // Overslaan, volgende in de loop

            if (!itm.href && _hasSubmenuItem(i))
            {
                itm.href = "appl/pda/menu.asp?menukop_key=" + itm.menu_key;
                itm.hasSubmenu = true;
                // Ooit TODO: 100 punten zou zijn als je hier de iconen van de submenu
                // items verzamelt en in 3x3 gridje toont
            }
            if (itm.href)
            {
                var protocol = itm.href.split(":");
                if (protocol.length < 2 || !protocol[0].match(/^(http|https|mailto|tel|qr)$/))
                {   // Gewone interne optie krijgt rooturl ervoor
                    if (itm.href.match(/[\?\\\/:]/g) === null) { // Als het een geupload bestand is, is er nog een (map-)prefix nodig
                        itm.href = HTTP.urlzelfnoroot() + S("menu_image_url_path") + itm.href;
                    }
                    else
                    {
                        itm.href = rooturl + "/" + itm.href;
                        if (itm.menu_key > 0)
                        {
                            itm.href += itm.href.indexOf("?") > -1?"&":"?";
                            itm.href += "from_menu_key=" + itm.menu_key;
                        }
                    }
                }
            }
            else
            {   // Overslaan, ik ben een menuitem zonder url en zonder submenu-items
                // Dit kan een inrichtingsfout zijn, maar logischer is dat het op rechtenbasis submenu-items heeft uitgesloten van weergave.
                continue;
            }

            if (colcnt % ITEMS_PER_ROW === 0) {
                menuHtml += "<div class='row"
                          + (colcnt == 0 ? "" : " closed") // Alleen de eerste rij default tonen
                          + "'>";
            }

            menuHtml += "<a class='col-" + (12 / ITEMS_PER_ROW) + " menu-item tappable" + (itm.hasSubmenu ? " has-submenu" : "") + "' href='" + safe.htmlattr(itm.href) + "'>"
                      + "  <div class='menu-icon tappable-target'>"
                      +      SYMBOL(itm.img, { "module": "MENU" })
                      + "  </div>"
                      + "  <div class='menu-caption limit-lines-2'>" + safe.html(itm.name) + "</div>"
                      + "</a>";
            colcnt++;

            if (colcnt % ITEMS_PER_ROW === 0 || i === kop.length - 1) {
                menuHtml += "</div>";
            }

            if (!(params.menukop_key > 0) && ITEMS_PER_ROW == colcnt) {
                // break;
            }
        }   // End for-loop
        menuHtml += "</div>";

        if ((params.layout || "card") == "card") { // Default 'card'
            var cardParams = {};
            var hasMore = colcnt >= ITEMS_PER_ROW;
            if (!(params.menukop_key > 0)) {
                cardParams.title = user_time_based_greeting() + " " + user.naam();
            }
            menuHtml = CARD_START_HTML(cardParams)
                     + menuHtml
                     + CARD_END_HTML({ "more": hasMore });
        }

        Response.Write(menuHtml);
    }
    return params.result;
}
%>