<commit_before>// keep this global reference around to ease debugging
var debugHook = (function () {
    const fromBaseDir = modulePath => require('path').join(require('electron').remote.app.getAppPath(), modulePath);

    // included with side effects to overwrite some globals
    require(fromBaseDir('src/js/renderer/polyfills.js'));

    // external imports
    const remote = require('electron').remote;
    const _ = require('lodash');
    const settings = require('electron-settings');
    const $ = jQuery = require("jquery-migrate"); // TODO: complete migration to jQuery v3 depends on bootbox support
    $.migrateTrace = false;
    require(fromBaseDir('libs/jqbtk.js')); // extends jQuery, no further global side effects
    const bootbox = require('bootbox');

    // project imports
    const Snapshot = require(fromBaseDir('src/js/renderer/Snapshot.js'));
    const SnapshotPrinter = require(fromBaseDir('src/js/renderer/SnapshotPrinter.js'));
    const SnapshotMailer = require(fromBaseDir('src/js/renderer/SnapshotMailer.js'));
    const SnapshotListUpdater = require(fromBaseDir('src/js/renderer/SnapshotListUpdater.js'));
    const SliderInitializer = require(fromBaseDir('src/js/renderer/SliderInitializer.js'));
    const notify = require(fromBaseDir('src/js/renderer/notify.js'));
    const preprocessSnapshotList = require(fromBaseDir('src/js/renderer/preprocessSnapshotList.js'));
    const packageJson = require(fromBaseDir('package.json'));
    const migrateOldSettings = require(fromBaseDir('src/js/renderer/migrateOldSettings.js'));
    const utils = require(fromBaseDir('src/js/renderer/utils.js'));

    // initialization
    migrateOldSettings();
    const miscConfig = settings.getAll();
    let snapshots; // to be initialized after preprocessing the SNAPSHOT list

    const snapshotMailer = new SnapshotMailer(miscConfig.mail);
    snapshotMailer.testConnection()
        .then(() => notify.success('Mail server is ready to take messages', ""))
        .catch(error => notify.error('Connection to mail server failed', 'Please check the error message', error));

    let mode;

    if (miscConfig.hideCursor) {
        const lastCSS = document.styleSheets[document.styleSheets.length - 1];
        lastCSS.insertRule("* { cursor: none; }", lastCSS.cssRules.length);
    }

    window.onresize = () => {
        const sx = $(window).width() / 1920;
        const sy = $(window).height() / 1080;
        const s = Math.min(sx, sy);
        const fullHdCentered = document.getElementById("full-hd-centered");
        fullHdCentered.style.transform = `scale(${s})`;
        fullHdCentered.style.left = `${($(window).width() - 1920 * s) / 2.0}px`;
        fullHdCentered.style.top = `${($(window).height() - 1080 * s) / 2.0}px`;
    };
    window.onresize();

    document.body.ondblclick = () => {
        if (mode === "slider") {
            const win = remote.getCurrentWindow();
            const sx = win.getContentSize()[0] / 1920;
            const sy = win.getContentSize()[0] / 1080;
            const s = Math.min(sx, sy);
            win.setContentSize(Math.floor(1920 * s), Math.floor(1080 * s), true);
        }
    };
    document.body.ondblclick();

    function initKeyHandlers(swiper, slideContents) {
        document.onkeydown = e => {
            if (mode === "slider") {
                const actions = {
                    "i": about,
                    "ArrowLeft": () => swiper.slidePrev(), // left arrow
                    "ArrowRight": () => swiper.slideNext(), // right arrow
                    "ArrowDown": () => slideContents[swiper.realIndex].nested.swiper.slideNext(), // down arrow
                    "ArrowUp": () => slideContents[swiper.realIndex].nested.swiper.slidePrev() // up arrow
                };
                actions[miscConfig.snapshots.autoUpdate.hotkey] = switchToUpdateMode;
                if (typeof actions[e.key] !== 'undefined')
                    actions[e.key]();
            }
        };
    }

    function about() {
        notify.info(
            `About ${packageJson.productName}`,
            `License: ${packageJson.license}<br/>Version: ${packageJson.version}`,
            process.versions
        );
    }

    function initIdleHandlers(idleAction) {
        let idle_timer = null;
        const init_idle_timer = delay => {
            if (idle_timer != null)
                clearTimeout(idle_timer);
            idle_timer = setTimeout(idle_handler, delay);
        };
        const non_idle_handler = () => {
            console.log("non_idle_handler");
            init_idle_timer(miscConfig.idleModeDelayMs);
        };
        const idle_handler = () => {
            console.log("idle_handler");
            idleAction();
            init_idle_timer(miscConfig.idleModeDelayBetweenActionsMs);
        };

        document.body.addEventListener('mouseup', non_idle_handler, true);
        document.body.addEventListener('mousemove', non_idle_handler, true);
        document.body.addEventListener('mousedown', non_idle_handler, true);
        document.body.addEventListener("touchstart", non_idle_handler, true);
        document.body.addEventListener("touchend", non_idle_handler, true);
        document.body.addEventListener("touchcancel", non_idle_handler, true);
        document.body.addEventListener("touchmove", non_idle_handler, true);
        document.body.addEventListener("onscroll", non_idle_handler, true);
        document.body.addEventListener("keydown", non_idle_handler, true);
        document.body.addEventListener("keyup", non_idle_handler, true);
        document.body.addEventListener("keypress", non_idle_handler, true);

        init_idle_timer(miscConfig.idleModeDelayMs);
    }

    function createIdleAction(swiper, slideContents) {
        return () => {
            bootbox.hideAll();
            slideContents[(swiper.realIndex + 1) % snapshots.length].nested.swiper.slideTo(0, 0);
            slideContents[(swiper.realIndex + 2) % snapshots.length].nested.swiper.slideTo(0, 0);
            swiper.slideNext(miscConfig.idleAnimationDurationMs, true);
        }
    }

    function switchToSlider() {
        bootbox.hideAll();
        mode = "slider";
    }

    function switchToUpdateMode() {
        mode = "update";

        bootbox.confirm({
            title: 'Confirm update',
            message: '
Are you sure that you want to update the list of available SNAPSHOTS?
',
            callback: function (result) {
                if (result)
                    updateSnapshotList();
                switchToSlider();
            }
        });
    }

    function switchToMailMode(snapshot) {
        mode = "mail";
        bootbox.confirm({
            title: 'Please enter your email address',
            message: '
Select one of the input fields to open the on screen keyboard. Click outside the on screen keyboard to hide it.

Name:<input type="text" class="keyboard form-control" id="emailName">

Email:<input type="text" class="keyboard form-control" id="emailAddress">

',
            callback: result => {
                if (result) {
                    const recipientName = $('#emailName').val().trim();
                    const recipientAddress = $('#emailAddress').val().trim();
                    snapshotMailer.send(snapshot.metadata, recipientAddress, recipientName === '' ? undefined : recipientName)
                        .then(info => notify.success('Email sent successfully', "", info))
                        .catch(error => notify.error('Email could not be sent', 'Please check the error message', error));
                }
                switchToSlider();
            }
        });
        $("#emailName").keyboard();
        $("#emailAddress").keyboard();
    }

    function switchToPrintMode(snapshot) {
        mode = "print";
        bootbox.confirm({
            title: 'Confirm printing',
            message: `<p class="dialog">Do you want to print: <em>"<b>${snapshot.metadata.authors.map(a => a.trim()).join(", ")}:</b> ${snapshot.metadata.title.trim()}"</em>?<p>`,
            callback: result => {
                if (result)
                    print(snapshot);
                switchToSlider();
            }
        });
    }

    function print(snapshot) {
        return SnapshotPrinter.print(snapshot.cachedPdf)
            .then(() => notify.success('File has been sent to the printer'))
            .catch(error => notify.error('Print job failed', 'Please check the error message', error));
    }

    async function updateSnapshotList() {
        const errorNotificationTitle = "Update of SNAPSHOT list failed";
        const successNotificationTitle = "Update of SNAPSHOT list successful";

        try {
            const newSnapshotList = await SnapshotListUpdater.update(miscConfig.snapshots.autoUpdate.url);
            if (_.isEqual(newSnapshotList.snapshots, miscConfig.snapshots.articles)) {
                notify.success(successNotificationTitle, "No change detected.", newSnapshotList);
            } else {
                settings.set("snapshots.articles", newSnapshotList.snapshots, {
                    prettify: true
                });
                notify.success(successNotificationTitle, "Reloading …", newSnapshotList)
                    .then(() => location.reload());
            }
        } catch (error) {
            switch (error.errorCode) {
                case SnapshotListUpdater.UpdateError.ERROR_DOWNLOAD_FAILED:
                    notify.error(errorNotificationTitle, "The list could not be downloaded.", error.cause);
                    break;
                case SnapshotListUpdater.UpdateError.ERROR_VERSION_MISMATCH:
                    notify.error(errorNotificationTitle, "Online data has wrong version tag.", error.cause);
                    break;
                case SnapshotListUpdater.UpdateError.ERROR_VALIDATION_FAILED:
                    notify.error(errorNotificationTitle, "The downloaded list is invalid.", error.cause);
                    break;
            }
        }
    }

    // GO!
    new Promise(resolve => $(document).ready(resolve))
        .then(miscConfig.snapshots.autoUpdate.enable ? () => {
            notify.info("Starting update of SNAPSHOT list");
            return updateSnapshotList().reflect();
        } : Promise.resolve())
        .then(async () => {
            const startTime = performance.now();
            const articles = preprocessSnapshotList(miscConfig.snapshots);
            snapshots = articles.map(article => new Snapshot(article, {
                cacheDir: utils.getPath('cache'),
                defaultWidth: 717,
                defaultHeight: 1014
            }));
            notify.updateInitProgressBar("#progressCache", {
                max: snapshots.length
            });
            notify.updateInitProgressBar("#progressDocs", {
                max: snapshots.length
            });

            const cachePDFPromises = [];
            const initDocumentPromises = [];
            const initNestedSlidesPromises = [];
            const initCompletePromises = [];
            let totalNumPages = 0;
            snapshots.forEach(snapshot => {
                let article = snapshot.metadata;

                let cachePromise = snapshot.cacheDocumentPromise.catch(e => {
                    notify.error("Initialization error", `Could not cache "${article.authors.join(", ")}: ${article.title}" (doi: ${article.doi})`, e);
                    throw e;
                });
                let initDocumentPromise = snapshot.initDocumentPromise.catch(e => {
                    notify.error("Initialization error", `Failed to load "${article.authors.join(", ")}: ${article.title}" (doi: ${article.doi})`, e);
                    throw e;
                });
                let cachePagePromises = snapshot.cachePagePromises.catch(e => {
                    notify.error("Initialization error",
                        `Failed to render pages of "${article.authors.join(", ")}: ${article.title}" (doi: ${article.doi})`, e);
                    throw e;
                });

                cachePromise.finally(() => notify.updateInitProgressBar("#progressCache", {
                    now: 1,
                    offset: true
                }));
                cachePagePromises.finally(() =>
                    notify.updateInitProgressBar("#progressDocs", {
                        now: 1,
                        offset: true
                    })
                );

                initDocumentPromise = initDocumentPromise.then(document => {
                    totalNumPages += document.numPages;
                    notify.updateInitProgressBar("#progressPages", {
                        max: totalNumPages
                    });
                    notify.updateInitProgressBar("#progressRendered", {
                        max: totalNumPages
                    });
                    return document;
                });

                let initCompletePromise = cachePagePromises
                    .catch(e => {
                        console.log("Problem processing snapshot", snapshot.metadata, e);
                    })
                    .then(actualCachePagePromises => Promise.all(actualCachePagePromises));

                snapshot.initPagePromises.then(promises => promises.forEach(promise => promise.finally(
                    () => notify.updateInitProgressBar("#progressPages", {
                        now: 1,
                        offset: true
                    }))));

                snapshot.cachePagePromises.then(promises => promises.forEach(promise => promise.finally(
                    () => notify.updateInitProgressBar("#progressRendered", {
                        now: 1,
                        offset: true
                    }))));

                cachePDFPromises.push(cachePromise);
                initDocumentPromises.push(initDocumentPromise);
                initNestedSlidesPromises.push(cachePagePromises);
                initCompletePromises.push(initCompletePromise);
            });

            // create the slider and add it to the DOM (final initialization is done upon insertion into the DOM)
            const {swiper, slideContents} = await SliderInitializer.createTopLevelSlider(snapshots, {
                onMail: miscConfig.mail.enable ? snapshot => switchToMailMode(snapshot) : undefined,
                onPrint: miscConfig.print.enable ? snapshot => switchToPrintMode(snapshot) : undefined,
            });
            document.querySelector('#full-hd-centered').appendChild(swiper.el);

            Promise.all(initNestedSlidesPromises).catch(() => notify.warning("Initialization incomplete", "Some SNAPSHOTS will be unavailable."));
            Promise.all(initCompletePromises)
                .then(notify.closeInitProgressBar)
                .then(() => {
                    initIdleHandlers(createIdleAction(swiper, slideContents));
                    initKeyHandlers(swiper, slideContents);
                    switchToSlider();

                    console.log(`loading took ${(performance.now() - startTime) / 1000.0}s`)
                });
        });

})();
<commit_msg>Add hotkey to reload the contents of the main window<commit_after>// keep this global reference around to ease debugging
var debugHook = (function () {
    const fromBaseDir = modulePath => require('path').join(require('electron').remote.app.getAppPath(), modulePath);

    // included with side effects to overwrite some globals
    require(fromBaseDir('src/js/renderer/polyfills.js'));

    // external imports
    const remote = require('electron').remote;
    const _ = require('lodash');
    const settings = require('electron-settings');
    const $ = jQuery = require("jquery-migrate"); // TODO: complete migration to jQuery v3 depends on bootbox support
    $.migrateTrace = false;
    require(fromBaseDir('libs/jqbtk.js')); // extends jQuery, no further global side effects
    const bootbox = require('bootbox');

    // project imports
    const Snapshot = require(fromBaseDir('src/js/renderer/Snapshot.js'));
    const SnapshotPrinter = require(fromBaseDir('src/js/renderer/SnapshotPrinter.js'));
    const SnapshotMailer = require(fromBaseDir('src/js/renderer/SnapshotMailer.js'));
    const SnapshotListUpdater = require(fromBaseDir('src/js/renderer/SnapshotListUpdater.js'));
    const SliderInitializer = require(fromBaseDir('src/js/renderer/SliderInitializer.js'));
    const notify = require(fromBaseDir('src/js/renderer/notify.js'));
    const preprocessSnapshotList = require(fromBaseDir('src/js/renderer/preprocessSnapshotList.js'));
    const packageJson = require(fromBaseDir('package.json'));
    const migrateOldSettings = require(fromBaseDir('src/js/renderer/migrateOldSettings.js'));
    const utils = require(fromBaseDir('src/js/renderer/utils.js'));

    // initialization
    migrateOldSettings();
    const miscConfig = settings.getAll();
    let snapshots; // to be initialized after preprocessing the SNAPSHOT list

    const snapshotMailer = new SnapshotMailer(miscConfig.mail);
    snapshotMailer.testConnection()
        .then(() => notify.success('Mail server is ready to take messages', ""))
        .catch(error => notify.error('Connection to mail server failed', 'Please check the error message', error));

    let mode;

    if (miscConfig.hideCursor) {
        const lastCSS = document.styleSheets[document.styleSheets.length - 1];
        lastCSS.insertRule("* { cursor: none; }", lastCSS.cssRules.length);
    }

    window.onresize = () => {
        const sx = $(window).width() / 1920;
        const sy = $(window).height() / 1080;
        const s = Math.min(sx, sy);
        const fullHdCentered = document.getElementById("full-hd-centered");
        fullHdCentered.style.transform = `scale(${s})`;
        fullHdCentered.style.left = `${($(window).width() - 1920 * s) / 2.0}px`;
        fullHdCentered.style.top = `${($(window).height() - 1080 * s) / 2.0}px`;
    };
    window.onresize();

    document.body.ondblclick = () => {
        if (mode === "slider") {
            const win = remote.getCurrentWindow();
            const sx = win.getContentSize()[0] / 1920;
            const sy = win.getContentSize()[0] / 1080;
            const s = Math.min(sx, sy);
            win.setContentSize(Math.floor(1920 * s), Math.floor(1080 * s), true);
        }
    };
    document.body.ondblclick();

    function initKeyHandlers(swiper, slideContents) {
        document.onkeydown = e => {
            if (mode === "slider") {
                const actions = {
                    "i": about,
                    "r": () => window.location.reload(),
                    "ArrowLeft": () => swiper.slidePrev(), // left arrow
                    "ArrowRight": () => swiper.slideNext(), // right arrow
                    "ArrowDown": () => slideContents[swiper.realIndex].nested.swiper.slideNext(), // down arrow
                    "ArrowUp": () => slideContents[swiper.realIndex].nested.swiper.slidePrev() // up arrow
                };
                actions[miscConfig.snapshots.autoUpdate.hotkey] = switchToUpdateMode;
                if (typeof actions[e.key] !== 'undefined')
                    actions[e.key]();
            }
        };
    }

    function about() {
        notify.info(
            `About ${packageJson.productName}`,
            `License: ${packageJson.license}<br/>Version: ${packageJson.version}`,
            process.versions
        );
    }

    function initIdleHandlers(idleAction) {
        let idle_timer = null;
        const init_idle_timer = delay => {
            if (idle_timer != null)
                clearTimeout(idle_timer);
            idle_timer = setTimeout(idle_handler, delay);
        };
        const non_idle_handler = () => {
            console.log("non_idle_handler");
            init_idle_timer(miscConfig.idleModeDelayMs);
        };
        const idle_handler = () => {
            console.log("idle_handler");
            idleAction();
            init_idle_timer(miscConfig.idleModeDelayBetweenActionsMs);
        };

        document.body.addEventListener('mouseup', non_idle_handler, true);
        document.body.addEventListener('mousemove', non_idle_handler, true);
        document.body.addEventListener('mousedown', non_idle_handler, true);
        document.body.addEventListener("touchstart", non_idle_handler, true);
        document.body.addEventListener("touchend", non_idle_handler, true);
        document.body.addEventListener("touchcancel", non_idle_handler, true);
        document.body.addEventListener("touchmove", non_idle_handler, true);
        document.body.addEventListener("onscroll", non_idle_handler, true);
        document.body.addEventListener("keydown", non_idle_handler, true);
        document.body.addEventListener("keyup", non_idle_handler, true);
        document.body.addEventListener("keypress", non_idle_handler, true);

        init_idle_timer(miscConfig.idleModeDelayMs);
    }

    function createIdleAction(swiper, slideContents) {
        return () => {
            bootbox.hideAll();
            slideContents[(swiper.realIndex + 1) % snapshots.length].nested.swiper.slideTo(0, 0);
            slideContents[(swiper.realIndex + 2) % snapshots.length].nested.swiper.slideTo(0, 0);
            swiper.slideNext(miscConfig.idleAnimationDurationMs, true);
        }
    }

    function switchToSlider() {
        bootbox.hideAll();
        mode = "slider";
    }

    function switchToUpdateMode() {
        mode = "update";

        bootbox.confirm({
            title: 'Confirm update',
            message: '
Are you sure that you want to update the list of available SNAPSHOTS?
',
            callback: function (result) {
                if (result)
                    updateSnapshotList();
                switchToSlider();
            }
        });
    }

    function switchToMailMode(snapshot) {
        mode = "mail";
        bootbox.confirm({
            title: 'Please enter your email address',
            message: '
Select one of the input fields to open the on screen keyboard. Click outside the on screen keyboard to hide it.

Name:<input type="text" class="keyboard form-control" id="emailName">

Email:<input type="text" class="keyboard form-control" id="emailAddress">

',
            callback: result => {
                if (result) {
                    const recipientName = $('#emailName').val().trim();
                    const recipientAddress = $('#emailAddress').val().trim();
                    snapshotMailer.send(snapshot.metadata, recipientAddress, recipientName === '' ? undefined : recipientName)
                        .then(info => notify.success('Email sent successfully', "", info))
                        .catch(error => notify.error('Email could not be sent', 'Please check the error message', error));
                }
                switchToSlider();
            }
        });
        $("#emailName").keyboard();
        $("#emailAddress").keyboard();
    }

    function switchToPrintMode(snapshot) {
        mode = "print";
        bootbox.confirm({
            title: 'Confirm printing',
            message: `<p class="dialog">Do you want to print: <em>"<b>${snapshot.metadata.authors.map(a => a.trim()).join(", ")}:</b> ${snapshot.metadata.title.trim()}"</em>?<p>`,
            callback: result => {
                if (result)
                    print(snapshot);
                switchToSlider();
            }
        });
    }

    function print(snapshot) {
        return SnapshotPrinter.print(snapshot.cachedPdf)
            .then(() => notify.success('File has been sent to the printer'))
            .catch(error => notify.error('Print job failed', 'Please check the error message', error));
    }

    async function updateSnapshotList() {
        const errorNotificationTitle = "Update of SNAPSHOT list failed";
        const successNotificationTitle = "Update of SNAPSHOT list successful";

        try {
            const newSnapshotList = await SnapshotListUpdater.update(miscConfig.snapshots.autoUpdate.url);
            if (_.isEqual(newSnapshotList.snapshots, miscConfig.snapshots.articles)) {
                notify.success(successNotificationTitle, "No change detected.", newSnapshotList);
            } else {
                settings.set("snapshots.articles", newSnapshotList.snapshots, {
                    prettify: true
                });
                notify.success(successNotificationTitle, "Reloading …", newSnapshotList)
                    .then(() => location.reload());
            }
        } catch (error) {
            switch (error.errorCode) {
                case SnapshotListUpdater.UpdateError.ERROR_DOWNLOAD_FAILED:
                    notify.error(errorNotificationTitle, "The list could not be downloaded.", error.cause);
                    break;
                case SnapshotListUpdater.UpdateError.ERROR_VERSION_MISMATCH:
                    notify.error(errorNotificationTitle, "Online data has wrong version tag.", error.cause);
                    break;
                case SnapshotListUpdater.UpdateError.ERROR_VALIDATION_FAILED:
                    notify.error(errorNotificationTitle, "The downloaded list is invalid.", error.cause);
                    break;
            }
        }
    }

    // GO!
    new Promise(resolve => $(document).ready(resolve))
        .then(miscConfig.snapshots.autoUpdate.enable ? () => {
            notify.info("Starting update of SNAPSHOT list");
            return updateSnapshotList().reflect();
        } : Promise.resolve())
        .then(async () => {
            const startTime = performance.now();
            const articles = preprocessSnapshotList(miscConfig.snapshots);
            snapshots = articles.map(article => new Snapshot(article, {
                cacheDir: utils.getPath('cache'),
                defaultWidth: 717,
                defaultHeight: 1014
            }));
            notify.updateInitProgressBar("#progressCache", {
                max: snapshots.length
            });
            notify.updateInitProgressBar("#progressDocs", {
                max: snapshots.length
            });

            const cachePDFPromises = [];
            const initDocumentPromises = [];
            const initNestedSlidesPromises = [];
            const initCompletePromises = [];
            let totalNumPages = 0;
            snapshots.forEach(snapshot => {
                let article = snapshot.metadata;

                let cachePromise = snapshot.cacheDocumentPromise.catch(e => {
                    notify.error("Initialization error", `Could not cache "${article.authors.join(", ")}: ${article.title}" (doi: ${article.doi})`, e);
                    throw e;
                });
                let initDocumentPromise = snapshot.initDocumentPromise.catch(e => {
                    notify.error("Initialization error", `Failed to load "${article.authors.join(", ")}: ${article.title}" (doi: ${article.doi})`, e);
                    throw e;
                });
                let cachePagePromises = snapshot.cachePagePromises.catch(e => {
                    notify.error("Initialization error",
                        `Failed to render pages of "${article.authors.join(", ")}: ${article.title}" (doi: ${article.doi})`, e);
                    throw e;
                });

                cachePromise.finally(() => notify.updateInitProgressBar("#progressCache", {
                    now: 1,
                    offset: true
                }));
                cachePagePromises.finally(() =>
                    notify.updateInitProgressBar("#progressDocs", {
                        now: 1,
                        offset: true
                    })
                );

                initDocumentPromise = initDocumentPromise.then(document => {
                    totalNumPages += document.numPages;
                    notify.updateInitProgressBar("#progressPages", {
                        max: totalNumPages
                    });
                    notify.updateInitProgressBar("#progressRendered", {
                        max: totalNumPages
                    });
                    return document;
                });

                let initCompletePromise = cachePagePromises
                    .catch(e => {
                        console.log("Problem processing snapshot", snapshot.metadata, e);
                    })
                    .then(actualCachePagePromises => Promise.all(actualCachePagePromises));

                snapshot.initPagePromises.then(promises => promises.forEach(promise => promise.finally(
                    () => notify.updateInitProgressBar("#progressPages", {
                        now: 1,
                        offset: true
                    }))));

                snapshot.cachePagePromises.then(promises => promises.forEach(promise => promise.finally(
                    () => notify.updateInitProgressBar("#progressRendered", {
                        now: 1,
                        offset: true
                    }))));

                cachePDFPromises.push(cachePromise);
                initDocumentPromises.push(initDocumentPromise);
                initNestedSlidesPromises.push(cachePagePromises);
                initCompletePromises.push(initCompletePromise);
            });

            // create the slider and add it to the DOM (final initialization is done upon insertion into the DOM)
            const {swiper, slideContents} = await SliderInitializer.createTopLevelSlider(snapshots, {
                onMail: miscConfig.mail.enable ? snapshot => switchToMailMode(snapshot) : undefined,
                onPrint: miscConfig.print.enable ? snapshot => switchToPrintMode(snapshot) : undefined,
            });
            document.querySelector('#full-hd-centered').appendChild(swiper.el);

            Promise.all(initNestedSlidesPromises).catch(() => notify.warning("Initialization incomplete", "Some SNAPSHOTS will be unavailable."));
            Promise.all(initCompletePromises)
                .then(notify.closeInitProgressBar)
                .then(() => {
                    initIdleHandlers(createIdleAction(swiper, slideContents));
                    initKeyHandlers(swiper, slideContents);
                    switchToSlider();

                    console.log(`loading took ${(performance.now() - startTime) / 1000.0}s`)
                });
        });

})();
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'PasswordView',
  extends: 'foam.u2.View',

  requires: [
    'foam.u2.TextField'
  ],

  css: `
    ^ .input-field-container {
      position: relative;
    }
    ^ .input-image {
      position: absolute;
      width: 30px;
      height: 30px;
      top: 5px;
      right: 10px;
    }
  `,

  constants: [
    {
      type: 'String',
      name: 'VISIBILITY',
      value: 'images/visibility.svg'
    },
    {
      type: 'String',
      name: 'VISIBILITY_OFF',
      value: 'images/visibility-off.svg'
    }
  ],

  properties: [
    {
      name: 'visibilityIcon',
      factory: function() {
        return this.VISIBILITY_OFF;
      }
    },
    {
      class: 'Boolean',
      name: 'passwordInvisible',
      value: true
    },
    {
      class: 'Boolean',
      name: 'passwordIcon'
    },
    {
      class: 'String',
      name: 'type',
      value: 'password'
    },
    'inputElement'
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.addClass(this.myClass()).start().
        addClass('input-field-container').
        start(this.TextField, {
          type: this.type,
          data$: this.data$,
          onKey: true
        }, this.inputElement$).
        addClass('full-width-input-password').end().
        start('img').show(this.passwordIcon$).addClass('input-image').
        attr('src', this.visibilityIcon$).on('click', this.visible).
        end().
      end();
    },

    function visibleIcon(visibilityIcon, type) {
      this.visibilityIcon = visibilityIcon;
      this.inputElement.setAttribute('type', type);
      this.passwordInvisible = ! this.passwordInvisible;
      this.enableClass('property-password', this.passwordInvisible);
    }
  ],

  listeners: [
    function visible() {
      if ( this.passwordInvisible ) {
        // Make password visible
        this.visibleIcon(this.VISIBILITY, 'text');
      } else {
        // Make password invisible
        this.visibleIcon(this.VISIBILITY_OFF, 'password');
      }
    }
  ]
});
<commit_msg>view password img - center fix - all cases<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'PasswordView',
  extends: 'foam.u2.View',

  requires: [
    'foam.u2.TextField'
  ],

  css: `
    ^ .input-image {
      --fieldSize: /*%INPUTHEIGHT%*/ 32px;
      position: absolute;
      height: calc( var(--fieldSize) / 1.2);
      top: calc( var(--fieldSize) / 15);
      right: 1vh;
    }
  `,

  constants: [
    {
      type: 'String',
      name: 'VISIBILITY',
      value: 'images/visibility.svg'
    },
    {
      type: 'String',
      name: 'VISIBILITY_OFF',
      value: 'images/visibility-off.svg'
    }
  ],

  properties: [
    {
      name: 'visibilityIcon',
      factory: function() {
        return this.VISIBILITY_OFF;
      }
    },
    {
      class: 'Boolean',
      name: 'passwordInvisible',
      value: true
    },
    {
      class: 'Boolean',
      name: 'passwordIcon'
    },
    {
      class: 'String',
      name: 'type',
      value: 'password'
    },
    'inputElement'
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.addClass(this.myClass()).start().
        start(this.TextField, {
          type: this.type,
          data$: this.data$,
          onKey: true
        }, this.inputElement$).
        addClass('full-width-input-password').end().
        start('img').show(this.passwordIcon$).addClass('input-image').
          attr('src', this.visibilityIcon$).on('click', this.visible).
        end().
      end();
    },

    function visibleIcon(visibilityIcon, type) {
      this.visibilityIcon = visibilityIcon;
      this.inputElement.setAttribute('type', type);
      this.passwordInvisible = ! this.passwordInvisible;
      this.enableClass('property-password', this.passwordInvisible);
    }
  ],

  listeners: [
    function visible() {
      if ( this.passwordInvisible ) {
        // Make password visible
        this.visibleIcon(this.VISIBILITY, 'text');
      } else {
        // Make password invisible
        this.visibleIcon(this.VISIBILITY_OFF, 'password');
      }
    }
  ]
});
<|endoftext|>


<commit_before>var zindex = 0;
var screenHeight = window.innerHeight;
var screenWidth = window.innerWidth;
var maxHeight = Math.floor(screenHeight / 3), minHeight = Math.floor(screenHeight / 5);
var maxWidth = Math.floor(screenWidth / 3), minWidth = Math.floor(screenWidth / 5);

// square-window mappings
var relations = {
    "home": {
        "windId": "home_window",
        "dims": {
            "initHeight": "",
            "initWidth": "",
            "prevHeight": "",
            "prevWidth": ""
        },
    },
    "internet": {
        "windId": "internet_window",
        "dims": {
            "initHeight": "",
            "initWidth": "",
            "prevHeight": "",
            "prevWidth": ""
        },
    },
    "pictures": {
        "windId": "pic_window",
        "dims": {
            "initHeight": 340,
            "initWidth": 420,
            "prevHeight": 340,
            "prevWidth": 420
        },
    },
    "videos": {
        "windId": "vid_window",
        "dims": {
            "initHeight": 485,
            "initWidth": 625,
            "prevHeight": 485,
            "prevWidth": 625
        },
    },
    "game": {
        "windId": "game_window",
        "dims": {
            "initHeight": 675,
            "initWidth": 750,
            "prevHeight": 675,
            "prevWidth": 750
        },
    },
    "folder": {
        "windId": "folder_window",
        "dims": {
            "initHeight": 470,
            "initWidth": 620,
            "prevHeight": 470,
            "prevWidth": 620
        },
    }
}

var tempId;
$(document).ready(function() {
    $(".window").addClass("new");

    $(".resize-drag").draggable({
        drag: function(event) { bringForward(this); },
        handle: ".topbar"/*,
        containment: "window"*/
    });

    // for(var squareId in relations) {
    //     var windId = "#" + relations[squareId].windId;
    //     $(windId).resizable({
    //         resize: function(event) {
    //             relations[squareId].dims.prevHeight = $(this).height();
    //             relations[squareId].dims.prevWidth = $(this).width();
    //         },
    //         minHeight: relations[squareId].dims.initHeight,
    //         minWidth: relations[squareId].dims.initWidth
    //     })
    // }

    $(".square").click(function() {
        $(this).css("background-color", "rgba(255, 255, 255, 0.7)");
        var squareId = $(this).attr("id");
        openWindow(relations[squareId].windId);
    });

    $(".exit, .min").click(function() {
        var windId = "#" + $(this).parent().parent().attr("id");
        hideWindow(windId);
        if($(this).hasClass("exit")) {
            if(windId === "#vid_window") { $("#vid").get(0).load(); }
            $(windId).removeClass("opened");
            var squareId = "#" + getSquare($(windId).attr("id"));
            $(squareId).css("background-color", "transparent");
        } else { // min
            var squareId = "#" + getSquare($(windId).attr("id"));
            $(squareId).css("background-color", "rgba(192, 192, 192, 0.5)");
        }
    });

    $(".window").click(function() {
        bringForward(this);
    });
});

function openWindow(windId) {
    zindex++;
    windId = "#" + windId;
    var css = { "display": "block", "position": "absolute", "z-index": zindex };

    if(!($(windId).hasClass("opened"))) {
        // open new window (with delay for flare)
        $("*").css("cursor", "progress");
        var rand = Math.floor(Math.random() * 600);
        setTimeout(function() {
            $(windId).addClass("opened");
            $(windId).addClass("active");

            if(windId === "#pic_window") {
                $("#image_slider").css({"width": "5460px"});
            }

            // randomize position only when opened the first time
            if($(windId).hasClass("new")) {
                css.top = Math.floor(Math.random() * (screen.height / 3 - minHeight + 1)) + minHeight / 2 + "px";
                css.left = Math.floor(Math.random() * (screen.width / 2 - minWidth + 1)) + minWidth / 2 + "px";
                $(windId).removeClass("new");
            }

            $(windId).css(css);
            $("*").css("cursor", "default");
            $("#status span, p.file, img.file, a, .square").css("cursor", "pointer");
        }, rand);
    } else if(!$(windId).hasClass("active")) {
        // reactivate minimized window
        $(windId).addClass("active");
        $(windId).css(css);
    } else {
        // minimize active window
        var squareId = "#" + getSquare($(windId).attr("id"));
        $(squareId).css("background-color", "rgba(192, 192, 192, 0.5)");
        hideWindow(windId);
    }
}

function getSquare(windId) {
    for(var squareId in relations) {
        if(relations[squareId].windId === windId) { return squareId; }
    }
}

function bringForward(wind) {
    zindex++;
    $(wind).css({"z-index": zindex});
}

function hideWindow(windId) {
    $(windId).css("display", "none");
    $(windId).removeClass("active");
}<commit_msg>windows now fade in and out isntead of just popping up<commit_after>var zindex = 0;
var screenHeight = window.innerHeight;
var screenWidth = window.innerWidth;
var maxHeight = Math.floor(screenHeight / 3), minHeight = Math.floor(screenHeight / 5);
var maxWidth = Math.floor(screenWidth / 3), minWidth = Math.floor(screenWidth / 5);

// square-window mappings
var relations = {
    "home": {
        "windId": "home_window",
        "dims": {
            "initHeight": "",
            "initWidth": "",
            "prevHeight": "",
            "prevWidth": ""
        },
    },
    "internet": {
        "windId": "internet_window",
        "dims": {
            "initHeight": "",
            "initWidth": "",
            "prevHeight": "",
            "prevWidth": ""
        },
    },
    "pictures": {
        "windId": "pic_window",
        "dims": {
            "initHeight": 340,
            "initWidth": 420,
            "prevHeight": 340,
            "prevWidth": 420
        },
    },
    "videos": {
        "windId": "vid_window",
        "dims": {
            "initHeight": 485,
            "initWidth": 625,
            "prevHeight": 485,
            "prevWidth": 625
        },
    },
    "game": {
        "windId": "game_window",
        "dims": {
            "initHeight": 675,
            "initWidth": 750,
            "prevHeight": 675,
            "prevWidth": 750
        },
    },
    "folder": {
        "windId": "folder_window",
        "dims": {
            "initHeight": 470,
            "initWidth": 620,
            "prevHeight": 470,
            "prevWidth": 620
        },
    }
}

var tempId;
$(document).ready(function() {
    $(".window").addClass("new");

    $(".resize-drag").draggable({
        drag: function(event) { bringForward(this); },
        handle: ".topbar"/*,
        containment: "window"*/
    });

    // for(var squareId in relations) {
    //     var windId = "#" + relations[squareId].windId;
    //     $(windId).resizable({
    //         resize: function(event) {
    //             relations[squareId].dims.prevHeight = $(this).height();
    //             relations[squareId].dims.prevWidth = $(this).width();
    //         },
    //         minHeight: relations[squareId].dims.initHeight,
    //         minWidth: relations[squareId].dims.initWidth
    //     })
    // }

    $(".square").click(function() {
        $(this).css("background-color", "rgba(255, 255, 255, 0.7)");
        var squareId = $(this).attr("id");
        openWindow(relations[squareId].windId);
    });

    $(".exit, .min").click(function() {
        var windId = "#" + $(this).parent().parent().attr("id");
        hideWindow(windId);
        if($(this).hasClass("exit")) {
            if(windId === "#vid_window") { $("#vid").get(0).load(); }
            $(windId).removeClass("opened");
            var squareId = "#" + getSquare($(windId).attr("id"));
            $(squareId).css("background-color", "transparent");
        } else { // min
            var squareId = "#" + getSquare($(windId).attr("id"));
            $(squareId).css("background-color", "rgba(192, 192, 192, 0.5)");
        }
    });

    $(".window").click(function() {
        bringForward(this);
    });
});

function openWindow(windId) {
    zindex++;
    windId = "#" + windId;
    var css = { "position": "absolute", "z-index": zindex };

    if(!($(windId).hasClass("opened"))) {
        // open new window (with delay for flare)
        $("*").css("cursor", "progress");
        var rand = Math.floor(Math.random() * 600);
        setTimeout(function() {
            $(windId).fadeIn("fast");

            $(windId).addClass("opened");
            $(windId).addClass("active");

            if(windId === "#pic_window") {
                $("#image_slider").css({"width": "5460px"});
            }

            // randomize position only when opened the first time
            if($(windId).hasClass("new")) {
                css.top = Math.floor(Math.random() * (screen.height / 3 - minHeight + 1)) + minHeight / 2 + "px";
                css.left = Math.floor(Math.random() * (screen.width / 2 - minWidth + 1)) + minWidth / 2 + "px";
                $(windId).removeClass("new");
            }

            $(windId).css(css);
            $("*").css("cursor", "default");
            $("#status span, p.file, img.file, a, .square").css("cursor", "pointer");
        }, rand);
    } else if(!$(windId).hasClass("active")) {
        // reactivate minimized window
        $(windId).fadeIn("fast");

        $(windId).addClass("active");
        $(windId).css(css);
    } else {
        // minimize active window
        var squareId = "#" + getSquare($(windId).attr("id"));
        $(squareId).css("background-color", "rgba(192, 192, 192, 0.5)");
        hideWindow(windId);
    }
}

function getSquare(windId) {
    for(var squareId in relations) {
        if(relations[squareId].windId === windId) { return squareId; }
    }
}

function bringForward(wind) {
    zindex++;
    $(wind).css({"z-index": zindex});
}

function hideWindow(windId) {
    // $(windId).css("display", "none");
    $(windId).fadeOut("fast");
    $(windId).removeClass("active");
}<|endoftext|>


<commit_before>'use strict';

var D3 = require('d3');
var MG = require('./metricsgraphics');

exports.flash = function(options) {
    MG.data_graphic({
        title: '',
        data: options.data,
        target: options.target,
        width: 600,
        height: 500,
        left: 100,
        full_width: true,
        transition_on_update: false,
        show_secondary_x_label: false,
        x_extended_ticks: true,
        xax_count: 5,
        xax_format: D3.time.format('%e %b, %y'),
        decimals: 0,
        baselines: [{
            value: 15,
            label: 'Statutory Limit'
        }],
        chart_type: options.data.length !== 0 ? 'line' : 'missing-data',
        missing_text: 'No data',
        legend: options.labels,
        legend_target: options.legend_target,
        aggregate_rollover: true,
        show_tooltips: false,
        interplate: 'linear',
        interpolate_tension: .98,
        area: options.area,
        y_label: 'Days to Complete Process',
        mouseover: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            if (options.data.length) {
                for (i = 1; i <= options.data.length; i++) {
                    var l_span = D3.select(options.legend_target + ' .mg-line' + i + '-legend-color');
                    l_span.text(' ');
                    l_span.text('— ' + options.labels[i - 1]);
                }
            }
            d.values.forEach(function(val, index) {
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                var no_days = d.values[index - 1] ? (val.value - d.values[index - 1].value).toFixed(0) : (val.value).toFixed(0);
                l_span.text('— ' + options.labels[val.line_id - 1] + ' : ' + no_days);
                var format = D3.time.format('%b %d, %Y');
                D3.select(options.target + '_total_trans').text(format(val.date) + ': ' + val.total_trans);
            });
        },
        mouseout: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            d.values.forEach(function(val, index) {
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                l_span.text('— ' + options.labels[index]);
            });
        }
    });
};

exports.singular = function(options, paydash) {

    MG.data_graphic({
        // title: options.title,
        title: '',
        data: options.data,
        width: 600,
        height: 500,
        left: 100,
        full_width: true,
        decimals: 0,
        target: options.target,
        xax_count: 15,
        xax_format: D3.time.format('%e %b, %y'),
        chart_type: options.data.length !== 0 ? 'line' : 'missing-data',
        missing_text: 'No data',
        show_secondary_x_label: false,
        x_extended_ticks: true,
        legend: options.labels,
        legend_target: options.legend_target,
        show_tooltips: false,
        aggregate_rollover: true,
        show_year_markers: true,
        transition_on_update: true,
        interplate: 'linear',
        interpolate_tension: 1,
        area: options.area,
        y_label: 'Days to Complete Process',
        mouseover: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            if (options.data.length) {
                for (i = 1; i <= options.data.length; i++) {
                    var l_span = D3.select(options.legend_target + ' .mg-line' + i + '-legend-color');
                    l_span.text(' ');
                    l_span.text('— ' + paydash[options.legend_labels][i - 1]);
                }
            }
            d.values.forEach(function(val, index) {
                var prefix = D3.formatPrefix(val.value);
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                l_span.text('— ' + paydash[options.legend_labels][val.line_id - 1] + ' : ' + prefix.scale(val.value).toFixed(0));
                var format = D3.time.format('%b %d, %Y');
                D3.select(options.target + '_total_trans').text(format(val.date) + ': ' + val.total_trans);
            });
        },
        mouseout: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            d.values.forEach(function(val, index) {
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                l_span.text('— ' + paydash[options.legend_labels][val.line_id - 1]);
            });
        }
    });
};

exports.small = function(options) {
    MG.data_graphic({
        title: options.title,
        data: options.data,
        width: 295,
        height: 300,
        right: 10,
        left: 90,
        small_text: true,
        xax_count: 3,
        decimals: 0,
        xax_format: D3.time.format('%e %b, %y'),
        chart_type: options.data.length !== 0 ? 'line' : 'missing-data',
        missing_text: 'No data',
        target: options.target,
        legend: options.labels,
        legend_target: options.legend_target,
        full_width: true,
        aggregate_rollover: true,
        x_extended_ticks: true,
        transition_on_update: false,
        max_y: options.max_y || undefined,
        interplate: 'linear',
        linked: true,
        interpolate_tension: 1,
        y_label: 'Days to Complete Process',
        area: options.area,
        show_secondary_x_label: false,
        max_x: options.max_x || undefined,
        min_x: options.min_x || undefined
    });
};
<commit_msg>Clear trans data on mouseout<commit_after>'use strict';

var D3 = require('d3');
var MG = require('./metricsgraphics');

exports.flash = function(options) {
    MG.data_graphic({
        title: '',
        data: options.data,
        target: options.target,
        width: 600,
        height: 500,
        left: 100,
        full_width: true,
        transition_on_update: false,
        show_secondary_x_label: false,
        x_extended_ticks: true,
        xax_count: 5,
        xax_format: D3.time.format('%e %b, %y'),
        decimals: 0,
        baselines: [{
            value: 15,
            label: 'Statutory Limit'
        }],
        chart_type: options.data.length !== 0 ? 'line' : 'missing-data',
        missing_text: 'No data',
        legend: options.labels,
        legend_target: options.legend_target,
        aggregate_rollover: true,
        show_tooltips: false,
        interplate: 'linear',
        interpolate_tension: .98,
        area: options.area,
        y_label: 'Days to Complete Process',
        mouseover: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            if (options.data.length) {
                for (i = 1; i <= options.data.length; i++) {
                    var l_span = D3.select(options.legend_target + ' .mg-line' + i + '-legend-color');
                    l_span.text(' ');
                    l_span.text('— ' + options.labels[i - 1]);
                }
            }
            d.values.forEach(function(val, index) {
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                var no_days = d.values[index - 1] ? (val.value - d.values[index - 1].value).toFixed(0) : (val.value).toFixed(0);
                l_span.text('— ' + options.labels[val.line_id - 1] + ' : ' + no_days);
                var format = D3.time.format('%b %d, %Y');
                D3.select(options.target + '_total_trans').text(format(val.date) + ': ' + val.total_trans);
            });
        },
        mouseout: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            D3.select(options.target + '_total_trans').text('');
            d.values.forEach(function(val, index) {
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                l_span.text('— ' + options.labels[index]);
            });
        }
    });
};

exports.singular = function(options, paydash) {

    MG.data_graphic({
        // title: options.title,
        title: '',
        data: options.data,
        width: 600,
        height: 500,
        left: 100,
        full_width: true,
        decimals: 0,
        target: options.target,
        xax_count: 15,
        xax_format: D3.time.format('%e %b, %y'),
        chart_type: options.data.length !== 0 ? 'line' : 'missing-data',
        missing_text: 'No data',
        show_secondary_x_label: false,
        x_extended_ticks: true,
        legend: options.labels,
        legend_target: options.legend_target,
        show_tooltips: false,
        aggregate_rollover: true,
        show_year_markers: true,
        transition_on_update: true,
        interplate: 'linear',
        interpolate_tension: 1,
        area: options.area,
        y_label: 'Days to Complete Process',
        mouseover: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            if (options.data.length) {
                for (i = 1; i <= options.data.length; i++) {
                    var l_span = D3.select(options.legend_target + ' .mg-line' + i + '-legend-color');
                    l_span.text(' ');
                    l_span.text('— ' + paydash[options.legend_labels][i - 1]);
                }
            }
            d.values.forEach(function(val, index) {
                var prefix = D3.formatPrefix(val.value);
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                l_span.text('— ' + paydash[options.legend_labels][val.line_id - 1] + ' : ' + prefix.scale(val.value).toFixed(0));
                var format = D3.time.format('%b %d, %Y');
                D3.select(options.target + '_total_trans').text(format(val.date) + ': ' + val.total_trans);
            });
        },
        mouseout: function(d, i) {
            if (!d.values) {
                d.values = [d];
            }
            D3.select(options.target + '_total_trans').text('');
            d.values.forEach(function(val, index) {
                var l_span = D3.select(options.legend_target + ' .mg-line' + val.line_id + '-legend-color');
                l_span.text(' ');
                l_span.text('— ' + paydash[options.legend_labels][val.line_id - 1]);
            });
        }
    });
};

exports.small = function(options) {
    MG.data_graphic({
        title: options.title,
        data: options.data,
        width: 295,
        height: 300,
        right: 10,
        left: 90,
        small_text: true,
        xax_count: 3,
        decimals: 0,
        xax_format: D3.time.format('%e %b, %y'),
        chart_type: options.data.length !== 0 ? 'line' : 'missing-data',
        missing_text: 'No data',
        target: options.target,
        legend: options.labels,
        legend_target: options.legend_target,
        full_width: true,
        aggregate_rollover: true,
        x_extended_ticks: true,
        transition_on_update: false,
        max_y: options.max_y || undefined,
        interplate: 'linear',
        linked: true,
        interpolate_tension: 1,
        y_label: 'Days to Complete Process',
        area: options.area,
        show_secondary_x_label: false,
        max_x: options.max_x || undefined,
        min_x: options.min_x || undefined
    });
};
<|endoftext|>


<commit_before>$(document).ready(function() {

	var currentIndex = 1;
	var sectionAnchors = ['profile', 'about-me', 'skills', 'education', 'career', 'projects'];
	var sectionNames = ['', 'About Me', 'Skills', 'Education', 'Career', 'Projects']

	var loadedProgressBars = false;

	$('#fullpage').fullpage({
		anchors: sectionAnchors,
		navigation: true,
		navigationTooltips: sectionNames,
		menu: '#menu',

		afterLoad: function(anchorLink, index) {
			currentIndex = index;

			if(anchorLink == 'skills' && !loadedProgressBars) {

				$('.progress .progress-bar').each(function() {
					var progressBarValue = $(this).attr('aria-valuenow') + '%';
					$(this).animate(
						{ width: progressBarValue },
						{ duration: 150, easing: 'easeOutExpo' }
						);
				});

				loadedProgressBars = true;
			}
		},

		onLeave: function(index, nextIndex, direction) {
			if(nextIndex == 1) { // going to first page
				$('.navbar-fixed-top').removeClass('top-nav-collapse');
				$('.navbar-fixed-top').addClass('navbar-transparent');
			} else {
				$('.navbar-fixed-top').addClass('top-nav-collapse');
				$('.navbar-fixed-top').removeClass('navbar-transparent');
			}
		},

	});

	if(currentIndex == 1) {
		$('#fullpage').fullpage.silentMoveTo(2);
		$('#fullpage').fullpage.silentMoveTo(1);
	}

});<commit_msg>Stop recording history as sections are traversed<commit_after>$(document).ready(function() {

	var currentIndex = 1;
	var sectionAnchors = ['profile', 'about-me', 'skills', 'education', 'career', 'projects'];
	var sectionNames = ['', 'About Me', 'Skills', 'Education', 'Career', 'Projects']

	var loadedProgressBars = false;

	$('#fullpage').fullpage({
		anchors: sectionAnchors,
		navigation: true,
		navigationTooltips: sectionNames,
		menu: '#menu',
		recordHistory: false,

		afterLoad: function(anchorLink, index) {
			currentIndex = index;

			if(anchorLink == 'skills' && !loadedProgressBars) {

				$('.progress .progress-bar').each(function() {
					var progressBarValue = $(this).attr('aria-valuenow') + '%';
					$(this).animate(
						{ width: progressBarValue },
						{ duration: 150, easing: 'easeOutExpo' }
						);
				});

				loadedProgressBars = true;
			}
		},

		onLeave: function(index, nextIndex, direction) {
			if(nextIndex == 1) { // going to first page
				$('.navbar-fixed-top').removeClass('top-nav-collapse');
				$('.navbar-fixed-top').addClass('navbar-transparent');
			} else {
				$('.navbar-fixed-top').addClass('top-nav-collapse');
				$('.navbar-fixed-top').removeClass('navbar-transparent');
			}
		},

	});

	if(currentIndex == 1) {
		$('#fullpage').fullpage.silentMoveTo(2);
		$('#fullpage').fullpage.silentMoveTo(1);
	}

});<|endoftext|>


<commit_before>'use strict';

/**
 * @ngdoc function
 * @name Pear2Pear.service:Pear
 * @description
 * # Pear service
 * Provides controllers with a data model for pear to pear app
 * It serves as an abstraction between Pear data and backend (SwellRT)
 */

angular.module('Pear2Pear')
  .factory('pear', [
           '$rootScope', 'swellRT', '$q', '$timeout', 'base64',
           function($rootScope, swellRT, $q, $timeout, base64) {

    var proxy = {
    };

    // FIXME model prototype
    var urlId = function(id) {
      if (id === undefined) { return ''; }

      return base64.encode(id);
    };

    // map of opened projects
    var openedProjects = {};
    // map of opened communities
    var openedCommunities = {};

    var def = $q.defer();

    function makeModelPublic(model){
      model.addParticipant('@' + SwellRTConfig.swellrtServerDomain,
                           null,
                           function(err){
                             console.log('ERROR: ' + err);
                           }
                          );
    }

    var communities = {

      all: function() {

        var communities = $q.defer();
        var foundCommunities = $q.defer();
        var foundProjectNumbers = $q.defer();

        var queries = $q.all([
          foundCommunities.promise,
          foundProjectNumbers.promuse
        ]);

        var comms = {};
        var nums = {};

        SwellRT.query(
          {
            'root.type': 'community'
          },
          function(result){
            angular.forEach(result.result, function(val) {
              comms[val.root.id] = val.root;
            });

            foundCommunities.resolve(comms);
          },
          function(e){
            foundCommunities.reject(e);
          }
        );
        SwellRT.query(
          {_aggregate:
           [{$match: {'root.type': 'project'}},
            {$unwind: '$root.communities'},
            {$group :
             {_id:'$root.communities',
              number: { $sum : 1 }
             }
            }]},
          function(result){
            nums = result.result;
            foundProjectNumbers.resolve(nums);
          },
          function(e){
            foundCommunities.reject(e);
          }
        );

        queries.then(function(){
          angular.forEach(nums, function(val){
            comms[val._id].numProjects = val.number;
          });
          communities.resolve(comms);

        });
        return communities.promise;
      },

      find: function(urlId) {

        var id = base64.decode(urlId);
        var comDef = $q.defer();
        var community = comDef.promise;

        if (!openedCommunities[id]) {
          openedCommunities[id] = comDef.promise;
          window.SwellRT.openModel(id, function(model){
            var pr = swellRT.proxy(model);
            comDef.resolve(pr);
          }, function(error){
            console.log(error);
            comDef.reject(error);
          });
        } else {
          openedCommunities[id].then(
            function(r){
              comDef.resolve(r);
            });
        }

        var allSnapshot = function(){
              var foundProjects = $q.defer();
              SwellRT.query(
                {
                  'root.type': 'project',
                  'root.communities': id,
                  $and: [{
                    $or: [
                      {'root.shareMode': 'public'},
                      {'root.supporters': users.current()},
                      {'root.contributors': users.current()}
                    ]
                  }]
                },
                function(result){
                  var projs = [];
                  angular.forEach(result.result, function(val) {
                    projs.push(val.root);
                  });
                 foundProjects.resolve(projs);
                },
                function(e){
                  foundProjects.reject(e);
                }
              );
              return foundProjects.promise;
      };
      return {
          community: comDef.promise,
          projects: {

            allSnapshot: allSnapshot,

            all: function() {
              var projsDef = $q.defer();
              allSnapshot().then(function(all){
                var promises = {};
                if (all.length > 0){
                  angular.forEach(all, function(val){
                    var projDef = $q.defer();
                    promises[val.id] = projDef.promise;
                    projects.find(base64.encode(val.id)).then(function(model){
                      $timeout(function(){
                        projDef.resolve(model);
                      });
                    });
                  });
                  projsDef.resolve($q.all(promises));
                } else {
                  projsDef.resolve([]);
                }
              });

              return projsDef.promise;
            },
            destroy: function(projId){
              var i = community.projects.indexOf(projId);
              if (i > -1){
                community.projects.splice(i,1);
              }
            }
          }
        };
      },
      create: function(data, callback) {
        var id = window.SwellRT.createModel(function(model){

          makeModelPublic(model);
          var p = swellRT.proxy(model);

          $timeout(function(){
            p.type = 'community';
            p.name = data.name;
            p.id = id;
            p.projects = [];
            callback(p);
          });
        });
      },
      destroy: function(urlId) {
        var id = base64.decode(urlId);
        // currently not supported by SwellRT
        return urlId;
      }

    };

    var findProjects = function(urlId) {
        var id = base64.decode(urlId);
        var def = $q.defer();
        if (!openedProjects[id]) {
          openedProjects[id] = def.promise;
          window.SwellRT.openModel(id, function(model){
            var pr = swellRT.proxy(model);
            def.resolve(pr);
          }, function(error){
            console.log(error);
            def.reject(error);
          });
        } else {
          openedProjects[id].then(
            function(r){
              def.resolve(r);
            });
        }
        return def.promise;
    };
    var projects = {

      find: findProjects,

      create: function(callback, communityId) {
        var id = window.SwellRT.createModel(function(model){

          makeModelPublic(model);
          var proxyProj = swellRT.proxy(model);
          $timeout(function(){
            proxyProj.type = 'project';
            proxyProj.communities = (communityId) ? [communityId] : [];
            proxyProj.id = id;
            proxyProj.title = '';
            proxyProj.chat = [];
            proxyProj.pad = new swellRT.TextObject();
            proxyProj.needs = [];
            proxyProj.promoter = users.current();
            proxyProj.supporters = [];
            proxyProj.contributors = [users.current()];
            proxyProj.shareMode = 'link';
            var d = $q.defer();
            d.resolve(proxyProj);
            openedProjects[id] = d.promise;
            callback(proxyProj);
          });
        });
      },

      setShareMode: function(projId, shareMode){
        projects.find(projId).then(
          function(project){
            $timeout(function(){
              project.shareMode = shareMode;
            });
          }
        );
      },

      addContributor: function(projId, user){
        if (!user){
          user = users.current();
        }
        console.log('user',user);
        projects.find(projId).then(
          function(p){
            if (user && p.contributors.indexOf(user) < 0){
              p.contributors.push(user);
            }
          });
      }
    };

    var users = {
      current: function() {
        return window.sessionStorage.getItem('userId');
      },
      setCurrent: function(name) {
        var cleanedName = name ? name.trim() : name;

        return window.sessionStorage.setItem('userId', cleanedName);
      },
      isCurrent: function(user) {
        return user === users.current();
      },
      loggedIn: function() {
        return users.current() !== 'undefined' && users.current() !== null;
      }
    };

    var addChatMessage = function(projectId, message) {
      projects.find(projectId).then(function(project){
        project.chat.push({
          text: message,
          who: users.current(),
          time: (new Date()).toJSON()
        });
        projects.addContributor(projectId);
      }, function(error){
        console.log(error);
      });
    };

    var toggleSupport = function(projectId) {
      projects.find(base64.encode(projectId)).then(
        function(model){
          var index = model.supporters.indexOf(users.current());

          $timeout(function(){
            if (index > -1) {
              model.supporters.splice(index, 1);
            } else {
              model.supporters.push(users.current());
            }
          });
        },
        function(error){
          console.log(error);
        }
      );
    };

    var registerUser = function(userName, password, onSuccess, onError){
      window.SwellRT.registerUser(SwellRTConfig.server, userName, password, onSuccess, onError);
    };

    var startSession = function(userName, password, onSuccess, onError){

      // if login with user Name, close previous anonimous session
      if (userName){
        window.SwellRT.stopSession();
      }
      window.SwellRT.startSession(
        SwellRTConfig.server, userName || SwellRT.user.ANONYMOUS, password || '',
        function(){
          SwellRTConfig.swellrtServerDomain = __session.domain;
          SwellRT.on(SwellRT.events.NETWORK_CONNECTED, onSuccess);
        }, onError);
    };

    window.onSwellRTReady = function () {
      startSession(null, null, function(){
          $timeout(
            function() {
              communities.all();
              def.resolve(SwellRT);
            });
        },
        function(error) {
          console.log(error);
        });
      // to avoid multiple calls
      window.onSwellRTReady = null;
    };

    if (window.SwellRT && typeof window.onSwellRTReady === 'function') {
      window.onSwellRTReady();
    }

    return {
      communities: communities,
      projects: projects,
      users: users,
      urlId: urlId,
      addChatMessage: addChatMessage,
      toggleSupport: toggleSupport,
      startSession: startSession,
      registerUser: registerUser,
      onLoad: function(f) {
        def.promise.then(f);
      }
    };
  }]);
<commit_msg>show only number of public projects<commit_after>'use strict';

/**
 * @ngdoc function
 * @name Pear2Pear.service:Pear
 * @description
 * # Pear service
 * Provides controllers with a data model for pear to pear app
 * It serves as an abstraction between Pear data and backend (SwellRT)
 */

angular.module('Pear2Pear')
  .factory('pear', [
           '$rootScope', 'swellRT', '$q', '$timeout', 'base64',
           function($rootScope, swellRT, $q, $timeout, base64) {

    var proxy = {
    };

    // FIXME model prototype
    var urlId = function(id) {
      if (id === undefined) { return ''; }

      return base64.encode(id);
    };

    // map of opened projects
    var openedProjects = {};
    // map of opened communities
    var openedCommunities = {};

    var def = $q.defer();

    function makeModelPublic(model){
      model.addParticipant('@' + SwellRTConfig.swellrtServerDomain,
                           null,
                           function(err){
                             console.log('ERROR: ' + err);
                           }
                          );
    }

    var communities = {

      all: function() {

        var communities = $q.defer();
        var foundCommunities = $q.defer();
        var foundProjectNumbers = $q.defer();

        var queries = $q.all([
          foundCommunities.promise,
          foundProjectNumbers.promuse
        ]);

        var comms = {};
        var nums = {};

        SwellRT.query(
          {
            'root.type': 'community'
          },
          function(result){
            angular.forEach(result.result, function(val) {
              comms[val.root.id] = val.root;
            });

            foundCommunities.resolve(comms);
          },
          function(e){
            foundCommunities.reject(e);
          }
        );
        SwellRT.query(
          {_aggregate:
           [{$match: {
             'root.type': 'project',
             'root.shareMode': 'public'
           }},
            {$unwind: '$root.communities'},
            {$group :
             {_id:'$root.communities',
              number: { $sum : 1 }
             }
            }]},
          function(result){
            nums = result.result;
            foundProjectNumbers.resolve(nums);
          },
          function(e){
            foundCommunities.reject(e);
          }
        );

        queries.then(function(){
          angular.forEach(nums, function(val){
            comms[val._id].numProjects = val.number;
          });
          communities.resolve(comms);

        });
        return communities.promise;
      },

      find: function(urlId) {

        var id = base64.decode(urlId);
        var comDef = $q.defer();
        var community = comDef.promise;

        if (!openedCommunities[id]) {
          openedCommunities[id] = comDef.promise;
          window.SwellRT.openModel(id, function(model){
            var pr = swellRT.proxy(model);
            comDef.resolve(pr);
          }, function(error){
            console.log(error);
            comDef.reject(error);
          });
        } else {
          openedCommunities[id].then(
            function(r){
              comDef.resolve(r);
            });
        }

        var allSnapshot = function(){
              var foundProjects = $q.defer();
              SwellRT.query(
                {
                  'root.type': 'project',
                  'root.communities': id,
                  $and: [{
                    $or: [
                      {'root.shareMode': 'public'},
                      {'root.supporters': users.current()},
                      {'root.contributors': users.current()}
                    ]
                  }]
                },
                function(result){
                  var projs = [];
                  angular.forEach(result.result, function(val) {
                    projs.push(val.root);
                  });
                 foundProjects.resolve(projs);
                },
                function(e){
                  foundProjects.reject(e);
                }
              );
              return foundProjects.promise;
      };
      return {
          community: comDef.promise,
          projects: {

            allSnapshot: allSnapshot,

            all: function() {
              var projsDef = $q.defer();
              allSnapshot().then(function(all){
                var promises = {};
                if (all.length > 0){
                  angular.forEach(all, function(val){
                    var projDef = $q.defer();
                    promises[val.id] = projDef.promise;
                    projects.find(base64.encode(val.id)).then(function(model){
                      $timeout(function(){
                        projDef.resolve(model);
                      });
                    });
                  });
                  projsDef.resolve($q.all(promises));
                } else {
                  projsDef.resolve([]);
                }
              });

              return projsDef.promise;
            },
            destroy: function(projId){
              var i = community.projects.indexOf(projId);
              if (i > -1){
                community.projects.splice(i,1);
              }
            }
          }
        };
      },
      create: function(data, callback) {
        var id = window.SwellRT.createModel(function(model){

          makeModelPublic(model);
          var p = swellRT.proxy(model);

          $timeout(function(){
            p.type = 'community';
            p.name = data.name;
            p.id = id;
            p.projects = [];
            callback(p);
          });
        });
      },
      destroy: function(urlId) {
        var id = base64.decode(urlId);
        // currently not supported by SwellRT
        return urlId;
      }

    };

    var findProjects = function(urlId) {
        var id = base64.decode(urlId);
        var def = $q.defer();
        if (!openedProjects[id]) {
          openedProjects[id] = def.promise;
          window.SwellRT.openModel(id, function(model){
            var pr = swellRT.proxy(model);
            def.resolve(pr);
          }, function(error){
            console.log(error);
            def.reject(error);
          });
        } else {
          openedProjects[id].then(
            function(r){
              def.resolve(r);
            });
        }
        return def.promise;
    };
    var projects = {

      find: findProjects,

      create: function(callback, communityId) {
        var id = window.SwellRT.createModel(function(model){

          makeModelPublic(model);
          var proxyProj = swellRT.proxy(model);
          $timeout(function(){
            proxyProj.type = 'project';
            proxyProj.communities = (communityId) ? [communityId] : [];
            proxyProj.id = id;
            proxyProj.title = '';
            proxyProj.chat = [];
            proxyProj.pad = new swellRT.TextObject();
            proxyProj.needs = [];
            proxyProj.promoter = users.current();
            proxyProj.supporters = [];
            proxyProj.contributors = [users.current()];
            proxyProj.shareMode = 'link';
            var d = $q.defer();
            d.resolve(proxyProj);
            openedProjects[id] = d.promise;
            callback(proxyProj);
          });
        });
      },

      setShareMode: function(projId, shareMode){
        projects.find(projId).then(
          function(project){
            $timeout(function(){
              project.shareMode = shareMode;
            });
          }
        );
      },

      addContributor: function(projId, user){
        if (!user){
          user = users.current();
        }
        console.log('user',user);
        projects.find(projId).then(
          function(p){
            if (user && p.contributors.indexOf(user) < 0){
              p.contributors.push(user);
            }
          });
      }
    };

    var users = {
      current: function() {
        return window.sessionStorage.getItem('userId');
      },
      setCurrent: function(name) {
        var cleanedName = name ? name.trim() : name;

        return window.sessionStorage.setItem('userId', cleanedName);
      },
      isCurrent: function(user) {
        return user === users.current();
      },
      loggedIn: function() {
        return users.current() !== 'undefined' && users.current() !== null;
      }
    };

    var addChatMessage = function(projectId, message) {
      projects.find(projectId).then(function(project){
        project.chat.push({
          text: message,
          who: users.current(),
          time: (new Date()).toJSON()
        });
        projects.addContributor(projectId);
      }, function(error){
        console.log(error);
      });
    };

    var toggleSupport = function(projectId) {
      projects.find(base64.encode(projectId)).then(
        function(model){
          var index = model.supporters.indexOf(users.current());

          $timeout(function(){
            if (index > -1) {
              model.supporters.splice(index, 1);
            } else {
              model.supporters.push(users.current());
            }
          });
        },
        function(error){
          console.log(error);
        }
      );
    };

    var registerUser = function(userName, password, onSuccess, onError){
      window.SwellRT.registerUser(SwellRTConfig.server, userName, password, onSuccess, onError);
    };

    var startSession = function(userName, password, onSuccess, onError){

      // if login with user Name, close previous anonimous session
      if (userName){
        window.SwellRT.stopSession();
      }
      window.SwellRT.startSession(
        SwellRTConfig.server, userName || SwellRT.user.ANONYMOUS, password || '',
        function(){
          SwellRTConfig.swellrtServerDomain = __session.domain;
          SwellRT.on(SwellRT.events.NETWORK_CONNECTED, onSuccess);
        }, onError);
    };

    window.onSwellRTReady = function () {
      startSession(null, null, function(){
          $timeout(
            function() {
              communities.all();
              def.resolve(SwellRT);
            });
        },
        function(error) {
          console.log(error);
        });
      // to avoid multiple calls
      window.onSwellRTReady = null;
    };

    if (window.SwellRT && typeof window.onSwellRTReady === 'function') {
      window.onSwellRTReady();
    }

    return {
      communities: communities,
      projects: projects,
      users: users,
      urlId: urlId,
      addChatMessage: addChatMessage,
      toggleSupport: toggleSupport,
      startSession: startSession,
      registerUser: registerUser,
      onLoad: function(f) {
        def.promise.then(f);
      }
    };
  }]);
<|endoftext|>


<commit_before>describe("About Arrays", function() {

  // We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe(FILL_ME_IN); // A mistake?-- http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(FILL_ME_IN);

    var multiTypeArray = [0, 1, "two", function() { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(FILL_ME_IN);
    expect(multiTypeArray[2]).toBe(FILL_ME_IN);
    expect(multiTypeArray[3]()).toBe(FILL_ME_IN);
    expect(multiTypeArray[4].value1).toBe(FILL_ME_IN);
    expect(multiTypeArray[4]["value2"]).toBe(FILL_ME_IN);
    expect(multiTypeArray[5][0]).toBe(FILL_ME_IN);
  });

  it("should understand array literals", function() {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, FILL_ME_IN]);

    array.push(3);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should understand array length", function() {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(FILL_ME_IN);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(FILL_ME_IN);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(FILL_ME_IN);
  });

  it("should slice arrays", function() {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(FILL_ME_IN);
    expect(array.slice(0, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 2)).toEqual(FILL_ME_IN);
    expect(array.slice(2, 20)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 0)).toEqual(FILL_ME_IN);
    expect(array.slice(3, 100)).toEqual(FILL_ME_IN);
    expect(array.slice(5, 1)).toEqual(FILL_ME_IN);
  });

  it("should know array references", function() {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe(FILL_ME_IN);

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe(FILL_ME_IN);

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe(FILL_ME_IN);
  });

  it("should push and pop", function() {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual(FILL_ME_IN);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });

  it("should know about shifting arrays", function() {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual(FILL_ME_IN);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(FILL_ME_IN);
    expect(array).toEqual(FILL_ME_IN);
  });
});
<commit_msg>Changed values in AboutArrays.js in order to pass all tests.<commit_after>describe("About Arrays", function() {

  // We shall contemplate truth by testing reality, via spec expectations.
  it("should create arrays", function() {
    var emptyArray = [];
    expect(typeof(emptyArray)).toBe("object"); // A mistake?-- http:javascript.crockford.com/remedial.html
    expect(emptyArray.length).toBe(0);

    var multiTypeArray = [0, 1, "two", function() { return 3; }, {value1: 4, value2: 5}, [6, 7]];
    expect(multiTypeArray[0]).toBe(0);
    expect(multiTypeArray[2]).toBe("two");
    expect(multiTypeArray[3]()).toBe(3);
    expect(multiTypeArray[4].value1).toBe(4);
    expect(multiTypeArray[4]["value2"]).toBe(5);
    expect(multiTypeArray[5][0]).toBe(6);
  });

  it("should understand array literals", function() {
    var array = [];
    expect(array).toEqual([]);

    array[0] = 1;
    expect(array).toEqual([1]);

    array[1] = 2;
    expect(array).toEqual([1, 2]);

    array.push(3);
    expect(array).toEqual([1, 2, 3]);
  });

  it("should understand array length", function() {
    var fourNumberArray = [1, 2, 3, 4];

    expect(fourNumberArray.length).toBe(4);
    fourNumberArray.push(5, 6);
    expect(fourNumberArray.length).toBe(6);

    var tenEmptyElementArray = new Array(10);
    expect(tenEmptyElementArray.length).toBe(10);

    tenEmptyElementArray.length = 5;
    expect(tenEmptyElementArray.length).toBe(5);
  });

  it("should slice arrays", function() {
    var array = ["peanut", "butter", "and", "jelly"];

    expect(array.slice(0, 1)).toEqual(["peanut"]);
    expect(array.slice(0, 2)).toEqual(["peanut", "butter"]);
    expect(array.slice(2, 2)).toEqual([]);
    expect(array.slice(2, 20)).toEqual(["and", "jelly"]);
    expect(array.slice(3, 0)).toEqual([]);
    expect(array.slice(3, 100)).toEqual(["jelly"]);
    expect(array.slice(5, 1)).toEqual([]);
  });

  it("should know array references", function() {
    var array = [ "zero", "one", "two", "three", "four", "five" ];

    function passedByReference(refArray) {
      refArray[1] = "changed in function";
    }
    passedByReference(array);
    expect(array[1]).toBe("changed in function");

    var assignedArray = array;
    assignedArray[5] = "changed in assignedArray";
    expect(array[5]).toBe("changed in assignedArray");

    var copyOfArray = array.slice();
    copyOfArray[3] = "changed in copyOfArray";
    expect(array[3]).toBe("three");
  });

  it("should push and pop", function() {
    var array = [1, 2];
    array.push(3);

    expect(array).toEqual([1, 2, 3]);

    var poppedValue = array.pop();
    expect(poppedValue).toBe(3);
    expect(array).toEqual([1, 2]);
  });

  it("should know about shifting arrays", function() {
    var array = [1, 2];

    array.unshift(3);
    expect(array).toEqual([3, 1, 2]);

    var shiftedValue = array.shift();
    expect(shiftedValue).toEqual(3);
    expect(array).toEqual([1, 2]);
  });
});
<|endoftext|>