/*
    $Revision$
    $Id$

    File:           FcltMgr.js

    Description:    FcltMgr is de manager van Facilitor die voornamelijk twee containers biedt
                    A) Een menu container
                    B) Een functie container (de tabjes rechts)
*/

function L(lcl)
{
    return FcltMgr.L(lcl);
}

var FcltMgr =
    {
        _pageManager: null, // defaultManager of tabbedManager
        globalData: [],
        reload: function (params)
        {
            params = params || "";
            // met (door jquery tabs toegevoegd) fragment identifier werkt onderstaande anders niet
            var hrefBase = window.location.href.split( "#" )[ 0 ];
			// nooit collapsed herladen?
            hrefBase = hrefBase.replace(/&collapsed=1/gi, "");
            if (hrefBase.indexOf("no_autoscroll") == -1)
                hrefBase = hrefBase + (hrefBase.indexOf("?")>0?"&":"?") + "no_autoscroll=1";
            if (params.appendurl)
            {
                var nm = params.appendurl.split("=")[0];
                if (hrefBase.indexOf("&" + nm + "=") > 0)
                    hrefBase = hrefBase.substr(0, hrefBase.indexOf("&" + nm + "="));
                hrefBase += "&" + params.appendurl;
            }
            // Vervang een eventuele hamburger door een spinner
            $("li#printhamburger i.fa.fa-fw.fa-bars").attr("class", "fa fa-fw fa-refresh fa-spin fa-2x");
            window.location.href = hrefBase;
        },
        defaultManager :
        {
            name: "defaultManager",
            openDetail: function(url, titel, params)
            {
                params = params || {};
                titel = titel || "";
                if (url.indexOf("hmac=") < 0)
                {
                    url += (url.indexOf("?")<0)?"?":"&";
                    url += "_titel_=" + escape(titel);
                }
                if (params.forcedeep)
                    window.open("../../?JumpTo=" + escape(params.orgurl));
                else
                    window.open(url);
//                FcltMgr.resized(window, params);
            },

            closeDetail: function(thiswindow, params)
            {
                window.close();
            },

            setTitle: function (title, params)
            {
                if (title)
                    window.document.title = title;
            }
        },

        tabbedManager :
        {
            name: "tabbedManager",
            _counter: 0,

            openDetail: function(url, titel, params)
            {
                FcltMgr._pageManager._openTab(url, titel, params);
            },
            closeDetail: function(thiswindow, params)
            {
                var active = this._$tabshost.tabs('option', 'active');
                var tab = $(this._$tabshost.find( ".ui-tabs-nav li" )[active]);
                FcltMgr._pageManager._closeTab(tab);

                return;
            },
            setTitle: function (title, params)
            {
                var orgtitle = null;
                if (title && title.length > 25)
                {
                    orgtitle = title;
                    title = title.substr(0, 20) + "...";
                }
                // FcltMgr heeft voor ons params al met windowname gevuld.
                params = params || {};
                var tab = this._$tabshost.find( ".ui-tabs-nav li[aria-controls='"+params.windowname+"']" );
                var waspinned = $(tab).find("span.tabpinned").length > 0;
                if (!waspinned)
                {
                    if (title)
                        tab.find("span:first").text(title);
                    if (orgtitle)
                        tab.find("span:first").attr('title', orgtitle);
                }
                if (params.hot)
                {
                    tab.find(".tabclose").addClass('hot');
                }
                else
                {
                    tab.find(".tabclose").removeClass('hot');
                }
                // De originele waarde van titel alleen aanpassen als deze "Loading..." is.
                var ttl_span = tab.find("span:first");
                if (ttl_span.attr("ttl") == L("lcl_shared_loading"))
                    ttl_span.attr("ttl", orgtitle||title);
            },

            // Sluit alle tabbladen behalve de huidige en behalve _editactive
            closeAll: function (zelf)
            {
                var active = this._$tabshost.tabs('option', 'active');
                $(".ui-tabs-nav li", this._$tabshost).each(function(i,j)
                {
                    if (i > 0 && i != active && !FcltMgr._pageManager._panelHot(this))
                    {
                        FcltMgr._pageManager._closeTab(this, { noRefresh: true });
                    }
                });
                this._$tabshost.tabs( "refresh" ); // Allemaal tegelijk is veel sneller in IE8
            },

            // 'Pin' het huidige tabje of geef deze juist vrij
            fnDoSave: function (ttl, data)
            {
                data.autoopenttl = ttl;
                protectRequest.dataToken(data);
                $.post(rooturl + "/appl/fac/fac_current_tab_save.asp",
                      data,
                      FcltCallbackAndThen(function (returndata)
                      {
                        if (returndata.saved)
                        {
                            if (data.taboption == "T")
                            {
                                var html = "<span title='"+L("lcl_current_tab_unsave")+"' class='tabpinned' onclick='FcltMgr.saveTab(this);'>&nbsp;<i class='fa fa-thumb-tack'></i></span>";
                                $(data.tab).find("span:first").text(ttl);
                                $(data.tab).find(".tabclose").before($(html));
                            }
                        }
                        else
                        {
                            if (data.taboption == "T")
                                $(data.tab).find(".tabpinned").remove();
                        }
                      }),
                      "json");
            },
            saveTab: function (zelf)
            {
                if (zelf)
                {
                    var li = $(zelf).parents('li:eq(0)')[0];
                    var active = $('li', this._$tabshost).index(li);
                }
                else
                {
                    var active = this._$tabshost.tabs('option', 'active');
                    if (active == 0 || FcltMgr._pageManager._panelHot(active))
                    {
                        FcltMgr.alert(L("lcl_tabs_nosave"));
                        return;
                    }
                }

                var tab = $(this._$tabshost.find( ".ui-tabs-nav li" )[active]);
                var a = $(tab).find("a");
                if (a.length)
                {
                    var href = $( a ).attr( "href" );
                    var ttl = $( a ).find("span:first").attr("ttl");
                    if (href.indexOf("#" > 0))
                       href = "#" + href.split("#")[1];
                    var panel = $(href);
                    // hmac beschermde pagina's zijn toch al heel snel invalid. Silent ignore.
                    if (panel.length &&
                        !panel[0].getAttribute("is_extern")) // externen is ook te complex
                    {
                        var url = panel[0].getAttribute("reusesrc");

                        var frm = window.frames[panel[0].id];
                        var filters = null;
                        if (FcltMgr._frmaccessible(frm))
                        {
                            url = frm.location.href; // bij een *net* aangemaakte melding is deze anders
                            if (frm.iface && frm.$("form[name=u2]").length)
                            {
                                filters = frm.iface.formToString(frm.$("form[name=u2]"));
                            }
                        }

                        if (url.indexOf("&fcltfilters=") > 0)
                            url = url.substr(0, url.indexOf("&fcltfilters="));
                        var data =
                            { autoopenurl: url,
                              filters: filters,
                              tab: tab
                            }
                        var waspinned = $(tab).find("span.tabpinned").length > 0;
                        if (waspinned)
                        {
                            data.filters = frm.fcltfilters; // deze moet je vrijgeven
                            data.taboption = "T"; // alleen tab wordt hier unpinned
                            FcltMgr._pageManager.fnDoSave(ttl, data); // Vrijgeven geen Prompt
                        }
                        else
                        {
                            if ( panel[0].getAttribute("reusesrc").indexOf("&hmac=") < 0)
                            {
                                data.textoptionT = L("lcl_current_tab_totab");
                                data.textoptionM = L("lcl_current_tab_tomenu");
                                fcltPrompt(L("lcl_current_tab"), ttl, FcltMgr._pageManager.fnDoSave, { data: data, required: true });
                            }
                            else
                            {
                                FcltMgr.alert(L("lcl_tabs_nosave"));
                            }
                        }
                    }
                    else
                    {
                        FcltMgr.alert(L("lcl_tabs_nosave"));
                    }
                }
            },

            init: function (tabs_id)
            {
                this._tabshost = tabs_id;
                this._$tabshost = $("#"+tabs_id);

                var $tabs = this._$tabshost.tabs(
                    {
                        beforeActivate: function(event, ui)
                        {
                            // Activeer de delay-loaded tabjes
                            var newP = ui.newPanel; // zal een iframe zijn
                            if (newP.length &&
                                newP[0].getAttribute('src').match(/empty.html$/) &&
                                newP[0].getAttribute('reusesrc'))
                            {
                                newP[0].setAttribute('src', newP[0].getAttribute('reusesrc'));
                            }
                            var ofrm = ui.oldPanel;
                            if (ofrm.length)
                            {
                                var frm = window.frames[ofrm[0].id];
                                if (FcltMgr._frmaccessible(frm))
                                    frm.wasScroll = $(frm).scrollTop(); // IE11/Win8 onthoudt dit erg slecht
                            }
                        },
                        activate: function(event, ui)
                        {
                            var ofrm = ui.oldPanel;
                            if (ofrm.length)
                            {
                                var frm = window.frames[ofrm[0].id];
                                if (FcltMgr._frmaccessible(frm) && frm.fcltontabhide)
                                {
                                    frm.fcltontabhide();
                                }
                            }
                            var ifrm = ui.newPanel;
                            if (ifrm.length)
                            {
                                var frm = window.frames[ifrm[0].id];
                                if (FcltMgr._frmaccessible(frm))
                                {
                                    $(frm).scrollTop(frm.wasScroll);
                                    var isHot = FcltMgr._pageManager._panelHot(ui.newTab);
                                    if (frm.fcltontabshow)
                                    {
                                        frm.fcltontabshow(isHot);
                                    }
                                    // Als door 'autoopen' veel tabjes tegelijk zijn geladen
                                    // dan is de iframeLoaded niet goed afgegaan. Doe dat alsnog.
                                    // AARW#37918 2016.3 speelt dit nog steeds met Edge 38.14393.0.0
                                    //  bij veel tab-wisselen
                                    $("iframe" ,frm.document).each(function()
                                        {
                                            if ($(this).height() == 0)
                                                FcltMgr.iframeLoaded(this);
                                            // Dialogen hadden de neiging te verdwijnen.
                                            // Zo (b)lijken ze terug te halen
                                            if ($(this).hasClass("fcltmodal"))
                                            {
                                                frm.$(this).dialog('widget').show();
                                                frm.FcltMgr._resizeModal(this);
                                            }
                                        })
                                }
                              	FcltMgr._pageManager._timedResizeActiveTab();
                            }
                        }
                    });
                $tabs.find( ".ui-tabs-nav" ).sortable({
                    items: "li:not([aria-controls='ID1'])", // Eerste tab ('mijn Facilitor') niet verplaatsen
                    axis: "x",
                    distance: 25,
                    stop: function() {
                        $tabs.tabs( "refresh" );
                    }
                });


                this._$tabshost.resize(function (){
                    	FcltMgr._pageManager._timedResizeActiveTab();
                    });

            },

            // Internal to tabbedManager
            _tabshost: null,
            _$tabshost: null,

            // Open een nieuwe tab 'url' in een iframe en 'Titel' als label
            _openTab: function (url, titel, params)
            {
                params = params || {};

                var openerId = '';
                var prev_active = this._$tabshost.tabs('option', 'active');
                var xx = $('a', this._$tabshost)[prev_active];
                if (xx)
                    openerId = xx.id;

                if (params.reuse) // try to find previous tab
                {
                    var found = -1;
                    var thePanel;
                    var nohmac = url;
                    if (nohmac.indexOf("&hmac=") > 0)
                        nohmac = nohmac.substr(0, url.indexOf("&hmac="))
                    $('a', this._$tabshost).each(function(i,j)
                    {
                       var href = $( this ).attr( "href" );
                       if (href.indexOf("#" > 0))
                          href = "#" + href.split("#")[1];
                       var panel = $(href);
                       var nohmac2 = panel[0].getAttribute("reusesrc");
                       if (nohmac2.indexOf("&hmac=") > 0)
                           nohmac2 = nohmac2.substr(0, nohmac2.indexOf("&hmac="))
                       if (panel.length && nohmac == nohmac2)
                       {
                           found = i;
                           thePanel = panel;
                       }
                    });
                    if (found >= 0)
                    {
                        this._$tabshost.tabs('option', 'active', found);
                        if (!FcltMgr._pageManager._panelHot(found)) // niet als hot
                        {
                            thePanel[0].src = url; // Wel de nieuwe url met nieuwste hmac gebruiken
                        }
                        return;
                    }
                }

                this._counter++;
                var theId = "ID"+this._counter;
                titel = titel ||L("lcl_shared_loading");
                var org_titel = titel;
                var telang = false;
                if (titel.length > 25)
                {
                    titel = titel.substr(0, 20);
                    telang = true;
                }
                // Titel HTML safe maken
                var newDiv = document.createElement("div"); // wordt wel door Garbage Collect opgeruimd.
              	if (typeof newDiv.innerText != 'undefined')
	                newDiv.innerText = titel
	              else
		              newDiv.textContent = titel;
                titel = newDiv.innerHTML;
                if (telang)
                     titel += "&hellip;";
                var tpl = "<li openerId='" + openerId + "'><a href='#" + theId + "'><span ttl='" +org_titel+ "'>" +titel + "</span>"
                        + (params.showpin?"<span title='"+L("lcl_current_tab_unsave")+"' class='tabpinned' onclick='FcltMgr.saveTab(this)'>&nbsp;<i class='fa fa-thumb-tack'></i></span>":"")
                        + (params.noclose?"":"<span class='tabclose' onclick='FcltMgr._pageManager._closeTab(this)'>&nbsp;X</span>")
                        + "</a></li>"

                // In eerste instantie met registreren we alleen reusesrc
                // In de beforeActivate nemen we die (pas) over naar src
                var startSrc = url;
                if (params.delayload)
                    var startSrc = "../../appl/shared/empty.html"; // Anders doet IE11 moeilijk 'permission denied'
                var panel = "<iframe frameborder='0'"
                                + " id='"+theId+"' name='"+theId
                                + "' src='"+startSrc
                                + "' reusesrc='"+url
                                + (params.is_extern?"' is_extern='1":"")
                                + "' class='frametab'></iframe>";
                this._$tabshost.find( ".ui-tabs-nav" ).append( tpl );
                this._$tabshost.append( panel );
                this._$tabshost.tabs( "refresh" );
                if (!params.noactivate)
                    this._$tabshost.tabs('option', 'active', -1); //  de laatste
            },

            _panelHot: function(tab) // tab mag een 'li' zijn of een index
            {
                if (typeof tab == "number")
                    var tab = this._$tabshost.find( ".ui-tabs-nav li" )[tab];
                if (!tab) // Tijdelijke patch AAIT#29057
                    return false;
                var panelId = $( tab ).attr( "aria-controls" );
                var frm0 = window.frames[panelId];
                if (!FcltMgr._frmaccessible(frm0))// neem aan: access denied kennisbank/externe pdf
                    return false;
                var frm = frm0.window;
                if (!FcltMgr._frmaccessible(frm))// neem aan: access denied by punchout
                    return false;

                return (frm.FcltMgr &&
                        frm.FcltMgr._editactive)
            },

            // Sluit een tabblad met het kruisje.
            _closeTab: function (zelf, params)
            {
                params = params || {};
                var li = $(zelf).closest('li')[0];
                // Opzoeken voordat hij verwijderd is
                var idx = $('li', this._$tabshost).index(li);
                var isCurrent = (idx == this._$tabshost.tabs('option', 'active'));

                var hotwnd = FcltMgr._pageManager._panelHot(li);
                if (hotwnd)
                {
                    if (!confirm(L("lcl_shared_closeandignore")))
                    {
                        // Alleen unlocken als we zelf het lock hadden
                        return false;
                    }
                    else
                    {
                        if (hotwnd.onCloseHot)
                            hotwnd.onCloseHot();
                    }
                }
                var openerId = $( li ).attr("openerId");
                var panelId = $( li ).remove().attr( "aria-controls" );
                FcltMgr._removeIframe($( "#" + panelId ));

                if (!params.noRefresh)
                {   // Probeer de 'opener' tab te activeren als je zelf actief bent
                    if (isCurrent)
                    {
                        var prevLi = $("a#" + openerId, this._$tabshost);
                        if (prevLi.length)
                        {
                            var idx = $('a', this._$tabshost).index(prevLi[0]);
                            if (idx > -1)
                                this._$tabshost.tabs('option', 'active', idx);
                        }
                    }

                    this._$tabshost.tabs( "refresh" );
                }

                return;
            },

            _timerID : null,

            _timedResizeActiveTab: function ()
            {
            	if (this._timerID) clearTimeout(this._timerID);
                this._timerID = setTimeout(this._resizeActiveTab, 100);
            },

            _resizeTab: function (ifrm)
            {
                var tabsHeaderHeight = ($(".ui-tabs-nav", FcltMgr._pageManager._$tabshost).height());
                var newHeight = $(window).height() - ($("#frheader").is(":visible")?$("#frheader").height():0) - 8.27 - tabsHeaderHeight - 3;
                // var newHeight = $("#maintabs").height()- tabsHeaderHeight - 3;
                $(ifrm).height(newHeight);
                // doet de 100% css wel $(ifrm).width(newWidth);
            },

            _resizeActiveTab: function ()
            {
                var ifrm = FcltMgr._pageManager._activeTab();
                // PF: constateerde dat via een tragere lijn (vpn) ifrm er niet op tijd kan zijn
                if (ifrm)
                    FcltMgr._pageManager._resizeTab(ifrm);
            },
            // levert het IFRAME object van de actieve tab op.
            _activeTab: function ()
            {
                var active = FcltMgr._pageManager._$tabshost.tabs('option', 'active');
                var tab = FcltMgr._pageManager._$tabshost.find( ".ui-tabs-nav li" )[active];
                var panelId = $( tab ).attr( "aria-controls" );
                var ifrm = $("#" + panelId)[0];
                return ifrm;
            }
        }, /*** EINDE TABBED MANAGER ***/

        _caller: null,

        _doRemove: function (frmid)
        {
            var $frm = $("#" + frmid);
            $frm.attr('onload', null); // hoeft niet voor empty en bovendien pakte hij wel eens het verkeerde frame
            $frm.attr('src', rooturl + "/appl/shared/empty.html"); // lijkt geheugenlek IE9 te voorkomen
            $frm.remove(); /* RWSN#26802: crasht IE8 uiteindelijk te veel
                              UWVA#32572: Toch weer teruggezet, als het probleem van RWSN#26802 zich nog steeds voordoet,
                                (ik kan het momenteel niet reproduceren) dan moet dat anders worden opgelost.
                                Dit weglaten zorgt voor meer problemen.
                                */
        },

        // De timeout vooromt vreemde IE9 problemen waarbij iface.button.enable klaagt dat iface niet bestaat.
        // of Date dan wel String is undefined. Dit gebeurt als je in een (Ajax) callback een closeDetail doet
        // (bijvoorbeeld opslaan res_edit_multi.asp). Na de Ajax onComplete wil jQuery nog wat opruimwerk doen
        // maar plotseling is de frame met code verdwenen.
        // Verder: de nieuwe Id om te voorkomen dat de verkeerde *volgende* dialoog gesloten worden! (opdr_close==>mld_close)
        _removeIframe: function($frm)
        {
            // Pas op: geen '.' in de newid want dan vindt _doRemove hem niet meer terug!
            var newid = "DELETE" + (new Date).getTime() + Math.floor(10000000*Math.random());
            $frm.css("display", "none");
            $frm.attr("id", newid).attr("name", newid);
            setTimeout("FcltMgr._doRemove('" + newid + "')", 1100);
        },

        // De allerhoogste te vinden manager
        topmanager: function ()
        {
            try
            {
                if (parent && parent.FcltMgr && parent.FcltMgr!=this)
                    return parent.FcltMgr.topmanager();
            }
            catch(e)
            { /* FACILITOR in een frame */};
            return this;
        },

        // Bij de tabbedManaher de hoogste FcltMgr nog net binnen het detail scherm
        // Bij de defaultManager gewoon de hoogste
        detailManager: function ()
        {
            if (FcltMgr.IsTheManager)
                return FcltMgr;
            if (FcltMgr._pageManager.name != "defaultManager" && parent.FcltMgr.IsTheManager)
                return FcltMgr;
            else
                return parent.FcltMgr.detailManager();
        },

        HostTabs: function(tabs_id) // tabs_id moet id van jQuery tabs object zijn
        {
            this._pageManager = this.tabbedManager;
            this._pageManager.init(tabs_id);
        },

        // Open een detailscherm (bijvoorbeeld vanuit een overzicht scherm)
        // Als dit vanuit een tab gebeurt dan wordt een nieuwe tab geopend,
        // anders een nieuw window
        // titel parameter mag weggelaten. Voorkeur is params.title zetten!
        openDetail: function(url, titel, params)
        {
     	  // Als titel een object is is het eigenlijk params
		    if ( typeof titel === "object" ) {
			      params = titel;
			      titel = params.titel;
		    }
            params = params || {};
            params.orgurl = url;
            titel = titel || "";
            // Vanuit het menu zitten er nog wel eens \n of spaties omheen. Opruimen
            titel = titel.replace(/\n/ig, " ");
            titel = titel.replace(/^\s+|\s+$/g,"");

            if (url[0]=="*")
                return FcltMgr.defaultManager.openDetail(url.substring(1), titel, params);

            if (url.slice(0,4) != "http")  // intern
            {
                if (url.slice(0,1) == '/')
                    url = url.substr(1);
                if ("rooturl" in window)
                    url = rooturl + "/" + url;
                else
                    url = "../../" + url;
            }

            FcltMgr._pageManager.openDetail(url, titel, params);
        },

        // Als via kruisje gesloten. Geen callback's en dergelijke
        _closeParams: null,
        setCloseParams: function (params) // Handig in combi met alwaysCallback
        {
            parent.FcltMgr._closeParams = params;
        },
        dialogClose: function (result)
        {
            $("div.suggestautocompleteContainer").hide();
            var orgParams = FcltMgr._modalParams[FcltMgr._modalCount];
            if (orgParams.alwaysCallback)
            {
                var params = FcltMgr._closeParams || orgParams.alwaysCallbackParams || {};
                params.cancel = true;
                FcltMgr._modalCallback[FcltMgr._modalCount](params, orgParams);
            }

            var $frm = $("iframe#fcltmodal" + FcltMgr._modalCount);
            FcltMgr._removeIframe($frm);
            FcltMgr._modalCount--;
        },

        // Open een Modaal popup detailscherm (bijvoorbeeld vanuit een overzicht scherm)
        // Voor schermen waarvan openDetail te veel eer is.
        // params ondersteunt:
        //  height, width in px;
        //  callback(data) aangeroepen door client dialoog's FcltMgr.CloseDetail(window, data)
        //  params die worden doorgegeven aan de dialoog.
        //      Die kan ze met FcltMgr.dialogArguments() ophalen (let op: clientside!)
        _modalCount: 0,
        _modalCallback: [],
        _modalParams: [],

        _resizeModal: function(frm)
        {
            try
            {
                var frmcontent = $(frm).contents(); // testing
            }
            catch (e)
            {
                // FcltMgr.alert("Bad resizing");
                return; // IE9 soms als dialoog net gesloten is
            }
            // Hoeveel extra moeten we rekenen voor jQuery dialog
            var dialogborderHeight = $(frm).closest(".ui-dialog").outerHeight() - $(frm).height();
            // 6 pixels extra marge wegens AAVL#38845
            var dialogborderWidth = 6 + $(frm).closest(".ui-dialog").outerWidth() - $(frm).closest(".ui-dialog").width();
            $(frm).height('10px'); // Voor verkleinde/ kleine frames. Anders default minimaal 150px
            var newHeight = Math.min(frmcontent.outerHeight(), $(window).height()-100);
            // FcltMgr.alert("W:" + $(window).height());
            // FcltMgr.alert("N:" + newHeight);
            // Omdat onze <iframe> de dialog *is* hoeven we die schijnbaar niet afzonderlijk te zetten?
            // $(frm).height(newHeight + 200);
            $('iframe#fcltmodal'+FcltMgr._modalCount).dialog('option', 'height', newHeight + dialogborderHeight + 20);
            var newHeight2 = Math.min(frmcontent.outerHeight(), $(window).height()-100);
            if (newHeight2 > newHeight) // Gebeurde in FireFox wel eens
                $('iframe#fcltmodal'+FcltMgr._modalCount).dialog('option', 'height', newHeight2 + dialogborderHeight + 20);
            var extraWidth = 0;
            if (newHeight <= frmcontent.height())
                extraWidth = 24; // scrollbar

            var newWidth = Math.min(frmcontent.outerWidth()+extraWidth , $(window).width()-10);
            if (dialogborderWidth)              // AAVL#38845
                newWidth += dialogborderWidth;
            $('iframe#fcltmodal'+FcltMgr._modalCount).dialog('option', 'width', newWidth);

            // Ook al is onze <iframe> de dialog moeten we deze wel afzonderlijk te zetten?
            $(frm).width(newWidth);

            var newWidth2 = Math.min(frmcontent.outerWidth()+extraWidth , $(window).width()-10);
            if (newWidth2 > newWidth) // FSN#39111
            {
                $('iframe#fcltmodal'+FcltMgr._modalCount).dialog('option', 'width', newWidth2);
                $(frm).width(newWidth2);
            }

            if (FcltMgr.isTouchscreen())
              $('iframe#fcltmodal'+FcltMgr._modalCount).dialog('option', 'position', { my: "top", at: "top", of: window });
            else
              $('iframe#fcltmodal'+FcltMgr._modalCount).dialog('option', 'position', { my: "center", at: "center", of: window });
        },

        // Opent een modal dialoog in de huidige 'detailManager'
        // titel parameter mag weggelaten. Voorkeur is params.title zetten!
        openModalDetail: function(url, titel, params)
        {
         	// Als titel een object is is het eigenlijk params
    		if ( typeof titel === "object" ) {
    			params = titel;
    			titel = params.titel;
    		}
    		var detailMgr = FcltMgr.detailManager();
    		if (!detailMgr.window.$.fn.dialog)
    		    detailMgr = FcltMgr; // Hopen dat we hem zelf hebben

            if (!detailMgr.window.$.fn.dialog)
                FcltMgr.alert("Internal error: jQuery-ui mist mogelijk in " + window.location.href);

            detailMgr._openModalDetail(url, titel, params);
        },

        _openModalDetail: function(url, titel, params)
        {
            // niet nog hoger zoeken
            this._modalCount++;
            params = params || {};
            this._modalCallback[FcltMgr._modalCount] = params.callback;
            this._modalParams[FcltMgr._modalCount] = params;
            params.modal = true;
            if (url.match(/queuemail\.asp/)) // Dan is de titel bedoeld voor *in* het frame
            {
                titel = L("lcl_shared_send_email");
            }
            params.title = titel;
            if (!("resizable" in params))
                params.resizable = true;

            if (params.noClose)
            {
                params.closeOnEscape = false;
                params.open = function(event, ui) { $(".ui-dialog-titlebar-close").hide(); }
            }

            params.close = this.dialogClose; // Omdat we het vanuit een Iframe willen doen.
            if (!("width" in params))
                params.width = 500;

            if (FcltMgr.isTouchscreen())
            {
                var css_scroll = "overflow:auto; -webkit-overflow-scrolling: touch;";
            }
            else
            {
                var css_scroll = "overflow: visible;";
            }

            var html = '<iframe class="fcltmodal"'
                        +' frameborder="0" onload="FcltMgr._resizeModal(this)"'
                        +' id="fcltmodal'+FcltMgr._modalCount+'" name="fcltmodal'+FcltMgr._modalCount+'" style="padding: 0px; '+ css_scroll +'"'
                        +' src="' + url + '">'
                     +'</iframe>';
            $(html).dialog(params).dialog('open');
        },

        dialogArguments: function()
        {
            return parent.FcltMgr._modalParams[parent.FcltMgr._modalCount];
        },

        // Sluit een detailscherm als de gebruiker klaar is met bewerken bijvoorbeeld,
        // Als het een tabje is wordt het tabje gesloten
        // Als het een window is wordt geprobeerd het window te sluiten.
        closeDetail: function(thiswindow, params)
        {
            thiswindow = thiswindow || window;
            params = params || {};
            if (params.warning)
            {
                FcltMgr.alert(params.warning);
                params.warning = null;
            }

            if (this._modalCount)
            {
                $('.ui-dialog-titlebar-close:last').trigger('click'); // doet indirect dialogClose
                var orgParams = this._modalParams[FcltMgr._modalCount+1];
                if (params.cancel && !orgParams.alwaysCallback)
                    return;
                if (this._modalCallback[FcltMgr._modalCount+1])
                    this._modalCallback[FcltMgr._modalCount+1](params, orgParams);
                //this._modalCount--;
                return;
            }
            // Minstens parent, we kunnen het nooit zelf zijn.
            //if (parent.FcltMgr.detailManager()._modalCount)
            //    return parent.FcltMgr.detailManager().closeDetail(thiswindow, params);

            if (FcltMgr.detailManager()._editactive == thiswindow)
            {
                if (FcltMgr._frmaccessible(parent) && parent.$)
                    parent.$("iframe").not("iframe[name="+window.name+"]").not(".frametab").removeClass("ui-widget-overlay ui-front");
                FcltMgr.detailManager()._editactive = false;
                FcltMgr.setTitle(null, {hot:false});
            }

            if (thiswindow.name)
            {
                if (!FcltMgr._frmaccessible(parent))
                {
                    // We zijn waarschijnlijk een share-and-meet frame
                    window.location.href = "../shared/empty.asp?msg=lcl_res_extern_close";
                    return;
                }
                var ifrm = parent.document.getElementById(thiswindow.name);
                if (ifrm && ifrm.getAttribute("FcltClose"))
                {
                    return eval("parent." + ifrm.getAttribute("FcltClose")).call(null,params);
                }
                if (ifrm && ifrm.getAttribute("srcparent"))
                {   // Na verwijderen van child een reload van de parent
                    ifrm.setAttribute("src", ifrm.getAttribute("srcparent").replace(/&collapsed=1/gi, ""));
                    return;
                }
                if (ifrm && ifrm.getAttribute("orgsrc"))
                {   // Na een reload nooit collapsed
                    ifrm.setAttribute("src", ifrm.getAttribute("orgsrc").replace(/&collapsed=1/gi, ""));
                    return;
                }
            }
            if (FcltMgr.IsTheManager)
                return FcltMgr._pageManager.closeDetail(window, params);
            else
                return parent.FcltMgr.closeDetail(parent.window, params);
        },

        closeAll: function (zelf)
        {
            FcltMgr._pageManager.closeAll(zelf);
        },

        saveTab: function (zelf)
        {
            FcltMgr._pageManager.saveTab(zelf);
        },

        saveFavMenu: function (zelf)
        {
            var ttl = $(zelf).closest(".menupinned").attr("fav_ttl");
            var data = {autoopenurl: "",
                        taboption: "M"
                       };
            FcltMgr._pageManager.fnDoSave(ttl, data);
            $(zelf).closest("li").remove();
        },

        setTitle: function (title, params)
        {
            params = params || {};
            params.windowname = FcltMgr.detailManager().window.name;
            FcltMgr.detailManager()._pageManager.setTitle(title, params);
        },

        // Zet het extra-titelblok in een IFRAMERHEADER
        setHeaderExtraTitle: function (html, params)
        {
            $(".fcltframeheader #iframerextratitle").show().html(html);
        },

        _frmaccessible: function(frm)
        {
            try
            {
                if (!frm)
                    return false;
                if (!frm.window)
                    return false;
                if (!frm.document.documentElement) // nog niet klaar (genoeg), soms bij IE8
                    return false;
                frm.FcltMgr; // Probeer frm te benaderen. Bewust zonder de haakjes
                return true;
            }
            catch(e)
            { // neem aan: access denied by punchout of share-and-meet extern tabje
              return false;
            }
        },

        // Aan te roepen door een childwindow als hijzelf resized is (bijvoorbeeld ++bezoekerregels)
        // params: largerOnly (internal)
        _safe_parent: function()
        {
            try
            {
                parent.document;
                return parent;
            }
            catch(e)
            {
            }
            return window;
        },
        resized: function(thiswindow, params)
        {
            params = params || {};
            thiswindow = thiswindow || window;
            if ( parent && FcltMgr._safe_parent() !=window )
            {
                var helpFrame = parent.document.getElementById(thiswindow.name);
                if (helpFrame)
                {
                    if ($(helpFrame).hasClass("fcltmodal"))
                    {   // AAEN#20885 jQuery 1.6.1/ ui 1.8.13 gaf problemen als rechtstreeks
                        setTimeout( function () { parent.FcltMgr._resizeModal(helpFrame) }, 100)
                    }
                    else if ($(helpFrame).hasClass("frametab"))
                    {   // Niets doen als via jumpto een list wordt aangeroepen (bv. prs_phonebook_list.asp).
                        // Anders verdwijnt door resizen de scrollbar.
                    }
                    else
                    {
                        // Flikkert in lange lijsten, daarom alleen als nodig
                        if (!params.largerOnly) // Alleen als (nog) geen scrollbar
                        {
                            // trucje om te zorgen dat *verlagen* ook gedetecteerd wordt
                            // Bewaar scrollTop om te voorkomen dat je naar boven springt
                            var tp = $(window.parent).scrollTop();
                            helpFrame.style.height = "10px";            // Anders geen bulkacties in lange lijsten
                        }

                        // Ooit nodig? In ieder geval problematisch met IE7 compatible $(helpFrame).width($(helpFrame).contents().width());
                        $(helpFrame).height($(helpFrame).contents().height())

                        if (!params.largerOnly)
                        {
                            $(window.parent).scrollTop(tp);
                            // nog een laatste keer keer voor als door de 1e scrollbars zijn gekomen/verdwenen
                            // door de Timeout krijgt IE zin te herberekenen
                            setTimeout(function () { FcltMgr.resized(window, { largerOnly: true }) }, 100);
                        }

                    }
                }
                if (parent.FcltMgr)
                {
                    parent.FcltMgr.resized(window, params);
                }
            }
        },

        // Aan te roepen vanuit een childwindow als hij bijvoorbeeld niet onzichtbaar wil refreshen
        inInvisbleTab: function()
        {
            if ( !parent || parent==window )
                return false;  // gokken op zichtbaar zijn

            var helpFrame = parent.document.getElementById(window.name);
            if (helpFrame)
            {
                if ($(helpFrame).hasClass("frametab"))
                {
                    return ($(helpFrame).css("display") == "none");
                }
            }
            if (parent.FcltMgr)
                return parent.FcltMgr.inInvisbleTab();
            return false;  // gokken op zichtbaar zijn

        },

        // <iframe onload='FcltMgr.iframeLoaded(this)'>
        iframeLoaded: function (elm_iframe, widthToo, largerOnly)
        {
            var $elm_iframe = $(elm_iframe);
            try
            {
                var frmcontent = $elm_iframe.contents(); // testing
            }
            catch (e)
            {
                return; // Qlikview in een ander frame
            }

            // Zet maar meteen een unload-event op de frame-contents
            // zodat we (veel) later een spinner krijgen als het frame
            // wordt vervangen
            $(elm_iframe.contentWindow).on("beforeunload", function () {
                    /* na 500 ms: bij empty.asp zetten we de spinner aan, bij andere
                     *            pagina's doen we een overlay
                     * na 2000ms: bij gewone pagina's doen we nu pas de spinner
                     */
                    elm_iframe.contentWindow.setTimeout(function () {
                            var $body = $("body", elm_iframe.contentDocument);
                            if (elm_iframe.contentDocument.location.href.match(/empty\.asp|empty\.html/ig))
                            {
                                if (!$body.find("div.busyloading").length)
                                {
                                    var w = $(window).width();
                                    $body.prepend("<div style='left:"+(w/2)+"px' class='busyloading'><i class='fa fa-spinner fa-pulse fa-4x fa-fw'></i></div>");
                                }
                            }
                            else
                            {
                                var wrapper = $("<div class='busyoverlay'></div>");
                                $body.contents().wrap(wrapper);
                            }
                        }, 500);
                    elm_iframe.contentWindow.setTimeout(function () {
                            var $body = $("body", elm_iframe.contentDocument);
                            if (!$body.find("div.busyloading").length)
                            {
                                var w = $(window).width();
                                $body.prepend("<div style='left:"+(w/2)+"px' class='busyloading'><i class='fa fa-spinner fa-pulse fa-4x fa-fw'></i></div>");
                            }
                        }, 2000);
                });

            // Als resultlist te breed is moet er wel een scrollbar onderin komen.
            // Ietwat getruct alleen voor result-sets, anders willen gewone schermen
            // niet altijd goed resizen van klein naar groot.
            // 1 pixel extra marge voor IE-bug FSN#32255
            if (frmcontent.width() > $elm_iframe.width() + 1 && elm_iframe.parentElement.id == "result")
            {
              widthToo = true;
            }

            var wasScroll = $(window).scrollTop();
            if (!largerOnly)
                $elm_iframe.height(10);// trucje om te zorgen dat *verlagen* ook gedetecteerd wordt

            $elm_iframe.height(frmcontent.height());
            $(window).scrollTop(wasScroll);

            if (widthToo)
            {
                $elm_iframe.width(100); // trucje om te zorgen dat *versmallen* ook gedetecteerd wordt
                // Nooit smaller dan de parent
                var newWidth = Math.max($(document.body).width(),frmcontent.width());
                $elm_iframe.width(newWidth);
                // this.get(0).scrollHeight > this.height();
                if ($elm_iframe[0].scrollWidth > newWidth) // scrollbar
                    $elm_iframe.height(frmcontent.height() + 24);
            }
            else
                elm_iframe.style.width = "100%";

            if (!largerOnly)
            {
                // nog een laatste keer keer voor als door de 1e scrollbars zijn gekomen/verdwenen
                // door de Timeout krijgt IE zin te herberekenen
                setTimeout(function () { FcltMgr.iframeLoaded(elm_iframe, widthToo, true) } , 100);
            }
            // Scroll resultaatblok automatisch in beeld
            if (wasScroll == 0 &&
                elm_iframe.parentElement && elm_iframe.parentElement.id == 'result' &&
                !frmcontent[0].URL.match("empty\.(asp|html)") &&
                !frmcontent[0].URL.match("no_autoscroll=1") &&
                !$elm_iframe.attr("skipautoscroll") &&
                !largerOnly &&
                $('#result').offset())
            {
                //window.location.hash = "result";
                $('html, body').animate({
                    scrollTop: $('#result').offset().top
                }, 400);
            }
            $elm_iframe.removeAttr("skipautoscroll"); // Volgens keer wel gewoon
            //FcltMgr.resized(window);
        },

        eventLoaded: function ()
        {
            if (parent && parent.FcltMgr)
                parent.FcltMgr.childLoaded(window);
        },

        // Door een child-window aan te roepen vlak voordat hij van show naar edit mode gaat
        startEdit: function (thiswindow, params)
        {
            if (FcltMgr.mayEdit(thiswindow, params))
            {
                FcltMgr.detailManager()._editactive = thiswindow;
                // Let op: soms wordt startEdit aangroepen van een sub-frame (res_show_rsv_ruimte.asp) maar
                //         soms echter ook vanuit de parent (nieuwe reservering-->res_reservering.asp)
                //         Die laatste zou eigen startEdit('window van het subframe') moeten doen
                // De parent.name.match(/^ID.*/) is voor de veiligheid voor als er geen frame omheen zit (touch)
                if (FcltMgr._frmaccessible(parent) && thiswindow.parent && thiswindow.parent.$
                    && (thiswindow != window || thiswindow.parent.name.match(/^ID.*/)))
                {
                    thiswindow.parent.$("iframe")
                            .not("iframe[name="+thiswindow.name+"]").not(".frametab,.fcltmodal")
                            .addClass("ui-widget-overlay ui-front").css('position','static');
                }
                FcltMgr.setTitle(null, { hot : thiswindow });
                return true;
            }
            else
                return false;
        },

        // Door een manager-window aan te roepen als hij wil gaan editen
        mayEdit: function (thiswindow, params)
        {
            if (FcltMgr.detailManager()._editactive)
            {
                FcltMgr.alert(L("lcl_shared_othertabactive"))
                return false;
            }
            return true;
        },

        setCaller: function(callerinfo)
        {
            this.topmanager()._caller = callerinfo;
        },

        getCaller: function()
        {
            return this.topmanager()._caller;
        },
        setData: function (code, data)
        {
            this.topmanager().globalData[code] = data;
        },
        getData: function (code)
        {
            return this.topmanager().globalData[code];
        },

        L: function (lcl)
        {
            if (!(lcl in window.LCL)) // nog niet met de cache meegekomen?
            {
                // Beetje onverwacht dat hij nog niet is gecached.
                // Ophalen met ajax. Dat registreert meteen in onze zelflerende cache
                var url = rooturl + "/appl/shared/load_lcl.asp?lcl=" + lcl;
                url += "&pathname=" + escape(document.location.pathname);
                window.LCL[lcl] = FcltSyncgetJSON(url).lcl;
            }
            return window.LCL[lcl];
        },

        stopPropagation: function(eventHandler)
        {   // This prevents the event from bubbling up to the onclick event handler for the line.
            eventHandler = eventHandler || window.event || {};
            if (eventHandler.stopPropagation)
                eventHandler.stopPropagation();
// Neen, dan kun je bijvoorbeeld in res_plan_obj geen vinkjes meer zetten
//            if (eventHandler.preventDefault)
//                eventHandler.preventDefault();

            eventHandler.cancelBubble = true;

        },

        isTouchscreen: function ()
        {
            var isTouch = false;
            var agent = navigator.userAgent;
            if (  (agent.indexOf("iPad") != -1)
               || (agent.indexOf("iPhone") != -1)
               || (agent.indexOf("SCH-I800") != -1)
               || ((agent.indexOf("Android") != -1) && (agent.indexOf("Mobile") == -1))
               )
            {
                isTouch = true;
            }
            return isTouch;
        },

        fixActiveelementError: function ()
        {   // FSN#25845
            // Fix 'unspecified error' op document.activeElement in jQuery 1.9.1/IE 9
            var agent = navigator.userAgent;
            if (agent.match(/MSIE 7\.0|MSIE 8\.0|MSIE 9\.0/))
            {
                try { document.documentElement.focus(); }
                catch(e) {/* soms met IE8 op 'remembered' tabbladen */}
            }
        },
        mydialog: function (tekst, params)
        {
            try {
                params.keepfocus = document.activeElement; // probeer die terug te zetten
            }
            catch(e) { /* unspecifed error in IE11 */ }
            this.topmanager()._mydialog(tekst, params);
        },
        _mydialog: function (tekst, params)
        {
            var ditwindow = window;
            tekst = tekst.replace(/\n/ig, "<br>");
            var dia = $('<div>' + tekst + '</div>');
            params.buttons = params.buttons || [];
            params.buttons.unshift( // Ok is er altijd
                        {
                            text: params.oktekst || L("lcl_ok"),
                            click: function ()
                            {
                                if (params.fncallback)
                                    params.fncallback();
                            }
                        });
            // Doe overal automatisch een 'close' achteraan
            for (var i = 0; i < params.buttons.length; i++)
            {
                var button = params.buttons[i];
                button.click = function (wasclick)
                    {
                        return function ()
                            {
                                if (wasclick)
                                    wasclick.apply(this, arguments);
                                dia.dialog("close");
                                if (params.keepfocus)
                                {
                                    params.keepfocus.focus();
                                }

                                if (params.fnafterclose)
                                {
                                    params.fnafterclose();
                                }
                            }
                    }(button.click);
            }

            var wWidth = $(window).width();
            var dWidth = wWidth * 0.8;
            dia.appendTo('body')
                .dialog({
                    modal: true,
                    title: params.title,
                    zIndex: 10000,
                    autoOpen: true,
                    width: 'auto',
                    closeOnEscape: false, // die doen we zelf om params.fncancel te kunnen aanroepen
                    create: function(){
                        $(this).css('maxWidth', dWidth);
                        $(this).dialog("widget").find('.ui-dialog-titlebar-close').remove();
                        $(this).closest('.ui-dialog').on('keydown', function(ev) {
                           if (ev.keyCode === $.ui.keyCode.ESCAPE) {
                                if (params.fncancel)
                                    params.fncancel();
                                dia.dialog("close");
                           }
                       });
                    },
                    resizable: false,
                    buttons: params.buttons,
                    close: function (event, ui) {
                        dia.remove();
                    }
                });
        },
        confirm: function (tekst, params, fncallback)
        {
            if (typeof params == "function")
            {   // shift
                fncallback = params;
                params = {};
            }
            if (params.autoconfirm)
            {
                fncallback();
                return;
            }
            if (window.fcltmobile || !this.topmanager().window.$.fn.dialog) // fallback als jQuery-ui niet is geladen
            {
                if (confirm(tekst))
                {
                    fncallback();
                }
                else
                {
                    if (params.fncancel)
                        params.fncancel();
                }
                return;
            }
            params.fncallback = fncallback;
            params.buttons = [
                {
                    text: params.canceltekst || L("lcl_cancel"),
                    click: function ()
                    {
                        if (params.fncancel)
                            params.fncancel();
                    }
                }];

            this.mydialog (tekst, params, fncallback);
        },
        alert: function (tekst, params)
        {
            params = params || {};
            if (window.fcltmobile || !this.topmanager().window.$.fn.dialog) // fallback als jQuery-ui niet is geladen
            {
                alert(tekst);
                return;
            }
            this.mydialog (tekst, params);
        }
    }

FcltMgr.url = window.location.href;
FcltMgr.window = window;
FcltMgr._pageManager = FcltMgr.defaultManager;
FcltMgr.IsTheManager = true;
try
{   // Als een van beide op /-1 eindigt niet al te hard klagen
    if (this.userId && !String(this.userId).match(/\/\-1$/)
          && parent && parent.userId && !String(parent.userId).match(/\/\-1$/)
          && this.userId != parent.userId)
        if (confirm("Unexpected change from user " + parent.userId + " to " + this.userId + "\nReload FACILITOR?"))
            top.location.reload();

    if (parent && parent.FcltMgr && parent.FcltMgr != FcltMgr)
    {
        FcltMgr._pageManager = parent.FcltMgr._pageManager;
        FcltMgr.IsTheManager = false;
    }
}
catch(e)
{
    /* Kan falen als FACILITOR in een frame draait */
}
