<commit_before>(function () {

    function getDocument(script) {
        return script ? script.ownerDocument : document;
    }

    function getCurrentScript() {
        var script = window.HTMLImports ? window.HTMLImports.currentScript : undefined;

        if (!script && !!document.currentScript) {
            script = document.currentScript.__importElement || document.currentScript;
        }

        return script;
    }

    var gaScript = getCurrentScript();
    var gaDocument = getDocument(gaScript);
    var serviceUrl = gaScript.getAttribute('serviceurl');
    var trackingId = gaScript.getAttribute('trackingid');
    var pageId = gaScript.getAttribute('pageid');
    var uid = gaDocument.baseURI.split('?uid=')[1].split("&")[0];
    var viewId;
    var dataCharts = [];

// GA API BEGIN

    function queryAccounts() {
        gapi.client.analytics.management.accounts.list().then(handleAccounts);
    }

    function getPropertyUrl(accountId, propertyId) {
        gapi.client.analytics.management.webproperties.get({
            'accountId': accountId,
            'webPropertyId': propertyId
        }).then(function (response) {
            setTitle(response.result.name);
        });
    }

    function handleAccounts(response) {
        // Handles the response from the accounts list method.
        if (response.result.items && response.result.items.length) {
            // Get the first Google Analytics account.
            let accountId;
            if (response.result.items.length == 1) {
                accountId = response.result.items[0];
            }
            else {
                let items = response.result.items.filter(item => (trackingId.indexOf(item.id) > -1));
                if (items[0]) {
                    accountId = items[0].id;
                }
            }

            // Uncomment if we need to show url for selected tracking Id
            //getPropertyUrl(firstAccountId, trackingId);

            if (accountId) {
                // Query for properties.
                queryProfiles(accountId, trackingId);
            }
            else {
                showError('No accounts found for the GA user.');
            }
        } else {
            showError('No accounts found for the GA user.');
        }
    }

    function showRequestError(errorObject) {
        if (errorObject.error && errorObject.error.message) {
            showError(errorObject.error.message);
        }
    }

    function queryProfiles(accountId, propertyId) {
        // Get a list of all Views (Profiles) for the first property
        // of the first Account.
        gapi.client.analytics.management.profiles.list({
            'accountId': accountId,
            'webPropertyId': propertyId
        })
            .then(handleProfiles)
            .then(null, function (err) {
                // Log any errors.
                console.log(err);
                showRequestError(err.result);
            });
    }

    function handleProfiles(response) {
        // Handles the response from the profiles list method.
        if (response.result.items && response.result.items.length) {
            // Get the first View (Profile) ID.
            viewId = "ga:" + response.result.items[0].id;

            initDatePicker();

            // Show statistics for found View ID
            if (pageId) {
                showStatisticsForPage();
            }
            else {
                showStatisticsForSite();
            }
        } else {
            showError('No GA views (profiles) found for the account.');
        }
    }

    function getToken() {
        if (pageId == "-1") {
            showError("GA app not added to the site");
            return;
        }
        if (!serviceUrl) {
            showAuthenticationError();
            return;
        }
        if (!trackingId) {
            showAuthenticationError("Tracking Id not found");
            return;
        }

        var request = new XMLHttpRequest();
        request.open("GET", serviceUrl, true);
        request.onload = function () {
            var responseObject = JSON.parse(request.responseText);
            if (responseObject.errorMessage) {
                showAuthenticationError(responseObject.errorMessage);
            }
            else if (responseObject.token) {

                cleanupCookies();

                setContainerVisible('ga-authenticated', true);
                setContainerVisible('ga-not-authenticated', false);

                createTitle();

                if (pageId) {
                    createContainerDiv("chart-container-1");
                    createContainerDiv("chart-container-2");
                    createContainerDiv("chart-container-3", "ga-kpi-chart");
                }
                else {
                    createContainerDiv("chart-container-1");
                    createContainerDiv("chart-container-2");
                    createContainerDiv("chart-container-2-1", "ga-vertical-container", "chart-container-2");
                    createContainerDiv("chart-container-2-2", "ga-vertical-container", "chart-container-2");

                    createContainerDiv("chart-container-3", "ga-bycountry-container");
                    createContainerDiv("chart-container-4", "ga-bypage-container");
                    createContainerDiv("chart-container-5", "ga-byreferer-container");
                }

                authorize(responseObject.token);
            }
        };
        request.send(null);
    }

    function authorize(token) {
        /**
         * Authorize the user with a token.
         */
        gapi.analytics.auth.authorize({
            serverAuth: {
                access_token: token
            }
        });

        queryAccounts();
    }

// GA API END

// DRAW CHART BEGIN

    function drawChart(containerId, config) {
        var queryCfg = {
            ids: viewId,
            metrics: config.metrics,
            dimensions: config.dimensions
        };

        if (config.filters) {
            queryCfg.filters = config.filters;
        }
        if (config['max-results']) {
            queryCfg['max-results'] = config['max-results'];
        }
        if (config.sort) {
            queryCfg.sort = config.sort;
        }

        var chart = new gapi.analytics.googleCharts.DataChart({
            query: queryCfg,
            chart: {
                container: getContainer(containerId),
                type: config.type,
                options: {
                    title: config.title,
                    width: '100%',
                    is3D: true
                }
            }
        });

        if (config.width) {
            chart.set({chart: {options: {legend: {position: 'none'}, chartArea: {width: config.width}}}});
        }

        dataCharts.push(chart);

        setDateAndDrawChart(chart);
    }

    function setDateAndDrawChart(chart) {
        chart.set(getDateRangeObject()).execute();
    }

    function getDateRangeObject() {
        var startDate = getStartDate(getDateFromCookie('start-date') || '7daysAgo');
        return {
            query: {
                'start-date': startDate,
                'end-date': getDateFromCookie('end-date') || 'today'
            }
        };
    }

    function formatSeconds(seconds) {
        var hours = parseInt(seconds / 3600) % 24;
        var minutes = parseInt(seconds / 60) % 60;
        var seconds = parseInt(seconds % 60);

        return (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" +
               (seconds < 10 ? "0" + seconds : seconds);
    }

    function showStatisticsForPage() {

        /**
         * Line chart by sessions
         */
        drawChart("chart-container-1", {
            title: 'Pageviews by Date',
            type: 'LINE',
            metrics: 'ga:pageViews,ga:uniquePageviews',
            dimensions: 'ga:date',
            filters: 'ga:pagePath==' + pageId
        });

        /**
         * Pie chart by user type (new vs returning)
         */
        drawChart("chart-container-2", {
            title: "Visitors",
            type: 'PIE',
            metrics: 'ga:sessions',
            dimensions: 'ga:userType',
            filters: 'ga:pagePath==' + pageId
        });

        /**
         * Table with avg metrics
         */
        var kpiRequest = new gapi.analytics.report.Data({
            query: {
                ids: viewId,
                metrics: 'ga:avgTimeOnPage,ga:avgPageLoadTime,ga:bounceRate',
                filters: 'ga:pagePath==' + pageId
            }
        });

        dataCharts.push(kpiRequest);

        kpiRequest.on("success", onKPILoaded);

        kpiRequest.set(getDateRangeObject()).execute();
    }

    function onKPILoaded(response) {
        if (response.totalsForAllResults) {
            createContainerDiv("kpi-container-data", "ga-kpi-container-data", "chart-container-3");
            var textContainer = createContainerDiv("kpi-container-text", "ga-kpi-container-text", "chart-container-3");

            var container = createContainerDiv("kpi-container-1", "ga-kpi-container", "kpi-container-data");
            container.innerHTML = "
" + parseFloat(response.totalsForAllResults["ga:avgPageLoadTime"]).toFixed(2) + "
";

            container = createContainerDiv("kpi-container-2", "ga-kpi-container", "kpi-container-data");
            container.innerHTML = "
" + formatSeconds(response.totalsForAllResults["ga:avgTimeOnPage"]) + "
";

            container = createContainerDiv("kpi-container-3", "ga-kpi-container", "kpi-container-data");
            container.innerHTML = "
" + parseFloat(response.totalsForAllResults["ga:bounceRate"]).toFixed(2) + "%
";

            textContainer.innerHTML = "Avg.load time (sec)Avg.time on pageBounce rate";
        }
    }

    function showStatisticsForSite() {
        /**
         * Line chart by sessions
         */
        drawChart("chart-container-1", {
            title: "Site Users",
            type: 'COLUMN',
            metrics: 'ga:Users, ga:newUsers',
            dimensions: 'ga:date'
        });

        /**
         * Pie chart by device
         */
        drawChart("chart-container-2-1", {
            title: "Devices",
            type: 'PIE',
            metrics: 'ga:sessions',
            dimensions: 'ga:deviceCategory',
            width: "90%"
        });

        /**
         * Pie chart by browser
         */
        drawChart("chart-container-2-2", {
            title: "Browsers",
            type: 'PIE',
            metrics: 'ga:sessions',
            dimensions: 'ga:browser',
            width: "90%",
            'sort': '-ga:sessions'
        });

        /**
         * Geo chart by countries
         */
        drawChart("chart-container-3", {
            type: 'GEO',
            metrics: 'ga:users',
            dimensions: 'ga:country'
        });

        /**
         * Table with top 10 pages
         */
        drawChart("chart-container-4", {
            type: 'TABLE',
            metrics: 'ga:uniquePageviews',
            dimensions: 'ga:pagePath',
            'max-results': 10,
            'sort': '-ga:uniquePageviews'
        });

        /**
         * Table with top 10 referers
         */
        drawChart("chart-container-5", {
            type: 'TABLE',
            metrics: 'ga:users',
            dimensions: 'ga:source',
            'max-results': 10,
            'sort': '-ga:users'
        });
    }

// DRAW CHART END

// COOKIES BEGIN

    function createCookie(name, value, days) {
        var expires = "";
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            var expires = "; expires=" + date.toGMTString();
        }

        document.cookie = "ga_" + name + "=" + value + expires + "; path=/";
    }

    function saveUidInCookie() {
        createCookie("uid", uid);
    }

    function saveDateInCookie(date) {
        createCookie(uid + ".start-date", date);
    }

    function getDateFromCookie(name) {
        return getCookie(uid + "." + name);
    }

    function getCookie(cname) {
        var name = "ga_" + cname + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i].trim();
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }

    function cleanupCookies() {
        var tempUid = getCookie("uid");

        if (tempUid && tempUid != uid) {
            createCookie("uid", tempUid, -1);
            createCookie(tempUid + ".start-date", "", -1);
            createCookie(tempUid + ".end-date", "", -1);
        }

        if (!tempUid || tempUid != uid) {
            saveUidInCookie(uid);
        }
    }

// COOKIES END

// DATE PICKER BEGIN

    function dateToString(date) {
        var sDay = (date.getDate() < 10) ? "0" + date.getDate() : date.getDate().toString();
        var sMonth = date.getMonth() + 1;
        sMonth = (sMonth < 10) ? "0" + sMonth : sMonth.toString();

        return date.getFullYear() + "-" + sMonth + "-" + sDay;
    }

    function getFirstDateOfPeriod(delta) {
        var date = new Date;
        date = new Date(date.setDate(date.getDate() - delta + 1));

        return dateToString(date);
    }

    function getFirstDateOfYear() {
        var date = new Date;
        return date.getFullYear() + "-01-01";
    }

    function initDatePicker() {
        var container = getContainer("ga-authenticated").querySelector("#date-range-container");
        var select = container.querySelector("select");
        select.hidden = false;
        if (getDateFromCookie('start-date')) {
            select.value = getDateFromCookie('start-date');
        }
        select.onchange = onDateSelected;
    }

    function getStartDate(date) {
        if (date == "thisWeek") {
            return getFirstDateOfPeriod((new Date).getDay());
        }
        else if (date == "thisMonth") {
            return getFirstDateOfPeriod((new Date).getDate());
        }
        else if (date == "thisYear") {
            return getFirstDateOfYear();
        }

        return date;
    }

    function onDateSelected(e) {
        saveDateInCookie(e.target.value);
        dataCharts.forEach(function (dataChart) {
            setDateAndDrawChart(dataChart);
        });
    }

// DATE PICKER END

// DOM ELEMENTS BEGIN

    function createTitle() {
        var container = getContainer("ga-authenticated").querySelector("#date-range-container");
        var title = container.querySelector("span");
        title.innerHTML = "Statistics for the " + (pageId ? "page" : "site");
    }

    function getContainer(containerId) {
        containerId = containerId + "_" + uid;
        return document.getElementById(containerId) || gaDocument.getElementById(containerId);
    }

    function createContainerDiv(id, cls, parentId) {
        var divId = id + "_" + uid;
        var container = getContainer(parentId || "ga-authenticated");
        var div = container.querySelector("#" + divId);

        if (!div) {
            div = gaDocument.createElement("div");

            div.setAttribute("id", divId);
            if (cls) {
                div.setAttribute("class", cls);
            }
            container.appendChild(div);
        }

        return div;
    }

    function setContainerVisible(containerId, visible) {
        var container = getContainer(containerId);
        if (container) {
            container.hidden = !visible;
        }

        return container;
    }

    function showAuthenticationError(errorMessage) {
        showError("Authentication failed" + (errorMessage ? ": " + errorMessage : ""));
    }

    function showError(errorMessage) {
        setContainerVisible('ga-not-authenticated', true).innerHTML = errorMessage;
        setContainerVisible('ga-authenticated', false);
    }

// DOM ELEMENTS END

    if (gapi.analytics.auth) {
        getToken();
    }
    else {
        gapi.analytics.ready(function () {
            getToken();
        });
    }
}());<commit_msg>Fixed fetching profiles when only one GA account is available<commit_after>(function () {

    function getDocument(script) {
        return script ? script.ownerDocument : document;
    }

    function getCurrentScript() {
        var script = window.HTMLImports ? window.HTMLImports.currentScript : undefined;

        if (!script && !!document.currentScript) {
            script = document.currentScript.__importElement || document.currentScript;
        }

        return script;
    }

    var gaScript = getCurrentScript();
    var gaDocument = getDocument(gaScript);
    var serviceUrl = gaScript.getAttribute('serviceurl');
    var trackingId = gaScript.getAttribute('trackingid');
    var pageId = gaScript.getAttribute('pageid');
    var uid = gaDocument.baseURI.split('?uid=')[1].split("&")[0];
    var viewId;
    var dataCharts = [];

// GA API BEGIN

    function queryAccounts() {
        gapi.client.analytics.management.accounts.list().then(handleAccounts);
    }

    function getPropertyUrl(accountId, propertyId) {
        gapi.client.analytics.management.webproperties.get({
            'accountId': accountId,
            'webPropertyId': propertyId
        }).then(function (response) {
            setTitle(response.result.name);
        });
    }

    function handleAccounts(response) {
        // Handles the response from the accounts list method.
        if (response.result.items && response.result.items.length) {
            // Get the first Google Analytics account.
            let accountId;
            if (response.result.items.length == 1) {
                accountId = response.result.items[0].id;
            }
            else {
                let items = response.result.items.filter(item => (trackingId.indexOf(item.id) > -1));
                if (items[0]) {
                    accountId = items[0].id;
                }
            }

            // Uncomment if we need to show url for selected tracking Id
            //getPropertyUrl(firstAccountId, trackingId);

            if (accountId) {
                // Query for properties.
                queryProfiles(accountId, trackingId);
            }
            else {
                showError('No accounts found for the GA user.');
            }
        } else {
            showError('No accounts found for the GA user.');
        }
    }

    function showRequestError(errorObject) {
        if (errorObject.error && errorObject.error.message) {
            showError(errorObject.error.message);
        }
    }

    function queryProfiles(accountId, propertyId) {
        // Get a list of all Views (Profiles) for the first property
        // of the first Account.
        gapi.client.analytics.management.profiles.list({
            'accountId': accountId,
            'webPropertyId': propertyId
        })
            .then(handleProfiles)
            .then(null, function (err) {
                // Log any errors.
                console.log(err);
                showRequestError(err.result);
            });
    }

    function handleProfiles(response) {
        // Handles the response from the profiles list method.
        if (response.result.items && response.result.items.length) {
            // Get the first View (Profile) ID.
            viewId = "ga:" + response.result.items[0].id;

            initDatePicker();

            // Show statistics for found View ID
            if (pageId) {
                showStatisticsForPage();
            }
            else {
                showStatisticsForSite();
            }
        } else {
            showError('No GA views (profiles) found for the account.');
        }
    }

    function getToken() {
        if (pageId == "-1") {
            showError("GA app not added to the site");
            return;
        }
        if (!serviceUrl) {
            showAuthenticationError();
            return;
        }
        if (!trackingId) {
            showAuthenticationError("Tracking Id not found");
            return;
        }

        var request = new XMLHttpRequest();
        request.open("GET", serviceUrl, true);
        request.onload = function () {
            var responseObject = JSON.parse(request.responseText);
            if (responseObject.errorMessage) {
                showAuthenticationError(responseObject.errorMessage);
            }
            else if (responseObject.token) {

                cleanupCookies();

                setContainerVisible('ga-authenticated', true);
                setContainerVisible('ga-not-authenticated', false);

                createTitle();

                if (pageId) {
                    createContainerDiv("chart-container-1");
                    createContainerDiv("chart-container-2");
                    createContainerDiv("chart-container-3", "ga-kpi-chart");
                }
                else {
                    createContainerDiv("chart-container-1");
                    createContainerDiv("chart-container-2");
                    createContainerDiv("chart-container-2-1", "ga-vertical-container", "chart-container-2");
                    createContainerDiv("chart-container-2-2", "ga-vertical-container", "chart-container-2");

                    createContainerDiv("chart-container-3", "ga-bycountry-container");
                    createContainerDiv("chart-container-4", "ga-bypage-container");
                    createContainerDiv("chart-container-5", "ga-byreferer-container");
                }

                authorize(responseObject.token);
            }
        };
        request.send(null);
    }

    function authorize(token) {
        /**
         * Authorize the user with a token.
         */
        gapi.analytics.auth.authorize({
            serverAuth: {
                access_token: token
            }
        });

        queryAccounts();
    }

// GA API END

// DRAW CHART BEGIN

    function drawChart(containerId, config) {
        var queryCfg = {
            ids: viewId,
            metrics: config.metrics,
            dimensions: config.dimensions
        };

        if (config.filters) {
            queryCfg.filters = config.filters;
        }
        if (config['max-results']) {
            queryCfg['max-results'] = config['max-results'];
        }
        if (config.sort) {
            queryCfg.sort = config.sort;
        }

        var chart = new gapi.analytics.googleCharts.DataChart({
            query: queryCfg,
            chart: {
                container: getContainer(containerId),
                type: config.type,
                options: {
                    title: config.title,
                    width: '100%',
                    is3D: true
                }
            }
        });

        if (config.width) {
            chart.set({chart: {options: {legend: {position: 'none'}, chartArea: {width: config.width}}}});
        }

        dataCharts.push(chart);

        setDateAndDrawChart(chart);
    }

    function setDateAndDrawChart(chart) {
        chart.set(getDateRangeObject()).execute();
    }

    function getDateRangeObject() {
        var startDate = getStartDate(getDateFromCookie('start-date') || '7daysAgo');
        return {
            query: {
                'start-date': startDate,
                'end-date': getDateFromCookie('end-date') || 'today'
            }
        };
    }

    function formatSeconds(seconds) {
        var hours = parseInt(seconds / 3600) % 24;
        var minutes = parseInt(seconds / 60) % 60;
        var seconds = parseInt(seconds % 60);

        return (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" +
               (seconds < 10 ? "0" + seconds : seconds);
    }

    function showStatisticsForPage() {

        /**
         * Line chart by sessions
         */
        drawChart("chart-container-1", {
            title: 'Pageviews by Date',
            type: 'LINE',
            metrics: 'ga:pageViews,ga:uniquePageviews',
            dimensions: 'ga:date',
            filters: 'ga:pagePath==' + pageId
        });

        /**
         * Pie chart by user type (new vs returning)
         */
        drawChart("chart-container-2", {
            title: "Visitors",
            type: 'PIE',
            metrics: 'ga:sessions',
            dimensions: 'ga:userType',
            filters: 'ga:pagePath==' + pageId
        });

        /**
         * Table with avg metrics
         */
        var kpiRequest = new gapi.analytics.report.Data({
            query: {
                ids: viewId,
                metrics: 'ga:avgTimeOnPage,ga:avgPageLoadTime,ga:bounceRate',
                filters: 'ga:pagePath==' + pageId
            }
        });

        dataCharts.push(kpiRequest);

        kpiRequest.on("success", onKPILoaded);

        kpiRequest.set(getDateRangeObject()).execute();
    }

    function onKPILoaded(response) {
        if (response.totalsForAllResults) {
            createContainerDiv("kpi-container-data", "ga-kpi-container-data", "chart-container-3");
            var textContainer = createContainerDiv("kpi-container-text", "ga-kpi-container-text", "chart-container-3");

            var container = createContainerDiv("kpi-container-1", "ga-kpi-container", "kpi-container-data");
            container.innerHTML = "
" + parseFloat(response.totalsForAllResults["ga:avgPageLoadTime"]).toFixed(2) + "
";

            container = createContainerDiv("kpi-container-2", "ga-kpi-container", "kpi-container-data");
            container.innerHTML = "
" + formatSeconds(response.totalsForAllResults["ga:avgTimeOnPage"]) + "
";

            container = createContainerDiv("kpi-container-3", "ga-kpi-container", "kpi-container-data");
            container.innerHTML = "
" + parseFloat(response.totalsForAllResults["ga:bounceRate"]).toFixed(2) + "%
";

            textContainer.innerHTML = "Avg.load time (sec)Avg.time on pageBounce rate";
        }
    }

    function showStatisticsForSite() {
        /**
         * Line chart by sessions
         */
        drawChart("chart-container-1", {
            title: "Site Users",
            type: 'COLUMN',
            metrics: 'ga:Users, ga:newUsers',
            dimensions: 'ga:date'
        });

        /**
         * Pie chart by device
         */
        drawChart("chart-container-2-1", {
            title: "Devices",
            type: 'PIE',
            metrics: 'ga:sessions',
            dimensions: 'ga:deviceCategory',
            width: "90%"
        });

        /**
         * Pie chart by browser
         */
        drawChart("chart-container-2-2", {
            title: "Browsers",
            type: 'PIE',
            metrics: 'ga:sessions',
            dimensions: 'ga:browser',
            width: "90%",
            'sort': '-ga:sessions'
        });

        /**
         * Geo chart by countries
         */
        drawChart("chart-container-3", {
            type: 'GEO',
            metrics: 'ga:users',
            dimensions: 'ga:country'
        });

        /**
         * Table with top 10 pages
         */
        drawChart("chart-container-4", {
            type: 'TABLE',
            metrics: 'ga:uniquePageviews',
            dimensions: 'ga:pagePath',
            'max-results': 10,
            'sort': '-ga:uniquePageviews'
        });

        /**
         * Table with top 10 referers
         */
        drawChart("chart-container-5", {
            type: 'TABLE',
            metrics: 'ga:users',
            dimensions: 'ga:source',
            'max-results': 10,
            'sort': '-ga:users'
        });
    }

// DRAW CHART END

// COOKIES BEGIN

    function createCookie(name, value, days) {
        var expires = "";
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            var expires = "; expires=" + date.toGMTString();
        }

        document.cookie = "ga_" + name + "=" + value + expires + "; path=/";
    }

    function saveUidInCookie() {
        createCookie("uid", uid);
    }

    function saveDateInCookie(date) {
        createCookie(uid + ".start-date", date);
    }

    function getDateFromCookie(name) {
        return getCookie(uid + "." + name);
    }

    function getCookie(cname) {
        var name = "ga_" + cname + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i].trim();
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }

    function cleanupCookies() {
        var tempUid = getCookie("uid");

        if (tempUid && tempUid != uid) {
            createCookie("uid", tempUid, -1);
            createCookie(tempUid + ".start-date", "", -1);
            createCookie(tempUid + ".end-date", "", -1);
        }

        if (!tempUid || tempUid != uid) {
            saveUidInCookie(uid);
        }
    }

// COOKIES END

// DATE PICKER BEGIN

    function dateToString(date) {
        var sDay = (date.getDate() < 10) ? "0" + date.getDate() : date.getDate().toString();
        var sMonth = date.getMonth() + 1;
        sMonth = (sMonth < 10) ? "0" + sMonth : sMonth.toString();

        return date.getFullYear() + "-" + sMonth + "-" + sDay;
    }

    function getFirstDateOfPeriod(delta) {
        var date = new Date;
        date = new Date(date.setDate(date.getDate() - delta + 1));

        return dateToString(date);
    }

    function getFirstDateOfYear() {
        var date = new Date;
        return date.getFullYear() + "-01-01";
    }

    function initDatePicker() {
        var container = getContainer("ga-authenticated").querySelector("#date-range-container");
        var select = container.querySelector("select");
        select.hidden = false;
        if (getDateFromCookie('start-date')) {
            select.value = getDateFromCookie('start-date');
        }
        select.onchange = onDateSelected;
    }

    function getStartDate(date) {
        if (date == "thisWeek") {
            return getFirstDateOfPeriod((new Date).getDay());
        }
        else if (date == "thisMonth") {
            return getFirstDateOfPeriod((new Date).getDate());
        }
        else if (date == "thisYear") {
            return getFirstDateOfYear();
        }

        return date;
    }

    function onDateSelected(e) {
        saveDateInCookie(e.target.value);
        dataCharts.forEach(function (dataChart) {
            setDateAndDrawChart(dataChart);
        });
    }

// DATE PICKER END

// DOM ELEMENTS BEGIN

    function createTitle() {
        var container = getContainer("ga-authenticated").querySelector("#date-range-container");
        var title = container.querySelector("span");
        title.innerHTML = "Statistics for the " + (pageId ? "page" : "site");
    }

    function getContainer(containerId) {
        containerId = containerId + "_" + uid;
        return document.getElementById(containerId) || gaDocument.getElementById(containerId);
    }

    function createContainerDiv(id, cls, parentId) {
        var divId = id + "_" + uid;
        var container = getContainer(parentId || "ga-authenticated");
        var div = container.querySelector("#" + divId);

        if (!div) {
            div = gaDocument.createElement("div");

            div.setAttribute("id", divId);
            if (cls) {
                div.setAttribute("class", cls);
            }
            container.appendChild(div);
        }

        return div;
    }

    function setContainerVisible(containerId, visible) {
        var container = getContainer(containerId);
        if (container) {
            container.hidden = !visible;
        }

        return container;
    }

    function showAuthenticationError(errorMessage) {
        showError("Authentication failed" + (errorMessage ? ": " + errorMessage : ""));
    }

    function showError(errorMessage) {
        setContainerVisible('ga-not-authenticated', true).innerHTML = errorMessage;
        setContainerVisible('ga-authenticated', false);
    }

// DOM ELEMENTS END

    if (gapi.analytics.auth) {
        getToken();
    }
    else {
        gapi.analytics.ready(function () {
            getToken();
        });
    }
}());<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var assert = require('power-assert');

describe('fetch()', function () {
    describe('', function () {
    });
});
<commit_msg>Add: fetch() test<commit_after>'use strict';

/**
 * Module dependencies.
 */
var assert = require('power-assert');
var contributions = require('../github-contributions.js');

describe('github-contributions', function () {
    describe('fetch()', function () {
        var status = 0;

        it('Response should be status 200', function (done) {
            contributions.fetch('kubosho', function(res, statusCode) {
                done();
                assert(statusCode === 200);
            })
        });

        it('Response should be status 404', function (done) {
            contributions.fetch('_', function(res, statusCode) {
                done();
                assert(statusCode === 404);
            })
        });
    });
});
<|endoftext|>


<commit_before>'use strict'

import React, { Component } from 'react'
import ReactCSS from 'reactcss'

import colors from '../../assets/styles/variables/colors'
import { spacing } from '../../assets/styles/variables/utils'

import { Button, Icon } from '../common/index'
import AliasContainer from '../../containers/AliasContainer'

import { generateKey } from '../../utils/pgp'

class Header extends Component {
  classes() {
    return {
      'default': {
        header: {
          background: colors.bgDark,
          display: 'flex',
          justifyContent: 'space-between',
          padding: `${spacing.m + spacing.statusBarHeight }px ${spacing.m}px ${spacing.m}px`,
        },
        actions: {
          display: 'flex',
          alignItems: 'center',
        },
        icon: {
          width: '24px',
        },
        Decrypt: {
          background: colors.primaryGradient, // TODO: File issue as this should work
          color: colors.bgDark,
        },
      },
    }
  }

  render() {

    return (

        <AliasContainer />

            <Icon name="more" color="#F4C97A"/>

    )
  }
}

export default ReactCSS(Header)
<commit_msg>Update header<commit_after>'use strict'

import React, { Component } from 'react'
import ReactCSS from 'reactcss'

import colors from '../../assets/styles/variables/colors'
import { spacing } from '../../assets/styles/variables/utils'

import { Button, Icon } from '../common/index'
import Alias from '../alias/Alias'
import HeaderKeyStatus from './HeaderKeyStatus'

import { generateKey } from '../../utils/pgp'

class Header extends Component {
  classes() {
    return {
      'default': {
        header: {
          background: colors.bgDark,
          display: 'flex',
          justifyContent: 'space-between',
          padding: `${spacing.m + spacing.statusBarHeight }px ${spacing.m}px ${spacing.m}px`,
        },
        actions: {
          display: 'flex',
          alignItems: 'center',
        },
        icon: {
          width: '24px',
          marginBottom: '2px',
        },
        Decrypt: {
          background: colors.primaryGradient, // TODO: File issue as this should work
          color: colors.bgDark,
        },
      },
    }
  }

  componentDidMount = () => {
    this.props.showComposer('alias')
  }

  counter = 0

  componentDidUpdate = (prevProps) => {
    console.log(prevProps.alias.privateKeyArmored)
    this.counter++
    if (prevProps.alias.privateKeyArmored !== this.props.alias.privateKeyArmored && this.counter < 3) {
      this.props.toggleComposer()
    }
  }

  render() {

    return (

        <Alias
          {...this.props }
        />

            <HeaderKeyStatus
              {...this.props }
            />

    )
  }
}

export default ReactCSS(Header)
<|endoftext|>


<commit_before>var Mappings = {};

Mappings.repeats = "";
Mappings.queue = "";

Mappings.actions = {
  goToRootUrl: function() {
    if (window.location.pathname.length === 0 || window.location.pathname === "/") {
      return false;
    }
    return chrome.runtime.sendMessage({action: "openLink", url: window.location.origin});
  },
  goUpUrl: function(repeats) {
    var rxp = new RegExp("(\/([^\/])+){0," + repeats + "}(\/)?$");
    if (window.location.pathname.length === 0 || window.location.pathname === "/") {
      return false;
    }
    var match = window.location.pathname.replace(rxp, "");
    if (match === window.location.pathname) {
      return false;
    }
    return chrome.runtime.sendMessage({action: "openLink", url: window.location.origin + match});
  },
  closeTab: function(repeats) {
    return chrome.runtime.sendMessage({action: "closeTab", repeats: repeats});
  },
  pinTab: function() {
    return chrome.runtime.sendMessage({action: "pinTab"});
  },
  firstTab: function() {
    return chrome.runtime.sendMessage({action: "firstTab"});
  },
  lastTab: function() {
    return chrome.runtime.sendMessage({action: "lastTab"});
  },
  moveTabRight: function(repeats) {
    return chrome.runtime.sendMessage({action: "moveTabRight", repeats: repeats});
  },
  moveTabLeft: function(repeats) {
    return chrome.runtime.sendMessage({action: "moveTabLeft", repeats: repeats});
  },
  reverseImage: function() {
    if (document.body.childNodes.length === 1 && document.body.firstChild.nodeName === "IMG") {
      if (document.body.firstChild.src) {
        return chrome.runtime.sendMessage({action: "openLinkTab", url: "https://www.google.com/searchbyimage?image_url=" + document.body.firstChild.src});
      }
    } else {
      setTimeout(function() {
        Hints.create(true, false, true);
      }, 0);
    }
  },
  scrollMouseH: function() {
    return document.body.scrollTop = Mouse.y - window.innerHeight / 2;
  },
  scrollMouseT: function() {
    return document.body.scrollTop = Mouse.y;
  },
  scrollMouseB: function() {
    return document.body.scrollTop = Mouse.y - window.innerHeight + 25;
  },
  scrollDown: function(repeats) {
    return Scroll.scroll("down", repeats);
  },
  scrollUp: function(repeats) {
    return Scroll.scroll("up", repeats);
  },
  scrollPageDown: function(repeats) {
    return Scroll.scroll("pageDown", repeats);
  },
  scrollPageUp: function(repeats) {
    return Scroll.scroll("pageUp", repeats);
  },
  scrollLeft: function(repeats) {
    return Scroll.scroll("left", repeats);
  },
  scrollRight: function(repeats) {
    return Scroll.scroll("right", repeats);
  },
  scrollToTop: function() {
    return Scroll.scroll("top");
  },
  scrollToBottom: function() {
    return Scroll.scroll("bottom");
  },
  createHint: function() {
    setTimeout(function() {
      return Hints.create();
    }, 0);
  },
  createTabbedHint: function() {
    setTimeout(function() {
      return Hints.create(true);
    }, 0);
  },
  yankUrl: function() {
    setTimeout(function() {
      return Hints.create(true, true);
    }, 0);
  },
  yankDocumentUrl: function() {
    return Clipboard.copy(document.URL);
  },
  openPaste: function() {
    return Clipboard.paste(false);
  },
  openPasteTab: function() {
    return Clipboard.paste(true);
  },
  insertMode: function() {
    return insertMode = true;
  },
  reloadTab: function() {
    return chrome.runtime.sendMessage({action: "reloadTab"});
  },
  nextSearchResult: function(repeats) {
    if (Command.type === "search" || Find.matches.length) {
      return Find.search(false, repeats);
    }
  },
  previousSearchResult: function(repeats) {
    if (Command.type === "search" || Find.matches.length) {
      return Find.search(true, repeats);
    }
  },
  nextTab: function(r) {
    return chrome.runtime.sendMessage({action: "nextTab", repeats: r});
  },
  previousTab: function(r) {
    return chrome.runtime.sendMessage({action: "previousTab", repeats: r});
  },
  goBack: function(repeats) {
    return history.go(-1 * repeats);
  },
  goForward: function(repeats) {
    return history.go(1 * repeats);
  },
  goToSource: function() {
    return chrome.runtime.sendMessage({action: "openLinkTab", url: "view-source:" + document.URL});
  },
  goToInput: function(repeats) {
    this.inputElements = [];
    var allInput = document.querySelectorAll("input,textarea");
    for (var i = 0, l = allInput.length; i < l; i++) {
      if (allInput[i].isInput() && allInput[i].isVisible() && allInput[i].id !== "command_input") {
        this.inputElements.push(allInput[i]);
      }
    }
    this.inputElementsIndex = repeats % this.inputElements.length;
    this.inputFocused = true;
    if (this.inputElements.length) {
      insertMode = true;
      return this.inputElements[this.inputElementsIndex].focus();
    }
  },
  shortCuts: function(s, repeats) {
    for (var i = 0, l = Mappings.shortCuts.length; i < l; i++) {
      if (s === Mappings.shortCuts[i][0]) {
        commandMode = true;
        Command.show(false, Mappings.shortCuts[i][1].replace(/^:/, "").replace(/<cr>(\s+)?$/i, ""));
        if (/<cr>(\s+)?$/i.test(Mappings.shortCuts[i][1])) {
          return Command.parse(Command.input.value, true, repeats);
        }
        return Command.parse(Command.input.value, false, repeats);
      }
    }
  },
  openSearchBar: function() {
    Command.hide();
    commandMode = true;
    Command.enterHit = false;
    return Command.show(true);
  },
  openCommandBar: function() {
    Command.hide();
    commandMode = true;
    Command.enterHit = false;
    return Command.show(false);
  }
};

Mappings.shortCuts = [
  ["o", ":open "],
  ["O", ":tabopen "],
  ["b", ":bookmarks "],
  ["t", ":tabopen "],
  ["I", ":history "],
  ["T", ":tabopen<cr>"],
  ["gd", ":tabopen chrome://downloads<cr>"]
];

Mappings.defaults = {
  closeTab: ["x"],
  scrollDown: ["s", "j"],
  scrollUp: ["w", "k"],
  scrollPageUp: ["e", "u"],
  scrollPageDown: ["d"],
  scrollToTop: ["gg"],
  scrollToBottom: ["G"],
  scrollLeft: ["h"],
  scrollRight: ["l"],
  insertMode: ["i"],
  reloadTab: ["r"],
  createHint: ["f"],
  pinTab: ["gp"],
  moveTabRight: [">"],
  moveTabLeft: ["<"],
  goBack: ["H", "S"],
  reverseImage: ["gr"],
  goForward: ["L", "D"],
  firstTab: ["g0"],
  lastTab: ["g$"],
  createTabbedHint: ["F"],
  goToInput: ["gi"],
  nextTab: ["K", "R", "gt"],
  scrollMouseT: ["zt"],
  scrollMouseB: ["zb"],
  scrollMouseH: ["zz"],
  goToSource: ["gs"],
  goToRootUrl: ["gU"],
  goUpUrl: ["gu"],
  yankUrl: ["Y"],
  yankDocumentUrl: ["yy"],
  openPaste: ["p"],
  openPasteTab: ["P"],
  previousTab: ["J", "E", "gT"],
  nextSearchResult: ["n"],
  previousSearchResult: ["N"],
  openSearchBar: ["/"],
  openCommandBar: [":"],
  shortCuts: []
}

Mappings.isValidQueue = function(c) {
  for (var key in this.defaults) {
    if (this.defaults.hasOwnProperty(key)) {
      for (var i = 0, l = this.defaults[key].length; i < l; i++) {
        if (this.defaults[key][i].substring(0, Mappings.queue.length) === Mappings.queue) {
          return true;
        }
      }
    }
  }
};

Mappings.parseCustom = function(config) {
  if (!/\n/.test(config)) {
    config = [config];
  } else {
    config = config.split("\n");
  }
  var keywords = [
    /^(\s+)?map /i,
    /^(\s+)?unmap /i
  ];
  var m = [];
  var u = [];
  for (var i = 0, l = config.length; i < l; i++) {
    for (var j = 0; j < keywords.length; j++) {
      if (keywords[j].test(config[i])) {
        var maps = config[i].split(/(\s+)/).filter(function(m) {
          if (!/(\s+)/.test(m)) {
            return m;
          }
        });
        if (maps.length === 3 || (maps.length >= 3 && /^:/.test(maps[2]))) {
          if (maps[0].toLowerCase() === "map") {
            if (maps.length > 3) {
              var c = "";
              for (var k = 3; k < maps.length; k++) {
                c += " " + maps[k];
              }
              m.push([maps[1], maps[2] + c]);
            } else {
              m.push([maps[1], maps[2]]);
            }
          }
        } else if (maps.length === 2 && maps[0].toLowerCase() === "unmap") {
          u.push(maps[1]);
        }
      }
    }
  }
  for (var i = 0; i < u.length; i++) {
    for (var key in this.defaults) {
      for (var j = 0; j < this.defaults[key].length; j++) {
        if (this.defaults[key][j] === u[i]) {
          this.defaults[key].splice(j, 1);
        }
      }
    }
  }
  for (var i = 0; i < m.length; i++) {
    if (m[i][1][0] === ":") {
      this.shortCuts.push([m[i][0], m[i][1]]);
    } else {
      for (var key in this.defaults) {
        if (key.toLowerCase() === m[i][1].toLowerCase()) {
          this.defaults[key].push(m[i][0]);
        }
      }
    }
  }
  for (var i = 0, l = Mappings.shortCuts.length; i < l; i++) {
    Mappings.defaults.shortCuts.push(Mappings.shortCuts[i][0]);
  }
};

Mappings.convertToAction = function(c) {
  if (!c) {
    return;
  } else if (Hints.active) {
    Hints.handleHint(c);
  } else if (Mappings.queue === "" && /[0-9]/.test(c)) {
    Mappings.repeats += c;
  } else {
    Mappings.queue += c;
    for (var key in this.defaults) {
      if (this.defaults.hasOwnProperty(key)) {
        if (!this.isValidQueue(c)) {
          Mappings.queue = "";
          Mappings.repeats = "";
        } else {
          for (var i = 0, l = this.defaults[key].length; i < l; i++) {
            if (Mappings.queue === this.defaults[key][i]) {
              if (Mappings.repeats === "0" || Mappings.repeats === "") {
                Mappings.repeats = "1";
              }
              if (key === "shortCuts") {
                Mappings.actions[key](Mappings.queue, parseInt(Mappings.repeats));
                Mappings.queue = "";
                return Mappings.repeats = "";
              }
              Mappings.actions[key](parseInt(Mappings.repeats));
              Mappings.queue = "";
              return Mappings.repeats = "";
            }
          }
        }
      }
    }
  }
};
<commit_msg>Fixed input element index<commit_after>var Mappings = {};

Mappings.repeats = "";
Mappings.queue = "";

Mappings.actions = {
  goToRootUrl: function() {
    if (window.location.pathname.length === 0 || window.location.pathname === "/") {
      return false;
    }
    return chrome.runtime.sendMessage({action: "openLink", url: window.location.origin});
  },
  goUpUrl: function(repeats) {
    var rxp = new RegExp("(\/([^\/])+){0," + repeats + "}(\/)?$");
    if (window.location.pathname.length === 0 || window.location.pathname === "/") {
      return false;
    }
    var match = window.location.pathname.replace(rxp, "");
    if (match === window.location.pathname) {
      return false;
    }
    return chrome.runtime.sendMessage({action: "openLink", url: window.location.origin + match});
  },
  closeTab: function(repeats) {
    return chrome.runtime.sendMessage({action: "closeTab", repeats: repeats});
  },
  pinTab: function() {
    return chrome.runtime.sendMessage({action: "pinTab"});
  },
  firstTab: function() {
    return chrome.runtime.sendMessage({action: "firstTab"});
  },
  lastTab: function() {
    return chrome.runtime.sendMessage({action: "lastTab"});
  },
  moveTabRight: function(repeats) {
    return chrome.runtime.sendMessage({action: "moveTabRight", repeats: repeats});
  },
  moveTabLeft: function(repeats) {
    return chrome.runtime.sendMessage({action: "moveTabLeft", repeats: repeats});
  },
  reverseImage: function() {
    if (document.body.childNodes.length === 1 && document.body.firstChild.nodeName === "IMG") {
      if (document.body.firstChild.src) {
        return chrome.runtime.sendMessage({action: "openLinkTab", url: "https://www.google.com/searchbyimage?image_url=" + document.body.firstChild.src});
      }
    } else {
      setTimeout(function() {
        Hints.create(true, false, true);
      }, 0);
    }
  },
  scrollMouseH: function() {
    return document.body.scrollTop = Mouse.y - window.innerHeight / 2;
  },
  scrollMouseT: function() {
    return document.body.scrollTop = Mouse.y;
  },
  scrollMouseB: function() {
    return document.body.scrollTop = Mouse.y - window.innerHeight + 25;
  },
  scrollDown: function(repeats) {
    return Scroll.scroll("down", repeats);
  },
  scrollUp: function(repeats) {
    return Scroll.scroll("up", repeats);
  },
  scrollPageDown: function(repeats) {
    return Scroll.scroll("pageDown", repeats);
  },
  scrollPageUp: function(repeats) {
    return Scroll.scroll("pageUp", repeats);
  },
  scrollLeft: function(repeats) {
    return Scroll.scroll("left", repeats);
  },
  scrollRight: function(repeats) {
    return Scroll.scroll("right", repeats);
  },
  scrollToTop: function() {
    return Scroll.scroll("top");
  },
  scrollToBottom: function() {
    return Scroll.scroll("bottom");
  },
  createHint: function() {
    setTimeout(function() {
      return Hints.create();
    }, 0);
  },
  createTabbedHint: function() {
    setTimeout(function() {
      return Hints.create(true);
    }, 0);
  },
  yankUrl: function() {
    setTimeout(function() {
      return Hints.create(true, true);
    }, 0);
  },
  yankDocumentUrl: function() {
    return Clipboard.copy(document.URL);
  },
  openPaste: function() {
    return Clipboard.paste(false);
  },
  openPasteTab: function() {
    return Clipboard.paste(true);
  },
  insertMode: function() {
    return insertMode = true;
  },
  reloadTab: function() {
    return chrome.runtime.sendMessage({action: "reloadTab"});
  },
  nextSearchResult: function(repeats) {
    if (Command.type === "search" || Find.matches.length) {
      return Find.search(false, repeats);
    }
  },
  previousSearchResult: function(repeats) {
    if (Command.type === "search" || Find.matches.length) {
      return Find.search(true, repeats);
    }
  },
  nextTab: function(r) {
    return chrome.runtime.sendMessage({action: "nextTab", repeats: r});
  },
  previousTab: function(r) {
    return chrome.runtime.sendMessage({action: "previousTab", repeats: r});
  },
  goBack: function(repeats) {
    return history.go(-1 * repeats);
  },
  goForward: function(repeats) {
    return history.go(1 * repeats);
  },
  goToSource: function() {
    return chrome.runtime.sendMessage({action: "openLinkTab", url: "view-source:" + document.URL});
  },
  goToInput: function(repeats) {
    this.inputElements = [];
    var allInput = document.querySelectorAll("input,textarea");
    for (var i = 0, l = allInput.length; i < l; i++) {
      if (allInput[i].isInput() && allInput[i].isVisible() && allInput[i].id !== "command_input") {
        this.inputElements.push(allInput[i]);
      }
    }
    if (this.inputElements.length === 0) return false;
    this.inputElementsIndex = repeats % this.inputElements.length - 1;
    if (this.inputElementsIndex < 0) this.inputElementsIndex = 0;
    for (var i = 0, l = this.inputElements.length; i < l; i++) {
      var br = this.inputElements[i].getBoundingClientRect();
      if (br.top + br.height >= 0 && br.left + br.width >= 0 && br.right - br.width <= window.innerWidth && br.top < window.innerHeight) {
        this.inputElementsIndex = i;
        break;
      }
    }
    log(this.inputElementsIndex);
    this.inputFocused = true;
    insertMode = true;
    this.inputElements[this.inputElementsIndex].focus();
  },
  shortCuts: function(s, repeats) {
    for (var i = 0, l = Mappings.shortCuts.length; i < l; i++) {
      if (s === Mappings.shortCuts[i][0]) {
        commandMode = true;
        Command.show(false, Mappings.shortCuts[i][1].replace(/^:/, "").replace(/<cr>(\s+)?$/i, ""));
        if (/<cr>(\s+)?$/i.test(Mappings.shortCuts[i][1])) {
          return Command.parse(Command.input.value, true, repeats);
        }
        return Command.parse(Command.input.value, false, repeats);
      }
    }
  },
  openSearchBar: function() {
    Command.hide();
    commandMode = true;
    Command.enterHit = false;
    return Command.show(true);
  },
  openCommandBar: function() {
    Command.hide();
    commandMode = true;
    Command.enterHit = false;
    return Command.show(false);
  }
};

Mappings.shortCuts = [
  ["o", ":open "],
  ["O", ":tabopen "],
  ["b", ":bookmarks "],
  ["t", ":tabopen "],
  ["I", ":history "],
  ["T", ":tabopen<cr>"],
  ["gd", ":tabopen chrome://downloads<cr>"]
];

Mappings.defaults = {
  closeTab: ["x"],
  scrollDown: ["s", "j"],
  scrollUp: ["w", "k"],
  scrollPageUp: ["e", "u"],
  scrollPageDown: ["d"],
  scrollToTop: ["gg"],
  scrollToBottom: ["G"],
  scrollLeft: ["h"],
  scrollRight: ["l"],
  insertMode: ["i"],
  reloadTab: ["r"],
  createHint: ["f"],
  pinTab: ["gp"],
  moveTabRight: [">"],
  moveTabLeft: ["<"],
  goBack: ["H", "S"],
  reverseImage: ["gr"],
  goForward: ["L", "D"],
  firstTab: ["g0"],
  lastTab: ["g$"],
  createTabbedHint: ["F"],
  goToInput: ["gi"],
  nextTab: ["K", "R", "gt"],
  scrollMouseT: ["zt"],
  scrollMouseB: ["zb"],
  scrollMouseH: ["zz"],
  goToSource: ["gs"],
  goToRootUrl: ["gU"],
  goUpUrl: ["gu"],
  yankUrl: ["Y"],
  yankDocumentUrl: ["yy"],
  openPaste: ["p"],
  openPasteTab: ["P"],
  previousTab: ["J", "E", "gT"],
  nextSearchResult: ["n"],
  previousSearchResult: ["N"],
  openSearchBar: ["/"],
  openCommandBar: [":"],
  shortCuts: []
}

Mappings.isValidQueue = function(c) {
  for (var key in this.defaults) {
    if (this.defaults.hasOwnProperty(key)) {
      for (var i = 0, l = this.defaults[key].length; i < l; i++) {
        if (this.defaults[key][i].substring(0, Mappings.queue.length) === Mappings.queue) {
          return true;
        }
      }
    }
  }
};

Mappings.parseCustom = function(config) {
  if (!/\n/.test(config)) {
    config = [config];
  } else {
    config = config.split("\n");
  }
  var keywords = [
    /^(\s+)?map /i,
    /^(\s+)?unmap /i
  ];
  var m = [];
  var u = [];
  for (var i = 0, l = config.length; i < l; i++) {
    for (var j = 0; j < keywords.length; j++) {
      if (keywords[j].test(config[i])) {
        var maps = config[i].split(/(\s+)/).filter(function(m) {
          if (!/(\s+)/.test(m)) {
            return m;
          }
        });
        if (maps.length === 3 || (maps.length >= 3 && /^:/.test(maps[2]))) {
          if (maps[0].toLowerCase() === "map") {
            if (maps.length > 3) {
              var c = "";
              for (var k = 3; k < maps.length; k++) {
                c += " " + maps[k];
              }
              m.push([maps[1], maps[2] + c]);
            } else {
              m.push([maps[1], maps[2]]);
            }
          }
        } else if (maps.length === 2 && maps[0].toLowerCase() === "unmap") {
          u.push(maps[1]);
        }
      }
    }
  }
  for (var i = 0; i < u.length; i++) {
    for (var key in this.defaults) {
      for (var j = 0; j < this.defaults[key].length; j++) {
        if (this.defaults[key][j] === u[i]) {
          this.defaults[key].splice(j, 1);
        }
      }
    }
  }
  for (var i = 0; i < m.length; i++) {
    if (m[i][1][0] === ":") {
      this.shortCuts.push([m[i][0], m[i][1]]);
    } else {
      for (var key in this.defaults) {
        if (key.toLowerCase() === m[i][1].toLowerCase()) {
          this.defaults[key].push(m[i][0]);
        }
      }
    }
  }
  for (var i = 0, l = Mappings.shortCuts.length; i < l; i++) {
    Mappings.defaults.shortCuts.push(Mappings.shortCuts[i][0]);
  }
};

Mappings.convertToAction = function(c) {
  if (!c) {
    return;
  } else if (Hints.active) {
    Hints.handleHint(c);
  } else if (Mappings.queue === "" && /[0-9]/.test(c)) {
    Mappings.repeats += c;
  } else {
    Mappings.queue += c;
    for (var key in this.defaults) {
      if (this.defaults.hasOwnProperty(key)) {
        if (!this.isValidQueue(c)) {
          Mappings.queue = "";
          Mappings.repeats = "";
        } else {
          for (var i = 0, l = this.defaults[key].length; i < l; i++) {
            if (Mappings.queue === this.defaults[key][i]) {
              if (Mappings.repeats === "0" || Mappings.repeats === "") {
                Mappings.repeats = "1";
              }
              if (key === "shortCuts") {
                Mappings.actions[key](Mappings.queue, parseInt(Mappings.repeats));
                Mappings.queue = "";
                return Mappings.repeats = "";
              }
              Mappings.actions[key](parseInt(Mappings.repeats));
              Mappings.queue = "";
              return Mappings.repeats = "";
            }
          }
        }
      }
    }
  }
};
<|endoftext|>


<commit_before>describe('ns.View.events', function() {

    function genTests(defs) {
        for (var i = 0, j = defs.length; i < j; i++) {
            var def = defs[i];
            (function(view, event, check, not) {
                it('should ' + (not == false ? 'not ': '') + ' trigger "' + event + '" for "' + view + '" (' + check + ')', function() {
                    var spyName = view + '-' + event + '-spy';
                    if (not === false) {
                        expect(this.events[spyName][check]).to.not.be.ok();
                    } else {
                        expect(this.events[spyName][check]).to.be.ok();
                    }
                });
            })(def[0], def[1], def[2], def[3]);

        }
    }

    function genOrderTests(defs) {
        for (var i = 0, j = defs.length - 1; i < j; i++) {
            var def = defs[i];
            var defNext = defs[i + 1];
            (function(view, event, pos, nextView, nextEvent, nextPos) {
                it('should trigger "'+event+'" for "'+view+'" before "'+nextEvent+'" for "'+nextView+'" ', function() {
                    var spyName = view + '-' + event + '-spy';
                    var nextSpyName = nextView + '-' + nextEvent + '-spy';

                    var spy = this.events[spyName];
                    if (typeof pos == 'number') {
                        spy = spy.getCall(pos);
                    }

                    var nextSpy = this.events[nextSpyName];
                    if (typeof nextPos == 'number') {
                        nextSpy = nextSpy.getCall(nextPos);
                    }

                    expect(spy.calledBefore(nextSpy)).to.be.ok();
                });
            })(def[0], def[1], def[2], defNext[0], defNext[1], defNext[2]);

        }
    }

    beforeEach(function() {
        ns.layout.define('app', {
            'app': {
                'head': true,
                'content@': true
            }
        });

        ns.layout.define('content1', {
            'app content@': {
                'content1': {
                    'content1-inner': true
                }
            }
        }, 'app');

        ns.layout.define('content2', {
            'app content@': {
                'content2': {
                    'content2-inner': true
                }
            }
        }, 'app');

        var views = ['app', 'head', 'content1', 'content1-async@content1-async-model', 'content1-inner', 'content2', 'content2-inner'];
        var events = ['ns-async', 'ns-init', 'ns-htmlinit', 'ns-show', 'ns-repaint', 'ns-hide', 'ns-htmldestroy'];

        this.events = {};

        for (var i = 0, j = views.length; i < j; i++) {
            var viewDecl = views[i].split('@');
            var view = viewDecl[0];
            var model = viewDecl[1];

            var eventsDecl = {};
            for (var k = 0, l = events.length; k < l; k++) {
                var event = events[k];
                var spy = sinon.spy();

                eventsDecl[event + ' .'] = spy;
                this.events[view + '-' + event + '-spy'] = spy
            }

            ns.View.define(view, {
                events: eventsDecl,
                models: model ? [model] : []
            });
        }

        /**
         *
         * @type {ns.View}
         */
        this.APP = ns.View.create('app');
    });

    afterEach(function() {
        delete this.events;
        delete this.APP;
    });

    describe('first rendering', function() {

        beforeEach(function() {
            var layout = ns.layout.page('content1', {});
            var update = new ns.Update(this.APP, layout, {});
            update.start();
        });

        describe('ns-init', function() {
            genTests([
                ['app', 'ns-init', 'calledOnce'],
                ['head', 'ns-init', 'calledOnce'],
                ['content1', 'ns-init', 'calledOnce'],
                ['content1-inner', 'ns-init', 'calledOnce'],
                ['content2', 'ns-init', 'called', false],
                ['content2-inner', 'ns-init', 'called', false]
            ]);
        });

        describe('ns-htmlinit', function() {
            genTests([
                ['app', 'ns-htmlinit', 'calledOnce'],
                ['head', 'ns-htmlinit', 'calledOnce'],
                ['content1', 'ns-htmlinit', 'calledOnce'],
                ['content1-inner', 'ns-htmlinit', 'calledOnce'],
                ['content2', 'ns-htmlinit', 'called', false],
                ['content2-inner', 'ns-htmlinit', 'called', false]
            ]);
        });

        describe('ns-show', function() {
            genTests([
                ['app', 'ns-show', 'calledOnce'],
                ['head', 'ns-show', 'calledOnce'],
                ['content1', 'ns-show', 'calledOnce'],
                ['content1-inner', 'ns-show', 'calledOnce'],
                ['content2', 'ns-show', 'called', false],
                ['content2-inner', 'ns-show', 'called', false]
            ]);
        });

        describe('ns-repaint', function() {
            genTests([
                ['app', 'ns-repaint', 'calledOnce'],
                ['head', 'ns-repaint', 'calledOnce'],
                ['content1', 'ns-repaint', 'calledOnce'],
                ['content1-inner', 'ns-repaint', 'calledOnce'],
                ['content2', 'ns-repaint', 'called', false],
                ['content2-inner', 'ns-repaint', 'called', false]
            ]);
        });

        describe('ns-hide', function() {
            genTests([
                ['app', 'ns-hide', 'called', false],
                ['head', 'ns-hide', 'called', false],
                ['content1', 'ns-hide', 'called', false],
                ['content1-inner', 'ns-hide', 'called', false],
                ['content2', 'ns-hide', 'called', false],
                ['content2-inner', 'ns-hide', 'called', false]
            ]);
        });

        describe('ns-htmldestroy', function() {
            genTests([
                ['app', 'ns-htmldestroy', 'called', false],
                ['head', 'ns-htmldestroy', 'called', false],
                ['content1', 'ns-htmldestroy', 'called', false],
                ['content1-inner', 'ns-htmldestroy', 'called', false],
                ['content2', 'ns-htmldestroy', 'called', false],
                ['content2-inner', 'ns-htmldestroy', 'called', false]
            ]);
        });

        describe('order', function() {
            genOrderTests([
                ['content1-inner', 'ns-htmlinit'],
                ['content1', 'ns-htmlinit'],
                ['head', 'ns-htmlinit'],
                ['app', 'ns-htmlinit'],

                ['content1-inner', 'ns-show'],
                ['content1', 'ns-show'],
                ['head', 'ns-show'],
                ['app', 'ns-show'],

                ['content1-inner', 'ns-repaint'],
                ['content1', 'ns-repaint'],
                ['head', 'ns-repaint'],
                ['app', 'ns-repaint']
            ]);
        });

    });

    describe('change view in box', function() {

        beforeEach(function() {
            var layout = ns.layout.page('content1', {});
            new ns.Update(this.APP, layout, {}).start();

            layout = ns.layout.page('content2', {});
            new ns.Update(this.APP, layout, {}).start();
        });

        genTests([

            ['content2-inner', 'ns-init', 'calledOnce'],
            ['content2-inner', 'ns-htmlinit', 'calledOnce'],
            ['content2-inner', 'ns-show', 'calledOnce'],
            ['content2-inner', 'ns-repaint', 'calledOnce'],

            ['content2', 'ns-init', 'calledOnce'],
            ['content2', 'ns-htmlinit', 'calledOnce'],
            ['content2', 'ns-show', 'calledOnce'],
            ['content2', 'ns-repaint', 'calledOnce'],

            ['app', 'ns-show', 'calledOnce'],
            ['content1-inner', 'ns-hide', 'calledOnce'],
            ['content1', 'ns-hide', 'calledOnce'],

            ['app', 'ns-repaint', 'calledTwice'],
            ['head', 'ns-repaint', 'calledTwice'],
            ['content1', 'ns-repaint', 'calledOnce'],
            ['content1-inner', 'ns-repaint', 'calledOnce'],
            ['content2', 'ns-repaint', 'calledOnce'],
            ['content2-inner', 'ns-repaint', 'calledOnce']
        ]);

        describe('order', function() {
            genOrderTests([
                ['content1-inner', 'ns-htmlinit', 0],
                ['content1', 'ns-htmlinit', 0],
                ['head', 'ns-htmlinit', 0],
                ['app', 'ns-htmlinit', 0],

                ['content1-inner', 'ns-show', 0],
                ['content1', 'ns-show', 0],
                ['head', 'ns-show', 0],
                ['app', 'ns-show', 0],

                ['content1-inner', 'ns-repaint', 0],
                ['content1', 'ns-repaint', 0],
                ['head', 'ns-repaint', 0],
                ['app', 'ns-repaint', 0],

                ['content1-inner', 'ns-hide', 0],
                ['content1', 'ns-hide', 0],

                ['content2-inner', 'ns-htmlinit', 0],
                ['content2', 'ns-htmlinit', 0],
                ['content2-inner', 'ns-show', 0],
                ['content2', 'ns-show', 0],

                ['content2-inner', 'ns-repaint', 0],
                ['content2', 'ns-repaint', 0],
                ['head', 'ns-repaint', 1],
                ['app', 'ns-repaint', 1]
            ]);
        });
    });

    describe('redraw view', function() {

        beforeEach(function() {
            var layout = ns.layout.page('content1', {});
            new ns.Update(this.APP, layout, {}).start();

            /**
             * @type {ns.View}
             */
            var vContent1 = this.events['content1-ns-init-spy'].getCall(0).thisValue;
            vContent1.invalidate();

            layout = ns.layout.page('content1', {});
            new ns.Update(this.APP, layout, {}).start();
        });

        describe('events', function() {
            genTests([
                ['content1-inner', 'ns-hide', 'calledOnce'],
                ['content1', 'ns-hide', 'calledOnce'],

                ['content1-inner', 'ns-htmldestroy', 'calledOnce'],
                ['content1', 'ns-htmldestroy', 'calledOnce'],

                ['content1-inner', 'ns-htmlinit', 'calledTwice'],
                ['content1', 'ns-htmlinit', 'calledTwice'],

                ['content1-inner', 'ns-show', 'calledTwice'],
                ['content1', 'ns-show', 'calledTwice'],

                ['content1-inner', 'ns-repaint', 'calledTwice'],
                ['content1', 'ns-repaint', 'calledTwice']
            ]);
        });

        describe('order', function() {
            genOrderTests([
                ['content1-inner', 'ns-htmlinit', 0],
                ['content1', 'ns-htmlinit', 0],
                ['head', 'ns-htmlinit', 0],
                ['app', 'ns-htmlinit', 0],

                ['content1-inner', 'ns-show', 0],
                ['content1', 'ns-show', 0],
                ['head', 'ns-show', 0],
                ['app', 'ns-show', 0],

                ['content1-inner', 'ns-repaint', 0],
                ['content1', 'ns-repaint', 0],
                ['head', 'ns-repaint', 0],
                ['app', 'ns-repaint', 0],

                ['content1-inner', 'ns-hide', 0],
                ['content1', 'ns-hide', 0],

                ['content1-inner', 'ns-htmldestroy', 0],
                ['content1', 'ns-htmldestroy', 0],

                ['content1-inner', 'ns-htmlinit', 1],
                ['content1', 'ns-htmlinit', 1],
                ['content1-inner', 'ns-show', 1],
                ['content1', 'ns-show', 1],

                ['content1-inner', 'ns-repaint', 1],
                ['content1', 'ns-repaint', 1],
                ['head', 'ns-repaint', 1],
                ['app', 'ns-repaint', 1]
            ]);
        });
    });

    describe('ns-async', function() {

        beforeEach(function() {
            ns.layout.define('content1-async', {
                'app content@': {
                    'content1-async&': {
                        'content1-inner': true
                    }
                }
            }, 'app');

            ns.Model.define('content1-async-model');

            this.xhr = sinon.useFakeXMLHttpRequest();
            var requests = this.requests = [];
            this.xhr.onCreate = function (xhr) {
                requests.push(xhr);
            };

            var layout = ns.layout.page('content1-async', {});
            new ns.Update(this.APP, layout, {}).start();
        });

        afterEach(function() {
            this.xhr.restore();
            ns.request.clean();
        });

        describe('first pass', function() {
            describe('events', function() {
                genTests([
                    ['content1-async', 'ns-async', 'calledOnce'],

                    ['content1-async', 'ns-htmldestroy', 'called', false],
                    ['content1-async', 'ns-hide', 'called', false],
                    ['content1-async', 'ns-htmlinit', 'called', false],
                    ['content1-async', 'ns-show', 'called', false],
                    ['content1-async', 'ns-repaint', 'called', false],

                    ['content1-inner', 'ns-htmldestroy', 'called', false],
                    ['content1-inner', 'ns-hide', 'called', false],
                    ['content1-inner', 'ns-htmlinit', 'called', false],
                    ['content1-inner', 'ns-show', 'called', false],
                    ['content1-inner', 'ns-repaint', 'called', false]
                ])
            });

            describe('order', function() {
                genOrderTests([
                    ['head', 'ns-htmlinit', 0],
                    ['app', 'ns-htmlinit', 0],

                    ['content1-async', 'ns-async', 0],

                    ['head', 'ns-show', 0],
                    ['app', 'ns-show', 0],

                    ['head', 'ns-repaint', 0],
                    ['app', 'ns-repaint', 0]
                ]);
            });
        });

        describe('second pass', function() {

            beforeEach(function() {
                this.requests[0].respond(
                    200,
                    {"Content-Type": "application/json"},
                    JSON.stringify({
                        models: [
                            {data: true}
                        ]
                    })
                );
            });

            describe('events', function() {
                genTests([
                    ['content1-async', 'ns-async', 'calledOnce'],

                    ['content1-async', 'ns-htmlinit', 'calledOnce'],
                    ['content1-async', 'ns-show', 'calledOnce'],
                    ['content1-async', 'ns-repaint', 'calledOnce'],

                    ['content1-inner', 'ns-htmlinit', 'calledOnce'],
                    ['content1-inner', 'ns-show', 'calledOnce'],
                    ['content1-inner', 'ns-repaint', 'calledOnce'],

                    ['head', 'ns-repaint', 'calledOnce'],
                    ['app', 'ns-repaint', 'calledOnce'],

                    ['content1-async', 'ns-htmldestroy', 'called', false],
                    ['content1-inner', 'ns-htmldestroy', 'called', false]
                ])
            });

            describe('order', function() {
                genOrderTests([
                    ['head', 'ns-htmlinit', 0],
                    ['app', 'ns-htmlinit', 0],

                    ['content1-async', 'ns-async', 0],

                    ['head', 'ns-show', 0],
                    ['app', 'ns-show', 0],

                    ['head', 'ns-repaint', 0],
                    ['app', 'ns-repaint', 0],

                    ['content1-inner', 'ns-htmlinit', 0],
                    ['content1-async', 'ns-htmlinit', 0],

                    ['content1-inner', 'ns-show', 0],
                    ['content1-async', 'ns-show', 0],

                    ['content1-inner', 'ns-repaint', 0],
                    ['content1-async', 'ns-repaint', 0]
                ]);
            })
        });

    });
});
<commit_msg>Failed tests for #89<commit_after>describe('ns.View.events', function() {

    function genTests(defs) {
        for (var i = 0, j = defs.length; i < j; i++) {
            var def = defs[i];
            (function(view, event, check, not) {
                it('should ' + (not == false ? 'not ': '') + ' trigger "' + event + '" for "' + view + '" (' + check + ')', function() {
                    var spyName = view + '-' + event + '-spy';
                    if (not === false) {
                        expect(this.events[spyName][check]).to.not.be.ok();
                    } else {
                        expect(this.events[spyName][check]).to.be.ok();
                    }
                });
            })(def[0], def[1], def[2], def[3]);

        }
    }

    function genOrderTests(defs) {
        for (var i = 0, j = defs.length - 1; i < j; i++) {
            var def = defs[i];
            var defNext = defs[i + 1];
            (function(view, event, pos, nextView, nextEvent, nextPos) {
                it('should trigger "'+event+'" for "'+view+'" before "'+nextEvent+'" for "'+nextView+'" ', function() {
                    var spyName = view + '-' + event + '-spy';
                    var nextSpyName = nextView + '-' + nextEvent + '-spy';

                    var spy = this.events[spyName];
                    if (typeof pos == 'number') {
                        spy = spy.getCall(pos);
                    }

                    var nextSpy = this.events[nextSpyName];
                    if (typeof nextPos == 'number') {
                        nextSpy = nextSpy.getCall(nextPos);
                    }

                    expect(spy.calledBefore(nextSpy)).to.be.ok();
                });
            })(def[0], def[1], def[2], defNext[0], defNext[1], defNext[2]);

        }
    }

    beforeEach(function() {
        ns.layout.define('app', {
            'app': {
                'head': true,
                'content@': true
            }
        });

        ns.layout.define('content1', {
            'app content@': {
                'content1': {
                    'content1-inner': true
                }
            }
        }, 'app');

        ns.layout.define('content2', {
            'app content@': {
                'content2': {
                    'content2-inner': true
                }
            }
        }, 'app');

        var views = ['app', 'head', 'content1', 'content1-async@content1-async-model', 'content1-inner', 'content2', 'content2-inner'];
        var events = ['ns-async', 'ns-init', 'ns-htmlinit', 'ns-show', 'ns-repaint', 'ns-hide', 'ns-htmldestroy'];

        this.events = {};

        for (var i = 0, j = views.length; i < j; i++) {
            var viewDecl = views[i].split('@');
            var view = viewDecl[0];
            var model = viewDecl[1];

            var eventsDecl = {};
            for (var k = 0, l = events.length; k < l; k++) {
                var event = events[k];
                var spy = sinon.spy();

                eventsDecl[event + ' .'] = spy;
                this.events[view + '-' + event + '-spy'] = spy
            }

            ns.View.define(view, {
                events: eventsDecl,
                models: model ? [model] : []
            });
        }

        /**
         *
         * @type {ns.View}
         */
        this.APP = ns.View.create('app');
    });

    afterEach(function() {
        delete this.events;
        delete this.APP;
    });

    describe('first rendering', function() {

        beforeEach(function() {
            var layout = ns.layout.page('content1', {});
            var update = new ns.Update(this.APP, layout, {});
            update.start();
        });

        describe('ns-init', function() {
            genTests([
                ['app', 'ns-init', 'calledOnce'],
                ['head', 'ns-init', 'calledOnce'],
                ['content1', 'ns-init', 'calledOnce'],
                ['content1-inner', 'ns-init', 'calledOnce'],
                ['content2', 'ns-init', 'called', false],
                ['content2-inner', 'ns-init', 'called', false]
            ]);
        });

        describe('ns-htmlinit', function() {
            genTests([
                ['app', 'ns-htmlinit', 'calledOnce'],
                ['head', 'ns-htmlinit', 'calledOnce'],
                ['content1', 'ns-htmlinit', 'calledOnce'],
                ['content1-inner', 'ns-htmlinit', 'calledOnce'],
                ['content2', 'ns-htmlinit', 'called', false],
                ['content2-inner', 'ns-htmlinit', 'called', false]
            ]);
        });

        describe('ns-show', function() {
            genTests([
                ['app', 'ns-show', 'calledOnce'],
                ['head', 'ns-show', 'calledOnce'],
                ['content1', 'ns-show', 'calledOnce'],
                ['content1-inner', 'ns-show', 'calledOnce'],
                ['content2', 'ns-show', 'called', false],
                ['content2-inner', 'ns-show', 'called', false]
            ]);
        });

        describe('ns-repaint', function() {
            genTests([
                ['app', 'ns-repaint', 'calledOnce'],
                ['head', 'ns-repaint', 'calledOnce'],
                ['content1', 'ns-repaint', 'calledOnce'],
                ['content1-inner', 'ns-repaint', 'calledOnce'],
                ['content2', 'ns-repaint', 'called', false],
                ['content2-inner', 'ns-repaint', 'called', false]
            ]);
        });

        describe('ns-hide', function() {
            genTests([
                ['app', 'ns-hide', 'called', false],
                ['head', 'ns-hide', 'called', false],
                ['content1', 'ns-hide', 'called', false],
                ['content1-inner', 'ns-hide', 'called', false],
                ['content2', 'ns-hide', 'called', false],
                ['content2-inner', 'ns-hide', 'called', false]
            ]);
        });

        describe('ns-htmldestroy', function() {
            genTests([
                ['app', 'ns-htmldestroy', 'called', false],
                ['head', 'ns-htmldestroy', 'called', false],
                ['content1', 'ns-htmldestroy', 'called', false],
                ['content1-inner', 'ns-htmldestroy', 'called', false],
                ['content2', 'ns-htmldestroy', 'called', false],
                ['content2-inner', 'ns-htmldestroy', 'called', false]
            ]);
        });

        describe('order', function() {
            genOrderTests([
                ['content1-inner', 'ns-htmlinit'],
                ['content1', 'ns-htmlinit'],
                ['head', 'ns-htmlinit'],
                ['app', 'ns-htmlinit'],

                ['content1-inner', 'ns-show'],
                ['content1', 'ns-show'],
                ['head', 'ns-show'],
                ['app', 'ns-show'],

                ['content1-inner', 'ns-repaint'],
                ['content1', 'ns-repaint'],
                ['head', 'ns-repaint'],
                ['app', 'ns-repaint']
            ]);
        });

    });

    describe('change view in box', function() {

        beforeEach(function() {
            var layout = ns.layout.page('content1', {});
            new ns.Update(this.APP, layout, {}).start();

            layout = ns.layout.page('content2', {});
            new ns.Update(this.APP, layout, {}).start();
        });

        genTests([

            ['content2-inner', 'ns-init', 'calledOnce'],
            ['content2-inner', 'ns-htmlinit', 'calledOnce'],
            ['content2-inner', 'ns-show', 'calledOnce'],
            ['content2-inner', 'ns-repaint', 'calledOnce'],

            ['content2', 'ns-init', 'calledOnce'],
            ['content2', 'ns-htmlinit', 'calledOnce'],
            ['content2', 'ns-show', 'calledOnce'],
            ['content2', 'ns-repaint', 'calledOnce'],

            ['app', 'ns-show', 'calledOnce'],
            ['content1-inner', 'ns-hide', 'calledOnce'],
            ['content1', 'ns-hide', 'calledOnce'],

            ['app', 'ns-repaint', 'calledTwice'],
            ['head', 'ns-repaint', 'calledTwice'],
            ['content1', 'ns-repaint', 'calledOnce'],
            ['content1-inner', 'ns-repaint', 'calledOnce'],
            ['content2', 'ns-repaint', 'calledOnce'],
            ['content2-inner', 'ns-repaint', 'calledOnce']
        ]);

        describe('order', function() {
            genOrderTests([
                ['content1-inner', 'ns-htmlinit', 0],
                ['content1', 'ns-htmlinit', 0],
                ['head', 'ns-htmlinit', 0],
                ['app', 'ns-htmlinit', 0],

                ['content1-inner', 'ns-show', 0],
                ['content1', 'ns-show', 0],
                ['head', 'ns-show', 0],
                ['app', 'ns-show', 0],

                ['content1-inner', 'ns-repaint', 0],
                ['content1', 'ns-repaint', 0],
                ['head', 'ns-repaint', 0],
                ['app', 'ns-repaint', 0],

                ['content1-inner', 'ns-hide', 0],
                ['content1', 'ns-hide', 0],

                ['content2-inner', 'ns-htmlinit', 0],
                ['content2', 'ns-htmlinit', 0],
                ['content2-inner', 'ns-show', 0],
                ['content2', 'ns-show', 0],

                ['content2-inner', 'ns-repaint', 0],
                ['content2', 'ns-repaint', 0],
                ['head', 'ns-repaint', 1],
                ['app', 'ns-repaint', 1]
            ]);
        });
    });

    describe('redraw view', function() {

        beforeEach(function() {
            var layout = ns.layout.page('content1', {});
            new ns.Update(this.APP, layout, {}).start();

            /**
             * @type {ns.View}
             */
            var vContent1 = this.events['content1-ns-init-spy'].getCall(0).thisValue;
            vContent1.invalidate();

            layout = ns.layout.page('content1', {});
            new ns.Update(this.APP, layout, {}).start();
        });

        describe('events', function() {
            genTests([
                ['content1-inner', 'ns-hide', 'calledOnce'],
                ['content1', 'ns-hide', 'calledOnce'],

                ['content1-inner', 'ns-htmldestroy', 'calledOnce'],
                ['content1', 'ns-htmldestroy', 'calledOnce'],

                ['content1-inner', 'ns-htmlinit', 'calledTwice'],
                ['content1', 'ns-htmlinit', 'calledTwice'],

                ['content1-inner', 'ns-show', 'calledTwice'],
                ['content1', 'ns-show', 'calledTwice'],

                ['content1-inner', 'ns-repaint', 'calledTwice'],
                ['content1', 'ns-repaint', 'calledTwice']
            ]);
        });

        describe('order', function() {
            genOrderTests([
                ['content1-inner', 'ns-htmlinit', 0],
                ['content1', 'ns-htmlinit', 0],
                ['head', 'ns-htmlinit', 0],
                ['app', 'ns-htmlinit', 0],

                ['content1-inner', 'ns-show', 0],
                ['content1', 'ns-show', 0],
                ['head', 'ns-show', 0],
                ['app', 'ns-show', 0],

                ['content1-inner', 'ns-repaint', 0],
                ['content1', 'ns-repaint', 0],
                ['head', 'ns-repaint', 0],
                ['app', 'ns-repaint', 0],

                ['content1-inner', 'ns-hide', 0],
                ['content1', 'ns-hide', 0],

                ['content1-inner', 'ns-htmldestroy', 0],
                ['content1', 'ns-htmldestroy', 0],

                ['content1-inner', 'ns-htmlinit', 1],
                ['content1', 'ns-htmlinit', 1],
                ['content1-inner', 'ns-show', 1],
                ['content1', 'ns-show', 1],

                ['content1-inner', 'ns-repaint', 1],
                ['content1', 'ns-repaint', 1],
                ['head', 'ns-repaint', 1],
                ['app', 'ns-repaint', 1]
            ]);
        });
    });

    describe('ns-async', function() {

        beforeEach(function() {
            ns.layout.define('content1-async', {
                'app content@': {
                    'content1-async&': {
                        'content1-inner': true
                    }
                }
            }, 'app');

            ns.Model.define('content1-async-model', {
                params: {
                    p: null
                }
            });

            this.xhr = sinon.useFakeXMLHttpRequest();
            var requests = this.requests = [];
            this.xhr.onCreate = function (xhr) {
                requests.push(xhr);
            };

            var params = {p: 1};
            var layout = ns.layout.page('content1-async', params);
            new ns.Update(this.APP, layout, params).start();
        });

        afterEach(function() {
            this.xhr.restore();
        });

        describe('first pass', function() {
            describe('events', function() {
                genTests([
                    ['content1-async', 'ns-async', 'calledOnce'],

                    ['content1-async', 'ns-htmldestroy', 'called', false],
                    ['content1-async', 'ns-hide', 'called', false],
                    ['content1-async', 'ns-htmlinit', 'called', false],
                    ['content1-async', 'ns-show', 'called', false],
                    ['content1-async', 'ns-repaint', 'called', false],

                    ['content1-inner', 'ns-htmldestroy', 'called', false],
                    ['content1-inner', 'ns-hide', 'called', false],
                    ['content1-inner', 'ns-htmlinit', 'called', false],
                    ['content1-inner', 'ns-show', 'called', false],
                    ['content1-inner', 'ns-repaint', 'called', false]
                ])
            });

            describe('order', function() {
                genOrderTests([
                    ['head', 'ns-htmlinit', 0],
                    ['app', 'ns-htmlinit', 0],

                    ['content1-async', 'ns-async', 0],

                    ['head', 'ns-show', 0],
                    ['app', 'ns-show', 0],

                    ['head', 'ns-repaint', 0],
                    ['app', 'ns-repaint', 0]
                ]);
            });
        });

        describe('second pass', function() {

            beforeEach(function() {
                this.requests[0].respond(
                    200,
                    {"Content-Type": "application/json"},
                    JSON.stringify({
                        models: [
                            {data: true}
                        ]
                    })
                );
            });

            describe('events', function() {
                genTests([
                    ['content1-async', 'ns-async', 'calledOnce'],

                    ['content1-async', 'ns-htmlinit', 'calledOnce'],
                    ['content1-async', 'ns-show', 'calledOnce'],
                    ['content1-async', 'ns-repaint', 'calledOnce'],

                    ['content1-inner', 'ns-htmlinit', 'calledOnce'],
                    ['content1-inner', 'ns-show', 'calledOnce'],
                    ['content1-inner', 'ns-repaint', 'calledOnce'],

                    ['head', 'ns-repaint', 'calledOnce'],
                    ['app', 'ns-repaint', 'calledOnce'],

                    ['content1-async', 'ns-htmldestroy', 'called', false],
                    ['content1-inner', 'ns-htmldestroy', 'called', false]
                ])
            });

            describe('order', function() {
                genOrderTests([
                    ['head', 'ns-htmlinit', 0],
                    ['app', 'ns-htmlinit', 0],

                    ['content1-async', 'ns-async', 0],

                    ['head', 'ns-show', 0],
                    ['app', 'ns-show', 0],

                    ['head', 'ns-repaint', 0],
                    ['app', 'ns-repaint', 0],

                    ['content1-inner', 'ns-htmlinit', 0],
                    ['content1-async', 'ns-htmlinit', 0],

                    ['content1-inner', 'ns-show', 0],
                    ['content1-async', 'ns-show', 0],

                    ['content1-inner', 'ns-repaint', 0],
                    ['content1-async', 'ns-repaint', 0]
                ]);
            })
        });

        describe('change params and redraw async-view', function() {

            beforeEach(function(finish) {
                // finish first draw
                this.requests[0].respond(
                    200,
                    {"Content-Type": "application/json"},
                    JSON.stringify({
                        models: [
                            {data: true}
                        ]
                    })
                );

                var that = this;

                window.setTimeout(function() {
                    // emulates go from /page?p=1 -> /page?p=2
                    var params = {p: 2};
                    var layout = ns.layout.page('content1-async', params);
                    new ns.Update(that.APP, layout, params).start();

                    finish();
                }, 50);
            });

            describe('first pass', function() {

                it('should create second "content1-async" node', function() {
                    var that = this;
                    expect(
                        $(that.APP.node).find('.ns-view-content1-sync')
                    ).to.have.length(2)
                });
            });
        });

    });
});
<|endoftext|>