<commit_before>(function (window) {

    var History = window.History;

    var pagerJsModule = function ($, ko) {

        "use strict";

        /**
         * @module pager
         * @readme README.md
         */

        var pager = {};

        pager.page = null;

        pager.now = function () {
            if (!Date.now) {
                return (new Date()).valueOf();
            } else {
                return Date.now();
            }
        };


        /**
         * @method extendWithPage
         * @static
         * @param {Observable} viewModel
         */
        pager.extendWithPage = function (viewModel) {
            var page = new pager.Page();
            viewModel.$__page__ = page;
            pager.page = page;
        };

        /**
         * Called when a route does not find a match.
         *
         * @var navigationFailed
         * @type {Observable}
         * @static
         */
        pager.navigationFailed = ko.observable();

        /**
         *
         * @param {String[]} route
         */
        pager.showChild = function (route) {
            pager.page.showPage(route);
            //pager.page.childManager.showChild(route);
        };

// common KnockoutJS helpers
        var _ko = {};

        _ko.value = ko.utils.unwrapObservable;

        _ko.arrayValue = function (arr) {
            return $.map(arr, function (e) {
                return _ko.value(e);
            });
        };

        var parseStringAsParameters = function (query) {
            var match,
                urlParams = {},
                pl = /\+/g, // Regex for replacing addition symbol with a space
                search = /([^&=]+)=?([^&]*)/g,
                decode = function (s) {
                    return decodeURIComponent(s.replace(pl, " "));
                };

            while (match = search.exec(query)) {
                urlParams[decode(match[1])] = decode(match[2]);
            }
            return urlParams;
        };

        var splitRoutePartIntoNameAndParameters = function (routePart) {
            if (!routePart) {
                return {name:null, params:{}};
            }
            var routeSplit = routePart.split('?');
            var name = routeSplit[0];
            var paramsString = routeSplit[1];
            var params = {};
            if (paramsString) {
                params = parseStringAsParameters(paramsString);
            }
            return {
                name:name,
                params:params
            };
        };

        /**
         * @class pager.ChildManager
         *
         * @param {pager.Page[]} children
         * @param {pager.Page} page
         */
        pager.ChildManager = function (children, page) {

            this.currentChildO = ko.observable(null);
            var me = this;
            this.page = page;
            // Used by showChild to find out if the navigation is still current.
            // In needed since the navigation is asynchronous and another navigation might happen in between.
            this.timeStamp = pager.now();

            /**
             * @method pager.ChildManager#hideChild
             */
            this.hideChild = function () {
                if (me.currentChild) {
                    if (me.currentChild.getId() !== 'start') {
                        me.currentChild.hidePage(function () {
                        });
                        me.currentChild = null;
                        me.currentChildO(null);
                    }
                }
            };

            /**
             * Show the sub-page in this ChildManager's page that matches the route.
             *
             * @method pager.ChildManager#showChild
             * @param {String[]} route route to match a sub-page to. Can be on the form `['foo','bar?x=22&y=11']`.
             */
            this.showChild = function (route) {
                this.timeStamp = pager.now();
                var timeStamp = this.timeStamp;
                var oldCurrentChild = me.currentChild;
                me.currentChild = null;
                var match = false;
                var currentRoutePair = splitRoutePartIntoNameAndParameters(route[0]);
                var currentRoute = currentRoutePair.name;
                var wildcard = null;
                $.each(children(), function (childIndex, child) {
                    if (!match) {
                        var id = child.getId();
                        if (id === currentRoute ||
                            ((currentRoute === '' || currentRoute == null) && id === 'start')) {
                            match = true;
                            me.currentChild = child;
                        }
                        if (id === '?') {
                            wildcard = child;
                        }
                    }
                });
                // find modals in parent - but only if 1) no match is found, 2) this page got a parent and 3) this page is not a modal!
                var isModal = false;

                var currentChildManager = me;

                var findMatchModalOrWildCard = function (childIndex, child) {
                    if (!match) {
                        var id = child.getId();
                        var modal = child.getValue().modal;
                        if (modal) {
                            if (id === currentRoute ||
                                ((currentRoute === '' || currentRoute == null) && id === 'start')) {
                                match = true;
                                me.currentChild = child;
                                isModal = true;
                            }
                            if (id === '?' && !wildcard) {
                                wildcard = child;
                                isModal = true;
                            }
                        }
                    }
                };

                while (!me.currentChild && currentChildManager.page.parentPage && !currentChildManager.page.getValue().modal) {
                    var parentChildren = currentChildManager.page.parentPage.children;
                    $.each(parentChildren(), findMatchModalOrWildCard);
                    if (!me.currentChild) {
                        currentChildManager = currentChildManager.page.parentPage.childManager;
                    }
                }

                if (!me.currentChild && wildcard) {
                    me.currentChild = wildcard;
                    //me.currentChild.currentId = currentRoute;
                }
                if (me.currentChild) {
                    me.currentChildO(me.currentChild);

                    if (isModal) {
                        me.currentChild.currentParentPage(me.page);
                    } else {
                        me.currentChild.currentParentPage(null);
                    }

                }

                var onFailed = function () {
                    if (pager.navigationFailed) {
                        pager.navigationFailed({page:me.page, route:route});
                    }
                    if (me.page.getValue().navigationFailed) {
                        _ko.value(me.page.getValue().navigationFailed)(me.page, route);
                    }
                };

                var showCurrentChild = function () {
                    var guard = _ko.value(me.currentChild.getValue().guard);
                    if (guard) {
                        guard(me.currentChild, route, function () {
                            if (me.timeStamp === timeStamp) {
                                me.currentChild.showPage(route.slice(1), currentRoutePair, route[0]);
                            }
                        }, oldCurrentChild);
                    } else {
                        me.currentChild.showPage(route.slice(1), currentRoutePair, route[0]);
                    }
                };

                if (oldCurrentChild && oldCurrentChild === me.currentChild) {
                    showCurrentChild();
                } else if (oldCurrentChild) {
                    oldCurrentChild.hidePage(function () {
                        if (me.currentChild) {
                            showCurrentChild();
                        } else {
                            onFailed();
                        }
                    });
                } else if (me.currentChild) {
                    showCurrentChild();
                } else {
                    onFailed();
                }
            };
        };

        /**
         *
         * @class pager.Page
         *
         * @param {Node} element
         * @param {Object} valueAccessor
         * @param {String} valueAccessor.id
         * @param {Observable} valueAccessor.with
         * @param {Function} valueAccessor.withOnShow
         * @param {String/Function} valueAccessor.source
         * @param {String/Function} valueAccessor.sourceLoaded
         * @param {Number/Boolean} valueAccessor.sourceCache
         * @param {String} valueAccessor.frame
         * @param {Boolean} valueAccessor.modal
         * @param {Boolean} valueAccessor.deep
         * @param {Function} valueAccessor.beforeHide
         * @param {Function} valueAccessor.beforeShow
         * @param {Function} valueAccessor.afterHide
         * @param {Function} valueAccessor.hideElement
         * @param {Function} valueAccessor.showElement
         * @param {Function} valueAccessor.loader
         * @param {Function} valueAccessor.navigationFailed
         * @param {Function} valueAccessor.guard
         * @param {Object} valueAccessor.params
         * @param {Object} valueAccessor.vars
         * @param {String} valueAccessor.fx
         * @param {String} valueAccessor.urlToggle can be either null (default), "none" or "show"
         * @param allBindingsAccessor
         * @param {Observable} viewModel
         * @param bindingContext
         */
        pager.Page = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            /**
             *
             * @type {Node}
             */
            this.element = element;
            /**
             *
             * @type {Observable}
             */
            this.valueAccessor = valueAccessor;
            /**
             *
             * @type {*}
             */
            this.allBindingsAccessor = allBindingsAccessor;
            /**
             *
             * @type {Observable}
             */
            this.viewModel = viewModel;
            /**
             *
             * @type {*}
             */
            this.bindingContext = bindingContext;

            /**
             *
             * @type {ObservableArray}
             */
            this.children = ko.observableArray([]);

            /**
             *
             * @type {pager.ChildManager}
             */
            this.childManager = new pager.ChildManager(this.children, this);
            /**
             *
             * @type {pager.Page}
             */
            this.parentPage = null;
            /**
             *
             * @type {String}
             */
            this.currentId = null;

            /**
             *
             *
             * @type {Observable}
             */
            this.ctx = null;

            /**
             *
             * @type {Observable/pager.Page}
             */
            this.currentParentPage = ko.observable(null);


            /**
             *
             * @type {Observable}
             */
            this.isVisible = ko.observable(false);

            this.originalRoute = ko.observable(null);

            this.route = null;
        };

        var p = pager.Page.prototype;

        /**
         * @method pager.Page#val
         *
         * @param {String} key
         * @return {Object} an un-boxed configuration property
         */
        p.val = function (key) {
            return _ko.value(this.getValue()[key]);
        };

        p.currentChildPage = function () {
            return this.childManager.currentChildO;
        };

        /**
         * @method pager.Page#showPage
         *
         * @param route
         * @param [pageRoute]
         * @param [originalRoute]
         */
        p.showPage = function (route, pageRoute, originalRoute) {
            var m = this,
                currentId = m.currentId,
                params = m.pageRoute ? m.pageRoute.params : null,
                isVisible = m.isVisible();
            m.currentId = pageRoute ? pageRoute.name : null;
            m.isVisible(true);
            if (originalRoute) {
                m.originalRoute(originalRoute);
            }
            m.route = route;
            m.pageRoute = pageRoute;
            // show if not already visible
            if (!isVisible) {
                m.setParams();
                m.show();
            } else {
                // show if wildcard got new ID
                if (m.getId() === '?' && currentId !== m.currentId) {
                    m.show();
                }
                // update params if they are updated
                if (pageRoute && params !== pageRoute.params) {
                    m.setParams();
                }
            }
            m.childManager.showChild(route);
        };

        /**
         * @method pager.Page#setParams
         *
         */
        p.setParams = function () {
            if (this.pageRoute && this.pageRoute.params) {
                var params = this.pageRoute.params;

                // get view model
                var vm = this.ctx;
                var userParams = this.val('params') || {};
                // for each param for URL
                $.each(params, function (key, value) {
                    if ($.inArray(key, userParams) !== -1) { // make sure it's a valid param
                        if (vm[key]) { // set observable ...
                            vm[key](value);
                        } else { // ... or create observable
                            vm[key] = ko.observable(value);
                        }
                    }
                });
            }
            if (this.pageRoute) {
                var nameParam = this.getValue()['nameParam'];
                if (nameParam) {
                    if (typeof nameParam === 'string') {
                        if (this.ctx[nameParam]) { // set observable ...
                            this.ctx[nameParam](this.currentId);
                        } else { // ... or create observable
                            this.ctx[nameParam] = ko.observable(this.currentId);
                        }
                    } else { // is Observable
                        nameParam(this.currentId);
                    }
                }
            }
        };

        /**
         * @method pager.Page#hidePage
         *
         * @param {Function} callback
         */
        p.hidePage = function (callback) {
            var m = this;
            if ('show' !== m.val('urlToggle')) {
                m.isVisible(false);
                m.hideElementWrapper(callback);
                m.childManager.hideChild();
            } else {
                if (callback) {
                    callback();
                }
            }
        };

        /**
         * @method pager.Page#init
         *
         * @return {Object}
         */
        p.init = function () {
            var m = this;
            var urlToggle = m.val('urlToggle');

            // listen to when the element is removed
            ko.utils.domNodeDisposal.addDisposeCallback(m.element, function () {
                // then remove this Page-instance
                m.parentPage.children.remove(m);
            });

            var value = m.getValue();
            if (urlToggle !== 'none') {
                m.parentPage = m.getParentPage();
                m.parentPage.children.push(this);
                m.hideElement();
            }


            // Fetch source
            if (m.val('source')) {
                m.loadSource(m.val('source'));
            }

            m.ctx = null;
            if (value['with']) {
                m.ctx = _ko.value(value['with']);
                m.augmentContext();
            } else if (value.withOnShow) {
                m.ctx = {};
            } else {
                m.ctx = m.viewModel;
                m.augmentContext();
            }
            m.childBindingContext = m.bindingContext.createChildContext(m.ctx);
            ko.utils.extend(m.childBindingContext, {$page:this});
            if (!m.val('withOnShow')) {
                ko.applyBindingsToDescendants(m.childBindingContext, m.element);
            }

            if (urlToggle !== 'none') {
                // check if this page should trigger showChild at parent
                if (m.parentPage.route && m.parentPage.route[0] === m.getId()) {
                    // call once the current event loop is finished.
                    setTimeout(function () {
                        m.parentPage.showPage(m.parentPage.route);
                    }, 0);
                }
            } else { // urlToggle === 'none'
                // when the page is rendered
                setTimeout(function () {
                    // if the page is visible
                    if ($(m.element).is(':visible')) {
                        // trigger showPage with empty route-array
                        m.showPage([]);
                    }
                }, 0);
            }

            return { controlsDescendantBindings:true};
        };

        p.augmentContext = function () {
            var m = this;
            if (m.val('params')) {
                $.each(this.val('params'), function (index, param) {
                    if (!m.ctx[param]) {
                        m.ctx[param] = ko.observable();
                    }
                });
            }
            if (this.val('vars')) {
                $.each(this.val('vars'), function (key, value) {
                    m.ctx[key] = ko.observable(value);
                });
            }
            this.setParams();
        };<commit_msg>UrlToggle='none' not redisplaying when embedded in a wildcard page<commit_after>(function (window) {

    var History = window.History;

    var pagerJsModule = function ($, ko) {

        "use strict";

        /**
         * @module pager
         * @readme README.md
         */

        var pager = {};

        pager.page = null;

        pager.now = function () {
            if (!Date.now) {
                return (new Date()).valueOf();
            } else {
                return Date.now();
            }
        };


        /**
         * @method extendWithPage
         * @static
         * @param {Observable} viewModel
         */
        pager.extendWithPage = function (viewModel) {
            var page = new pager.Page();
            viewModel.$__page__ = page;
            pager.page = page;
        };

        /**
         * Called when a route does not find a match.
         *
         * @var navigationFailed
         * @type {Observable}
         * @static
         */
        pager.navigationFailed = ko.observable();

        /**
         *
         * @param {String[]} route
         */
        pager.showChild = function (route) {
            pager.page.showPage(route);
            //pager.page.childManager.showChild(route);
        };

// common KnockoutJS helpers
        var _ko = {};

        _ko.value = ko.utils.unwrapObservable;

        _ko.arrayValue = function (arr) {
            return $.map(arr, function (e) {
                return _ko.value(e);
            });
        };

        var parseStringAsParameters = function (query) {
            var match,
                urlParams = {},
                pl = /\+/g, // Regex for replacing addition symbol with a space
                search = /([^&=]+)=?([^&]*)/g,
                decode = function (s) {
                    return decodeURIComponent(s.replace(pl, " "));
                };

            while (match = search.exec(query)) {
                urlParams[decode(match[1])] = decode(match[2]);
            }
            return urlParams;
        };

        var splitRoutePartIntoNameAndParameters = function (routePart) {
            if (!routePart) {
                return {name:null, params:{}};
            }
            var routeSplit = routePart.split('?');
            var name = routeSplit[0];
            var paramsString = routeSplit[1];
            var params = {};
            if (paramsString) {
                params = parseStringAsParameters(paramsString);
            }
            return {
                name:name,
                params:params
            };
        };

        /**
         * @class pager.ChildManager
         *
         * @param {pager.Page[]} children
         * @param {pager.Page} page
         */
        pager.ChildManager = function (children, page) {

            this.currentChildO = ko.observable(null);
            var me = this;
            this.page = page;
            // Used by showChild to find out if the navigation is still current.
            // In needed since the navigation is asynchronous and another navigation might happen in between.
            this.timeStamp = pager.now();

            /**
             * @method pager.ChildManager#hideChild
             */
            this.hideChild = function () {
                if (me.currentChild) {
                    if (me.currentChild.getId() !== 'start') {
                        me.currentChild.hidePage(function () {
                        });
                        me.currentChild = null;
                        me.currentChildO(null);
                    }
                }
            };

            /**
             * Show the sub-page in this ChildManager's page that matches the route.
             *
             * @method pager.ChildManager#showChild
             * @param {String[]} route route to match a sub-page to. Can be on the form `['foo','bar?x=22&y=11']`.
             */
            this.showChild = function (route) {
                this.timeStamp = pager.now();
                var timeStamp = this.timeStamp;
                var oldCurrentChild = me.currentChild;
                me.currentChild = null;
                var match = false;
                var currentRoutePair = splitRoutePartIntoNameAndParameters(route[0]);
                var currentRoute = currentRoutePair.name;
                var wildcard = null;
                $.each(children(), function (childIndex, child) {
                    if (!match) {
                        var id = child.getId();
                        if (id === currentRoute ||
                            ((currentRoute === '' || currentRoute == null) && id === 'start')) {
                            match = true;
                            me.currentChild = child;
                        }
                        if (id === '?') {
                            wildcard = child;
                        }
                    }
                });
                // find modals in parent - but only if 1) no match is found, 2) this page got a parent and 3) this page is not a modal!
                var isModal = false;

                var currentChildManager = me;

                var findMatchModalOrWildCard = function (childIndex, child) {
                    if (!match) {
                        var id = child.getId();
                        var modal = child.getValue().modal;
                        if (modal) {
                            if (id === currentRoute ||
                                ((currentRoute === '' || currentRoute == null) && id === 'start')) {
                                match = true;
                                me.currentChild = child;
                                isModal = true;
                            }
                            if (id === '?' && !wildcard) {
                                wildcard = child;
                                isModal = true;
                            }
                        }
                    }
                };

                while (!me.currentChild && currentChildManager.page.parentPage && !currentChildManager.page.getValue().modal) {
                    var parentChildren = currentChildManager.page.parentPage.children;
                    $.each(parentChildren(), findMatchModalOrWildCard);
                    if (!me.currentChild) {
                        currentChildManager = currentChildManager.page.parentPage.childManager;
                    }
                }

                if (!me.currentChild && wildcard) {
                    me.currentChild = wildcard;
                    //me.currentChild.currentId = currentRoute;
                }
                if (me.currentChild) {
                    me.currentChildO(me.currentChild);

                    if (isModal) {
                        me.currentChild.currentParentPage(me.page);
                    } else {
                        me.currentChild.currentParentPage(null);
                    }

                }

                var onFailed = function () {
                    if (pager.navigationFailed) {
                        pager.navigationFailed({page:me.page, route:route});
                    }
                    if (me.page.getValue().navigationFailed) {
                        _ko.value(me.page.getValue().navigationFailed)(me.page, route);
                    }
                };

                var showCurrentChild = function () {
                    var guard = _ko.value(me.currentChild.getValue().guard);
                    if (guard) {
                        guard(me.currentChild, route, function () {
                            if (me.timeStamp === timeStamp) {
                                me.currentChild.showPage(route.slice(1), currentRoutePair, route[0]);
                            }
                        }, oldCurrentChild);
                    } else {
                        me.currentChild.showPage(route.slice(1), currentRoutePair, route[0]);
                    }
                };

                if (oldCurrentChild && oldCurrentChild === me.currentChild) {
                    showCurrentChild();
                } else if (oldCurrentChild) {
                    oldCurrentChild.hidePage(function () {
                        if (me.currentChild) {
                            showCurrentChild();
                        } else {
                            onFailed();
                        }
                    });
                } else if (me.currentChild) {
                    showCurrentChild();
                } else {
                    onFailed();
                }
            };
        };

        /**
         *
         * @class pager.Page
         *
         * @param {Node} element
         * @param {Object} valueAccessor
         * @param {String} valueAccessor.id
         * @param {Observable} valueAccessor.with
         * @param {Function} valueAccessor.withOnShow
         * @param {String/Function} valueAccessor.source
         * @param {String/Function} valueAccessor.sourceLoaded
         * @param {Number/Boolean} valueAccessor.sourceCache
         * @param {String} valueAccessor.frame
         * @param {Boolean} valueAccessor.modal
         * @param {Boolean} valueAccessor.deep
         * @param {Function} valueAccessor.beforeHide
         * @param {Function} valueAccessor.beforeShow
         * @param {Function} valueAccessor.afterHide
         * @param {Function} valueAccessor.hideElement
         * @param {Function} valueAccessor.showElement
         * @param {Function} valueAccessor.loader
         * @param {Function} valueAccessor.navigationFailed
         * @param {Function} valueAccessor.guard
         * @param {Object} valueAccessor.params
         * @param {Object} valueAccessor.vars
         * @param {String} valueAccessor.fx
         * @param {String} valueAccessor.urlToggle can be either null (default), "none" or "show"
         * @param allBindingsAccessor
         * @param {Observable} viewModel
         * @param bindingContext
         */
        pager.Page = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            /**
             *
             * @type {Node}
             */
            this.element = element;
            /**
             *
             * @type {Observable}
             */
            this.valueAccessor = valueAccessor;
            /**
             *
             * @type {*}
             */
            this.allBindingsAccessor = allBindingsAccessor;
            /**
             *
             * @type {Observable}
             */
            this.viewModel = viewModel;
            /**
             *
             * @type {*}
             */
            this.bindingContext = bindingContext;

            /**
             *
             * @type {ObservableArray}
             */
            this.children = ko.observableArray([]);

            /**
             *
             * @type {pager.ChildManager}
             */
            this.childManager = new pager.ChildManager(this.children, this);
            /**
             *
             * @type {pager.Page}
             */
            this.parentPage = null;
            /**
             *
             * @type {String}
             */
            this.currentId = null;

            /**
             *
             *
             * @type {Observable}
             */
            this.ctx = null;

            /**
             *
             * @type {Observable/pager.Page}
             */
            this.currentParentPage = ko.observable(null);


            /**
             *
             * @type {Observable}
             */
            this.isVisible = ko.observable(false);

            this.originalRoute = ko.observable(null);

            this.route = null;
        };

        var p = pager.Page.prototype;

        /**
         * @method pager.Page#val
         *
         * @param {String} key
         * @return {Object} an un-boxed configuration property
         */
        p.val = function (key) {
            return _ko.value(this.getValue()[key]);
        };

        p.currentChildPage = function () {
            return this.childManager.currentChildO;
        };

        /**
         * @method pager.Page#showPage
         *
         * @param route
         * @param [pageRoute]
         * @param [originalRoute]
         */
        p.showPage = function (route, pageRoute, originalRoute) {
            var m = this,
                currentId = m.currentId,
                params = m.pageRoute ? m.pageRoute.params : null,
                isVisible = m.isVisible();
            m.currentId = pageRoute ? pageRoute.name : null;
            m.isVisible(true);
            if (originalRoute) {
                m.originalRoute(originalRoute);
            }
            m.route = route;
            m.pageRoute = pageRoute;
            // show if not already visible
            if (!isVisible) {
                m.setParams();
                m.show();
            } else {
                // show if wildcard got new ID
                if (m.getId() === '?' && currentId !== m.currentId) {
                    m.show();
                }
                // update params if they are updated
                if (pageRoute && params !== pageRoute.params) {
                    m.setParams();
                }
            }
            m.childManager.showChild(route);
        };

        /**
         * @method pager.Page#setParams
         *
         */
        p.setParams = function () {
            if (this.pageRoute && this.pageRoute.params) {
                var params = this.pageRoute.params;

                // get view model
                var vm = this.ctx;
                var userParams = this.val('params') || {};
                // for each param for URL
                $.each(params, function (key, value) {
                    if ($.inArray(key, userParams) !== -1) { // make sure it's a valid param
                        if (vm[key]) { // set observable ...
                            vm[key](value);
                        } else { // ... or create observable
                            vm[key] = ko.observable(value);
                        }
                    }
                });
            }
            if (this.pageRoute) {
                var nameParam = this.getValue()['nameParam'];
                if (nameParam) {
                    if (typeof nameParam === 'string') {
                        if (this.ctx[nameParam]) { // set observable ...
                            this.ctx[nameParam](this.currentId);
                        } else { // ... or create observable
                            this.ctx[nameParam] = ko.observable(this.currentId);
                        }
                    } else { // is Observable
                        nameParam(this.currentId);
                    }
                }
            }
        };

        /**
         * @method pager.Page#hidePage
         *
         * @param {Function} callback
         */
        p.hidePage = function (callback) {
            var m = this;
            if ('show' !== m.val('urlToggle')) {
                m.isVisible(false);
                m.hideElementWrapper(callback);
                m.childManager.hideChild();
            } else {
                if (callback) {
                    callback();
                }
            }
        };

        /**
         * @method pager.Page#init
         *
         * @return {Object}
         */
        p.init = function () {
            var m = this;
            var urlToggle = m.val('urlToggle');

            // listen to when the element is removed
            ko.utils.domNodeDisposal.addDisposeCallback(m.element, function () {
                // then remove this Page-instance
                if (m.parentPage)
                    m.parentPage.children.remove(m);
            });

            var value = m.getValue();
            if (urlToggle !== 'none') {
                m.parentPage = m.getParentPage();
                m.parentPage.children.push(this);
                m.hideElement();
            }


            // Fetch source
            if (m.val('source')) {
                m.loadSource(m.val('source'));
            }

            m.ctx = null;
            if (value['with']) {
                m.ctx = _ko.value(value['with']);
                m.augmentContext();
            } else if (value.withOnShow) {
                m.ctx = {};
            } else {
                m.ctx = m.viewModel;
                m.augmentContext();
            }
            m.childBindingContext = m.bindingContext.createChildContext(m.ctx);
            ko.utils.extend(m.childBindingContext, { $page: this });
            if (!m.val('withOnShow')) {
                ko.applyBindingsToDescendants(m.childBindingContext, m.element);
            }

            if (urlToggle !== 'none') {
                // check if this page should trigger showChild at parent
                if (m.parentPage.route && m.parentPage.route[0] === m.getId()) {
                    // call once the current event loop is finished.
                    setTimeout(function () {
                        m.parentPage.showPage(m.parentPage.route);
                    }, 0);
                }
            } else { // urlToggle === 'none'
                // when the page is rendered
                var display = function () {
                    // if the page is visible
                    if ($(m.element).is(':visible')) {
                        // trigger showPage with empty route-array
                        m.showPage([]);
                    }
                };
                setTimeout(display, 0);
                m.getParentPage().isVisible.subscribe(function (x) {
                    if (x) {
                        setTimeout(display, 0);
                    }
                });
            }

            return { controlsDescendantBindings: true };
        };

        p.augmentContext = function () {
            var m = this;
            if (m.val('params')) {
                $.each(this.val('params'), function (index, param) {
                    if (!m.ctx[param]) {
                        m.ctx[param] = ko.observable();
                    }
                });
            }
            if (this.val('vars')) {
                $.each(this.val('vars'), function (key, value) {
                    m.ctx[key] = ko.observable(value);
                });
            }
            this.setParams();
        };
{'fraction_non_alphanumeric': 0.11011718643791293, 'fraction_numerical': 0.0011147665787541803, 'mean_word_length': 1.0524553571428572, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1473660', 'n_tokens_mistral': 9126, 'n_tokens_neox': 8616, 'n_words': 1829}