<commit_before>/**
 * ngNavigation/tests/ngNavigation.spec.js
 *
 * Copyright (c) 2015 David Vuong
 * Licensed MIT
 */
'use strict';

describe('ngNavigation', function () {
    beforeEach(module('ngNavigation'));

    var Navigation;
    beforeEach(inject(function (_Navigation_) {
        Navigation = _Navigation_;
    }));

    describe('Auxiliary, p._endsWith', function () {
        it('should be true if ends up suffix', function () {
            expect(Navigation._p._endsWith('hello, world/', '/')).toBe(true);
        });

        it('should be false if not ends up suffix', function () {
            expect(Navigation._p._endsWith('hello, world/', 'x')).toBe(false);
        });

        it('should be false when the string is empty', function () {
            expect(Navigation._p._endsWith('', '/')).toBe(false);
        });
    });

    describe('Auxiliary, p._route', function () {
        var $location;
        beforeEach(inject(function (_$location_) {
            $location = _$location_;
        }));

        it('should call $location.path without params', function () {
            spyOn($location, 'search');

            Navigation._p._route('/example');
            expect($location.search).not.toHaveBeenCalled();
        });

        it('should call $location.path.search with params', function () {
            spyOn($location, 'search');

            Navigation._p._route('/example', { param: '1' });
            expect($location.search).toHaveBeenCalled();
        });
    });

    describe('Auxiliary, p._overridesDefaults', function () {
        it('should not override with undefined values', function () {
            Navigation._p._overrideDefaults({ appendSlash: undefined });
            expect(Navigation.getDefaultOptions().appendSlash).toBe(false);
        });

        it('should override with defined values', function () {
            Navigation._p._overrideDefaults({ stripSlash: true });
            expect(Navigation.getDefaultOptions().stripSlash).toBe(true);
        });

        it('should throw exception if stripSlash and appendSlash are true', function () {
            expect(function () {
                Navigation._p._overrideDefaults({ stripSlash: true, appendSlash: true });
            }).toThrow();
        });

        it('should not override with no values at all', function () {
            var copy = {};
            angular.copy(Navigation.getDefaultOptions(), copy);
            Navigation._p._overrideDefaults({});
            expect(copy).toEqual(Navigation.getDefaultOptions());
        });
    });

    describe('Auxiliary, p._deconstructUrlPath', function () {
        it('should separate the url and params if both exists', function () {
            var parsed = Navigation._p._deconstructUrlPath('/example?hello=world&x=y');
            expect(parsed).toEqual({ url: '/example', params: { hello: 'world', x: 'y' }});
        });

        it('should not give me params if no query params in url', function () {
            var parsed = Navigation._p._deconstructUrlPath('/example');
            expect(parsed).toEqual({ url: '/example', params: {}});
        });
    });

    describe('Core, self.init', function () {
        it('should initialize instance variables on self', function () {
            Navigation.init();

            expect(Navigation._hasInit).toBeDefined();
            expect(Navigation._isClearing).toBeDefined();
            expect(Navigation._isRouting).toBeDefined();
            expect(Navigation._routeStack).toBeDefined();
        });

        it('should be idempotent', function () {
            Navigation.init();
            expect(Navigation._hasInit).toBe(true);

            spyOn(Navigation._p, '_overrideDefaults');
            Navigation.init();

            expect(Navigation._hasInit).toBe(true);
            expect(Navigation._p._overrideDefaults).not.toHaveBeenCalled();
        });

        it('should start listening on route changes', function () {
            inject(function ($rootScope) {
                spyOn($rootScope, '$on');
                Navigation.init();
                expect($rootScope.$on).toHaveBeenCalled();
            });
        });

        it('should not update stack if no previous route exists', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                $rootScope.$broadcast('$routeChangeSuccess', {
                    originalPath: '/test', params: {} }, undefined
                );
                expect(Navigation._routeStack.length).toBe(0);
            });
        });

        it('should update stack if previous route exists', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };

                // event, currentPath, previousPath...
                $rootScope.$broadcast('$routeChangeSuccess', pathA, undefined);
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                var pathA_ = { url: '/test-a', params: {}, label: undefined };
                expect(Navigation._routeStack[0]).toEqual(pathA_);
            });
        });

        it('should not update if isRouting=true', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                Navigation._isRouting = true;
                spyOn(Navigation, 'pushToRouteStack');

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);

                expect(Navigation.pushToRouteStack).not.toHaveBeenCalled();
            });
        });

        it('should not update when isClearing=true', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                Navigation._isClearing = true;
                spyOn(Navigation, 'pushToRouteStack');

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);

                expect(Navigation.pushToRouteStack).not.toHaveBeenCalled();
            });
        });

        it('should keep route stack empty when isClearing=true', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                // Successfully added a new "previous" route to the stack.
                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                // Clear the stack and set it to not be added in the next route.
                Navigation._routeStack.length = 0;
                Navigation._isClearing = true;
                expect(Navigation._routeStack.length).toBe(0);

                // Cause another route, expect it to remain empty.
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(0);
            });
        });

        it('should pop stack if A->B [A] then B->A, giving [A, B] instead of [A]', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };

                // I'm at /test-b, was at /test-a.
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                // I'm at going to /test-a was at test-b/
                $rootScope.$broadcast('$routeChangeSuccess', pathA, pathB);
                expect(Navigation._routeStack.length).toBe(1);

                var pathB_ = { url: '/test-b', params: {}, label: undefined };
                expect(Navigation._routeStack[0]).toEqual(pathB_);
            });
        });
    });

    describe('Core, self.peakRouteStack', function () {
        it('should return an empty object if stack is empty', function () {
            Navigation.init();
            expect(Navigation._routeStack.length).toBe(0);
            expect(Navigation.peakRouteStack()).toEqual({});
        });

        it('should return the most recent previous route', function () {
            inject(function ($rootScope) {
                Navigation.init();

                var pathA = {originalPath: '/test-a', params: {}};
                var pathB = {originalPath: '/test-b', params: {}};

                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);

                var pathA_ = {url: '/test-a', params: {}, label: undefined};
                expect(Navigation.peakRouteStack()).toEqual(pathA_);
            });
        });
    });

    describe('Core, self.isBackRouteAvailable', function () {
        it('should be true if not empty', function () {
            Navigation.init();
            Navigation._routeStack.push({url: '/test-a', params: {}, label: undefined});
            expect(Navigation.isBackRouteAvailable()).toBe(true);
        });

        it('should be false if empty', function () {
            Navigation.init();
            expect(Navigation.isBackRouteAvailable()).toBe(false);
        });
    });

    describe('Core, self.clearRouteStack', function () {
        it('should clear route stack', function () {
            Navigation.init();
            Navigation._routeStack.push({url: '/test-a', params: {}, label: undefined});
            Navigation.clearRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should not populate route stack with any new routes', function () {
            Navigation.init();
            Navigation.clearRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should set isClearing=true', function () {
            Navigation.init();
            Navigation.clearRouteStack();
            expect(Navigation._isClearing).toBe(true);
        });
    });

    describe('Core, self.pushToRouteStack', function () {
        it('should push to route stack', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts');

            var path = { url: '/accounts', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should not push to route stack if duplicate', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts');
            Navigation.pushToRouteStack('/accounts');
            Navigation.pushToRouteStack('/accounts', { params: { x: 1 }});

            expect(Navigation._routeStack.length).toBe(1);
        });

        it('should label the route if label exists', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts', { label: 'Back' });

            var path = { url: '/accounts', params: {}, label: 'Back' };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should parse query params from url if exists', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts?x=y&a=b&d=d');

            var path = { url: '/accounts', params: { x: 'y', a: 'b', d: 'd' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should override params if query params in url', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts?x=y', { params: { a: 'b' } });

            var path = { url: '/accounts', params: { x: 'y' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should push with options.params if exists', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts/10', { params: { a: 'b'} });

            var path = { url: '/accounts/10', params: { a: 'b' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should not push if url does not exist', function () {
            Navigation.init();
            Navigation.pushToRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should not push if url does not exist', function () {
            Navigation.init();
            Navigation.pushToRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should add trailing slash if not exists', function () {
            Navigation.init({ appendSlash: true });
            Navigation.pushToRouteStack('/accounts');

            var path = { url: '/accounts/', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should add trailing slash if not exists with query params', function () {
            Navigation.init({ appendSlash: true });
            Navigation.pushToRouteStack('/accounts?x=y');

            var path = { url: '/accounts/', params: { x: 'y' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should not append slash if already exists', function () {
            Navigation.init({ appendSlash: true });
            Navigation.pushToRouteStack('/accounts/');

            var path = { url: '/accounts/', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should should strip slash if exists', function () {
            Navigation.init({ stripSlash: true });
            Navigation.pushToRouteStack('/accounts/');

            var path = { url: '/accounts', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should should strip slash if exists with query params', function () {
            Navigation.init({ stripSlash: true });
            Navigation.pushToRouteStack('/accounts/?x=y');

            var path = { url: '/accounts', params: { x: 'y' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should should not strip slash if not exists', function () {
            Navigation.init({ stripSlash: true });
            Navigation.pushToRouteStack('/accounts');

            var path = { url: '/accounts', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });
    });

    describe('Core, self.routeTo', function () {
        it('should not route when isRouting=true', function () {
            Navigation.init();

            spyOn(Navigation._p, '_route');
            Navigation._isRouting = true;
            Navigation.routeTo('/accounts');
            expect(Navigation._p._route).not.toHaveBeenCalled();
        });

        it('should clear stack when clearStack=true', function () {
            Navigation.init();

            spyOn(Navigation, 'clearRouteStack');
            Navigation.routeTo('/accounts', { clearStack: true });
            expect(Navigation.clearRouteStack).toHaveBeenCalled();
        });

        it('should not clear stack when clearStack is not set', function () {
            Navigation.init();

            spyOn(Navigation, 'clearRouteStack');
            Navigation.routeTo('/accounts');
            expect(Navigation.clearRouteStack).not.toHaveBeenCalled();
        });

        it('should route when routeTo is called', function () {
            Navigation.init();

            spyOn(Navigation._p, '_route');
            Navigation.routeTo('/accounts');
            expect(Navigation._p._route).toHaveBeenCalled();
        });
    });

    describe('Core, self.back', function () {
        it('should not pop stack when stack is empty', function () {
            Navigation.init();

            spyOn(Navigation._routeStack, 'pop');
            Navigation.back();
            expect(Navigation._routeStack.pop).not.toHaveBeenCalled();
        });

        it('should use fallback stack when stack is empty', function () {
            Navigation.init();

            spyOn(Navigation._routeStack, 'pop');
            spyOn(Navigation._p, '_route');
            Navigation.back({ url: '/accounts', params: { x: 'y' } });

            expect(Navigation._routeStack.pop).not.toHaveBeenCalled();
            expect(Navigation._p._route).toHaveBeenCalled();
        });

        it('should use fallback stack when stack is empty (only url)', function () {
            Navigation.init();

            spyOn(Navigation._routeStack, 'pop');
            spyOn(Navigation._p, '_route');
            Navigation.back({ url: '/accounts' });

            expect(Navigation._routeStack.pop).not.toHaveBeenCalled();
            expect(Navigation._p._route).toHaveBeenCalledWith('/accounts', {});
        });

        it('should pop stack when going back to previous page', function () {
            inject(function ($rootScope, $window) {
                Navigation.init();

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                // Stub out `$window.history.back` to avoid karma errors.
                spyOn($window.history, 'back');
                Navigation.back();
                expect(Navigation._routeStack.length).toBe(0);
            });
        });
    });
});
<commit_msg>tests(ngNavigation.*): fixed it(...) terminology<commit_after>/**
 * ngNavigation/tests/ngNavigation.spec.js
 *
 * Copyright (c) 2015 David Vuong
 * Licensed MIT
 */
'use strict';

describe('ngNavigation', function () {
    beforeEach(module('ngNavigation'));

    var Navigation;
    beforeEach(inject(function (_Navigation_) {
        Navigation = _Navigation_;
    }));

    describe('Auxiliary, p._endsWith', function () {
        it('should be true when str ends with suffix', function () {
            expect(Navigation._p._endsWith('hello, world/', '/')).toBe(true);
        });

        it('should be false when str does not end suffix', function () {
            expect(Navigation._p._endsWith('hello, world/', 'x')).toBe(false);
        });

        it('should be false when the string is empty', function () {
            expect(Navigation._p._endsWith('', '/')).toBe(false);
        });
    });

    describe('Auxiliary, p._route', function () {
        var $location;
        beforeEach(inject(function (_$location_) {
            $location = _$location_;
        }));

        it('should call $location.path when no params provided', function () {
            spyOn($location, 'search');

            Navigation._p._route('/example');
            expect($location.search).not.toHaveBeenCalled();
        });

        it('should call $location.path.search when params provided', function () {
            spyOn($location, 'search');

            Navigation._p._route('/example', { param: '1' });
            expect($location.search).toHaveBeenCalled();
        });
    });

    describe('Auxiliary, p._overridesDefaults', function () {
        it('should not override when values are undefined', function () {
            Navigation._p._overrideDefaults({ appendSlash: undefined });
            expect(Navigation.getDefaultOptions().appendSlash).toBe(false);
        });

        it('should override when values are defined', function () {
            Navigation._p._overrideDefaults({ stripSlash: true });
            expect(Navigation.getDefaultOptions().stripSlash).toBe(true);
        });

        it('should throw exception when stripSlash and appendSlash are true', function () {
            expect(function () {
                Navigation._p._overrideDefaults({ stripSlash: true, appendSlash: true });
            }).toThrow();
        });

        it('should not override when no values provided at all', function () {
            var copy = {};
            angular.copy(Navigation.getDefaultOptions(), copy);
            Navigation._p._overrideDefaults({});
            expect(copy).toEqual(Navigation.getDefaultOptions());
        });
    });

    describe('Auxiliary, p._deconstructUrlPath', function () {
        it('should separate the url and params when both exists', function () {
            var parsed = Navigation._p._deconstructUrlPath('/example?hello=world&x=y');
            expect(parsed).toEqual({ url: '/example', params: { hello: 'world', x: 'y' }});
        });

        it('should not give me params when no query params in url', function () {
            var parsed = Navigation._p._deconstructUrlPath('/example');
            expect(parsed).toEqual({ url: '/example', params: {}});
        });
    });

    describe('Core, self.init', function () {
        it('should initialize instance variables on self when init is called', function () {
            Navigation.init();

            expect(Navigation._hasInit).toBeDefined();
            expect(Navigation._isClearing).toBeDefined();
            expect(Navigation._isRouting).toBeDefined();
            expect(Navigation._routeStack).toBeDefined();
        });

        it('should be idempotent when called init called multiple times', function () {
            Navigation.init();
            expect(Navigation._hasInit).toBe(true);

            spyOn(Navigation._p, '_overrideDefaults');
            Navigation.init();

            expect(Navigation._hasInit).toBe(true);
            expect(Navigation._p._overrideDefaults).not.toHaveBeenCalled();
        });

        it('should start listening on route changes when init is called', function () {
            inject(function ($rootScope) {
                spyOn($rootScope, '$on');
                Navigation.init();
                expect($rootScope.$on).toHaveBeenCalled();
            });
        });

        it('should not update stack when no previous route exists', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                $rootScope.$broadcast('$routeChangeSuccess', {
                    originalPath: '/test', params: {} }, undefined
                );
                expect(Navigation._routeStack.length).toBe(0);
            });
        });

        it('should update stack when previous route exists', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };

                // event, currentPath, previousPath...
                $rootScope.$broadcast('$routeChangeSuccess', pathA, undefined);
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                var pathA_ = { url: '/test-a', params: {}, label: undefined };
                expect(Navigation._routeStack[0]).toEqual(pathA_);
            });
        });

        it('should not update when isRouting=true', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                Navigation._isRouting = true;
                spyOn(Navigation, 'pushToRouteStack');

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);

                expect(Navigation.pushToRouteStack).not.toHaveBeenCalled();
            });
        });

        it('should not update when isClearing=true', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                Navigation._isClearing = true;
                spyOn(Navigation, 'pushToRouteStack');

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);

                expect(Navigation.pushToRouteStack).not.toHaveBeenCalled();
            });
        });

        it('should keep route stack empty when isClearing=true', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                // Successfully added a new "previous" route to the stack.
                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                // Clear the stack and set it to not be added in the next route.
                Navigation._routeStack.length = 0;
                Navigation._isClearing = true;
                expect(Navigation._routeStack.length).toBe(0);

                // Cause another route, expect it to remain empty.
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(0);
            });
        });

        it('should pop stack when A->B [A] then B->A, giving [A, B] instead of [A]', function () {
            inject(function ($rootScope) {
                Navigation.init();
                expect(Navigation._routeStack.length).toBe(0);

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };

                // I'm at /test-b, was at /test-a.
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                // I'm at going to /test-a was at test-b/
                $rootScope.$broadcast('$routeChangeSuccess', pathA, pathB);
                expect(Navigation._routeStack.length).toBe(1);

                var pathB_ = { url: '/test-b', params: {}, label: undefined };
                expect(Navigation._routeStack[0]).toEqual(pathB_);
            });
        });
    });

    describe('Core, self.peakRouteStack', function () {
        it('should return an empty object when stack is empty', function () {
            Navigation.init();
            expect(Navigation._routeStack.length).toBe(0);
            expect(Navigation.peakRouteStack()).toEqual({});
        });

        it('should return the most recent previous route when stack is not empty', function () {
            inject(function ($rootScope) {
                Navigation.init();

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };

                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);

                var pathA_ = {url: '/test-a', params: {}, label: undefined};
                expect(Navigation.peakRouteStack()).toEqual(pathA_);
            });
        });
    });

    describe('Core, self.isBackRouteAvailable', function () {
        it('should be true when not empty', function () {
            Navigation.init();
            Navigation._routeStack.push({url: '/test-a', params: {}, label: undefined});
            expect(Navigation.isBackRouteAvailable()).toBe(true);
        });

        it('should be false when empty', function () {
            Navigation.init();
            expect(Navigation.isBackRouteAvailable()).toBe(false);
        });
    });

    describe('Core, self.clearRouteStack', function () {
        it('should clear route stack when called', function () {
            Navigation.init();
            Navigation._routeStack.push({url: '/test-a', params: {}, label: undefined});
            Navigation.clearRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should not populate route stack with any new routes when called', function () {
            Navigation.init();
            Navigation.clearRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should set isClearing=true when called', function () {
            Navigation.init();
            Navigation.clearRouteStack();
            expect(Navigation._isClearing).toBe(true);
        });
    });

    describe('Core, self.pushToRouteStack', function () {
        it('should push to route stack', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts');

            var path = { url: '/accounts', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should not push to route stack when duplicate routes are provided', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts');
            Navigation.pushToRouteStack('/accounts');
            Navigation.pushToRouteStack('/accounts', { params: { x: 1 }});

            expect(Navigation._routeStack.length).toBe(1);
        });

        it('should label the route when the label exists', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts', { label: 'Back' });

            var path = { url: '/accounts', params: {}, label: 'Back' };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should parse query params from url when query params exist', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts?x=y&a=b&d=d');

            var path = { url: '/accounts', params: { x: 'y', a: 'b', d: 'd' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should override params when query params in url', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts?x=y', { params: { a: 'b' } });

            var path = { url: '/accounts', params: { x: 'y' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should push with options.params when params exists', function () {
            Navigation.init();
            Navigation.pushToRouteStack('/accounts/10', { params: { a: 'b'} });

            var path = { url: '/accounts/10', params: { a: 'b' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should not push when url does not exist', function () {
            Navigation.init();
            Navigation.pushToRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should not push when url does not exist', function () {
            Navigation.init();
            Navigation.pushToRouteStack();
            expect(Navigation._routeStack.length).toBe(0);
        });

        it('should add trailing slash when slash does not exist', function () {
            Navigation.init({ appendSlash: true });
            Navigation.pushToRouteStack('/accounts');

            var path = { url: '/accounts/', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should add trailing slash when slash does not exist with query params', function () {
            Navigation.init({ appendSlash: true });
            Navigation.pushToRouteStack('/accounts?x=y');

            var path = { url: '/accounts/', params: { x: 'y' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should not append slash when already exists', function () {
            Navigation.init({ appendSlash: true });
            Navigation.pushToRouteStack('/accounts/');

            var path = { url: '/accounts/', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should should strip slash when slash exists', function () {
            Navigation.init({ stripSlash: true });
            Navigation.pushToRouteStack('/accounts/');

            var path = { url: '/accounts', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should should strip slash when slash exists with query params', function () {
            Navigation.init({ stripSlash: true });
            Navigation.pushToRouteStack('/accounts/?x=y');

            var path = { url: '/accounts', params: { x: 'y' }, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });

        it('should should not strip slash when slash does not exist', function () {
            Navigation.init({ stripSlash: true });
            Navigation.pushToRouteStack('/accounts');

            var path = { url: '/accounts', params: {}, label: undefined };
            expect(Navigation._routeStack[0]).toEqual(path);
        });
    });

    describe('Core, self.routeTo', function () {
        it('should not route when isRouting=true', function () {
            Navigation.init();

            spyOn(Navigation._p, '_route');
            Navigation._isRouting = true;
            Navigation.routeTo('/accounts');
            expect(Navigation._p._route).not.toHaveBeenCalled();
        });

        it('should clear stack when clearStack=true', function () {
            Navigation.init();

            spyOn(Navigation, 'clearRouteStack');
            Navigation.routeTo('/accounts', { clearStack: true });
            expect(Navigation.clearRouteStack).toHaveBeenCalled();
        });

        it('should not clear stack when clearStack is not set', function () {
            Navigation.init();

            spyOn(Navigation, 'clearRouteStack');
            Navigation.routeTo('/accounts');
            expect(Navigation.clearRouteStack).not.toHaveBeenCalled();
        });

        it('should route when routeTo is called', function () {
            Navigation.init();

            spyOn(Navigation._p, '_route');
            Navigation.routeTo('/accounts');
            expect(Navigation._p._route).toHaveBeenCalled();
        });
    });

    describe('Core, self.back', function () {
        it('should not pop stack when stack is empty', function () {
            Navigation.init();

            spyOn(Navigation._routeStack, 'pop');
            Navigation.back();
            expect(Navigation._routeStack.pop).not.toHaveBeenCalled();
        });

        it('should use fallback stack when stack is empty', function () {
            Navigation.init();

            spyOn(Navigation._routeStack, 'pop');
            spyOn(Navigation._p, '_route');
            Navigation.back({ url: '/accounts', params: { x: 'y' } });

            expect(Navigation._routeStack.pop).not.toHaveBeenCalled();
            expect(Navigation._p._route).toHaveBeenCalled();
        });

        it('should use fallback stack when stack is empty (only url)', function () {
            Navigation.init();

            spyOn(Navigation._routeStack, 'pop');
            spyOn(Navigation._p, '_route');
            Navigation.back({ url: '/accounts' });

            expect(Navigation._routeStack.pop).not.toHaveBeenCalled();
            expect(Navigation._p._route).toHaveBeenCalledWith('/accounts', {});
        });

        it('should pop stack when going back to previous page', function () {
            inject(function ($rootScope, $window) {
                Navigation.init();

                var pathA = { originalPath: '/test-a', params: {} };
                var pathB = { originalPath: '/test-b', params: {} };
                $rootScope.$broadcast('$routeChangeSuccess', pathB, pathA);
                expect(Navigation._routeStack.length).toBe(1);

                // Stub out `$window.history.back` to avoid karma errors.
                spyOn($window.history, 'back');
                Navigation.back();
                expect(Navigation._routeStack.length).toBe(0);
            });
        });
    });
});
<|endoftext|>


<commit_before>var _bigdeal_opts = undefined;

var _bigdeal_template = '\
  \

\

\

\

\

\

\
          \
          <input type="text" class="form-control holder search suggest" do="add" placeholder="Search" style="font-size:1.6em;height:50px;border-bottom:1px solid #D82D34;">\

\
            \
            \

\

\

\

\

\

\

\
        \

\

\
          Download\

\

\

\

\

\

\
      Institution 	\
      Publisher 	\
      Collection 	\
      FTE 	\
      Carnegie 	\
      Year 	\
      USD Value 	\

\

\

\

\

\
      < previous results\

\

\
      back to top\

\

\
      next results >\

\

\

';

var bigdeal_build = function() {
  jQuery(document).ready(function() {
    var opts = _bigdeal_opts;
    var api = opts.api ? opts.api : 'https://dev.api.cottagelabs.com/service/bigdeal';

    $(opts.target).append(opts.template);
    $('body').on('click','.backtotop', function(e) {
      if (e) e.preventDefault();
      $('html,body').animate({ scrollTop: 0 }, 'fast');
    });
    $('body').on('click','.sorters', function(e) {
      if (e) e.preventDefault();
      var w = $(this).attr('href') !== '#' ? $(this).attr('href') : $(this).html().toLowerCase();
      var cs = $('.holder.sortfield').val();
      var icon = $(this).children('img').attr('src');
      var src = opts.static.replace('https:','').replace('http:','');
      src += icon.indexOf('red') === -1 ? (icon.indexOf('up') !== -1 ? 'up' : 'down') : (icon.indexOf('up') === -1 ? 'up' : 'down');
      $(this).children('img').attr('src',src + '_red_cropped.png');
      $(this).parent().siblings().children().children('img').each(function() {
        if ($(this).attr('src').indexOf('red') !== -1) $(this).attr('src',$(this).attr('src').replace('red_','grey_'));
      });
      if (cs === w) {
        $('.holder.sortdirection').val($('.holder.sortdirection').val() !== 'asc' ? 'asc' : 'desc').trigger('change');
      } else {
        $('.holder.sortdirection').val('asc');
        $('.holder.sortfield').val(w).trigger('change');
      }
    });

    var record = function(rec,idx) {
      var options = $.fn.holder.options;
      var fromclass='.from' + options.query.from;
      var rr = '';
      var iid = rec.institution.replace(/ /g,'_');
      if (rec.years) {
        rr += '

' + (rec.url ? '' + rec.institution + '' : rec.institution) + '
';
        rr += '
' + (rec.notes && rec.notes.toLowerCase().trim() !== 'not found' ? rec.notes : '') + '
';
        rr += '	' + rec.publisher + '	' + rec.collection + '	';
        rr += '' + rec.fte + '	' + rec.carnegiebasicclassification + '	' + rec.years + '	$' + rec.usdvalue + '
';
      }
      return rr;
    }

    var exporter = function(e) {
      var q = JSON.parse(JSON.stringify($('#holder').holder.options.query))
      q.size = $('#holder').holder.options.response.hits.total;
      $(this).attr('href', api + '.csv?source=' + encodeURIComponent(JSON.stringify(q)));
    }
    $('.exporter').bind('click',exporter);

    var _citv = undefined;
    var completes = function(event,th) {
      if (th.is(':checked')) {
        $('#holder').holder.options.defaultfilters = [{"query_string": {"query": "url:*"}}];
        setInterval(function() {
          if ($('a.holder:contains(\'url:*\')').length) {
            $('a.holder:contains(\'url:*\')').hide();
            clearInterval(_citv);
            _citv = undefined;
          }
        }, 100);
      } else {
        $('#holder').holder.options.defaultfilters = [];
        $('#holder').holder.options.remove(undefined, $('a.holder:contains(\'url:*\')'));
      }
      $('#holder').holder.options.execute();
    }

    var review = function(data) {
      $('.lowercontrols').show();
      var options = $('#holder').holder.options;
      if (data === undefined) data = options.response;
      var fromclass='.from' + options.query.from;
      if (options.paging) {
        if (!options.scroll) $('.' + options.class + '.result').not(fromclass).hide();
      } else {
        options.records = [];
        $('.' + options.class + '.result').remove();
      }
      var results = options.extract ? dotindex(data,options.extract) : data;
      for ( var r in results ) {
        var rec = results[r];
        if (rec.fields) rec = rec.fields;
        if (rec._source) rec = rec._source;
        for ( var f in rec ) { // is this loop worth doing by default?
          if ( rec[f] instanceof Array && rec[f].length === 1) rec[f] = rec[f][0];
          if ( rec[f] !== 0 && rec[f] !== false && !rec[f] ) rec[f] = "Not found";
        }
        options.records.push(rec);
        if (typeof options.record === 'function') {
          $('.' + options.class + '.results').append(options.record(rec,r));
        }
      }
    }

    $.fn.holder.display.sort.fields = ['institution.exact','publisher.exact','collection.exact','fte','carnegiebasicclassification.exact','years.exact','value'];
    $.fn.holder.display.sort.default = {'value': 'desc'};

    $('#holder').holder({
      completes: completes,
      review: review,
      url: api,
      datatype: 'JSON',
      pushstate: false,
      record: record,
      collapse: false,
      //sort: 'institution.exact',
      //sticky:true,
      display: ['filters','range','sort'],
      size: 100,
      facets: {
        institution: { terms: { field: "institution.exact", size: 1000, order: "term" } },
        publisher: { terms: { field: "publisher.exact", size: 1000, order: "term", exclude: [''] } },
        'Carnegie': { terms: { field: "carnegiebasicclassification.exact", size: 1000, order: "term" } },
        collection: { terms: { field: "collection.exact", size: 1000, order: "term" } }
      },
      ranges: {
        usdvalue: {
          name: 'USD Value',
          step: 100,
          min: 0,
          max: 10000000
        },
        years: {
          name: 'Years',
          step: 1,
          min: 2002,
          max: 2022
        },
        fte: {
          name: 'FTE',
          step: 10,
          min: 100,
          max: 100000
        }
      }
    });
  });
};

var _bigdeal_got = 0;
var bigdeal_get = function() {
  var headTag = document.getElementsByTagName("head")[0];
  var need = ['/holder/jquery.holder.js','/holder/display/filters.js','/holder/display/sort.js','/holder/display/range.js'];
  var jqTag = document.createElement('script');
  jqTag.type = 'text/javascript';
  jqTag.src = _bigdeal_opts.static + need[_bigdeal_got];
  if (_bigdeal_got === need.length-1) {
    jqTag.onload = bigdeal_build;
  } else {
    _bigdeal_got += 1;
    jqTag.onload = bigdeal_get;
  }
  headTag.appendChild(jqTag);
}

var bigdeal_setup = function(opts) {
  if (opts === undefined) opts = {}
  if (opts.api === undefined) opts.api = 'https://api.cottagelabs.com/service/bigdeal';
  //if (opts.site === undefined) opts.site = 'https://bigdeal.test.cottagelabs.com';
  if (opts.static === undefined) opts.static = 'https://openaccessbutton.org/static/bigdeal';
  if (opts.target === undefined) opts.target = '#bigdeal';
  if (opts.template === undefined) opts.template = _bigdeal_template;
  opts.template = opts.template.replace(/XXXstaticXXX/g,opts.static.replace('https:','').replace('http:',''));
  _bigdeal_opts = opts;

  if ($ === undefined) {
    var headTag = document.getElementsByTagName("head")[0];
    var jqTag = document.createElement('script');
    jqTag.type = 'text/javascript';
    jqTag.src = opts.static + '/jquery-1.10.2.min.js';
    jqTag.onload = bigdeal_get;
    headTag.appendChild(jqTag);
  } else {
     bigdeal_get();
  }
}
<commit_msg>chrome insecure scripts change<commit_after>var _bigdeal_opts = undefined;

var _bigdeal_template = '\
  \

\

\

\

\

\

\
          \
          <input type="text" class="form-control holder search suggest" do="add" placeholder="Search" style="font-size:1.6em;height:50px;border-bottom:1px solid #D82D34;">\

\
            \
            \

\

\

\

\

\

\

\
        \

\

\
          Download\

\

\

\

\

\

\
      Institution 	\
      Publisher 	\
      Collection 	\
      FTE 	\
      Carnegie 	\
      Year 	\
      USD Value 	\

\

\

\

\

\
      < previous results\

\

\
      back to top\

\

\
      next results >\

\

\

';

var bigdeal_build = function() {
  jQuery(document).ready(function() {
    var opts = _bigdeal_opts;
    var api = opts.api ? opts.api : 'https://dev.api.cottagelabs.com/service/bigdeal';

    $(opts.target).append(opts.template);
    $('body').on('click','.backtotop', function(e) {
      if (e) e.preventDefault();
      $('html,body').animate({ scrollTop: 0 }, 'fast');
    });
    $('body').on('click','.sorters', function(e) {
      if (e) e.preventDefault();
      var w = $(this).attr('href') !== '#' ? $(this).attr('href') : $(this).html().toLowerCase();
      var cs = $('.holder.sortfield').val();
      var icon = $(this).children('img').attr('src');
      var src = opts.static.replace('https:','').replace('http:','');
      src += icon.indexOf('red') === -1 ? (icon.indexOf('up') !== -1 ? 'up' : 'down') : (icon.indexOf('up') === -1 ? 'up' : 'down');
      $(this).children('img').attr('src',src + '_red_cropped.png');
      $(this).parent().siblings().children().children('img').each(function() {
        if ($(this).attr('src').indexOf('red') !== -1) $(this).attr('src',$(this).attr('src').replace('red_','grey_'));
      });
      if (cs === w) {
        $('.holder.sortdirection').val($('.holder.sortdirection').val() !== 'asc' ? 'asc' : 'desc').trigger('change');
      } else {
        $('.holder.sortdirection').val('asc');
        $('.holder.sortfield').val(w).trigger('change');
      }
    });

    var record = function(rec,idx) {
      var options = $.fn.holder.options;
      var fromclass='.from' + options.query.from;
      var rr = '';
      var iid = rec.institution.replace(/ /g,'_');
      if (rec.years) {
        rr += '

' + (rec.url ? '' + rec.institution + '' : rec.institution) + '
';
        rr += '
' + (rec.notes && rec.notes.toLowerCase().trim() !== 'not found' ? rec.notes : '') + '
';
        rr += '	' + rec.publisher + '	' + rec.collection + '	';
        rr += '' + rec.fte + '	' + rec.carnegiebasicclassification + '	' + rec.years + '	$' + rec.usdvalue + '
';
      }
      return rr;
    }

    var exporter = function(e) {
      var q = JSON.parse(JSON.stringify($('#holder').holder.options.query))
      q.size = $('#holder').holder.options.response.hits.total;
      $(this).attr('href', api + '.csv?source=' + encodeURIComponent(JSON.stringify(q)));
    }
    $('.exporter').bind('click',exporter);

    var _citv = undefined;
    var completes = function(event,th) {
      if (th.is(':checked')) {
        $('#holder').holder.options.defaultfilters = [{"query_string": {"query": "url:*"}}];
        setInterval(function() {
          if ($('a.holder:contains(\'url:*\')').length) {
            $('a.holder:contains(\'url:*\')').hide();
            clearInterval(_citv);
            _citv = undefined;
          }
        }, 100);
      } else {
        $('#holder').holder.options.defaultfilters = [];
        $('#holder').holder.options.remove(undefined, $('a.holder:contains(\'url:*\')'));
      }
      $('#holder').holder.options.execute();
    }

    var review = function(data) {
      $('.lowercontrols').show();
      var options = $('#holder').holder.options;
      if (data === undefined) data = options.response;
      var fromclass='.from' + options.query.from;
      if (options.paging) {
        if (!options.scroll) $('.' + options.class + '.result').not(fromclass).hide();
      } else {
        options.records = [];
        $('.' + options.class + '.result').remove();
      }
      var results = options.extract ? dotindex(data,options.extract) : data;
      for ( var r in results ) {
        var rec = results[r];
        if (rec.fields) rec = rec.fields;
        if (rec._source) rec = rec._source;
        for ( var f in rec ) { // is this loop worth doing by default?
          if ( rec[f] instanceof Array && rec[f].length === 1) rec[f] = rec[f][0];
          if ( rec[f] !== 0 && rec[f] !== false && !rec[f] ) rec[f] = "Not found";
        }
        options.records.push(rec);
        if (typeof options.record === 'function') {
          $('.' + options.class + '.results').append(options.record(rec,r));
        }
      }
    }

    $.fn.holder.display.sort.fields = ['institution.exact','publisher.exact','collection.exact','fte','carnegiebasicclassification.exact','years.exact','value'];
    $.fn.holder.display.sort.default = {'value': 'desc'};
    $.fn.holder.display.range.url = 'https://openaccessbutton.org/static/bigdeal/'

    $('#holder').holder({
      completes: completes,
      review: review,
      url: api,
      datatype: 'JSON',
      pushstate: false,
      record: record,
      collapse: false,
      //sort: 'institution.exact',
      //sticky:true,
      display: ['filters','range','sort'],
      size: 100,
      facets: {
        institution: { terms: { field: "institution.exact", size: 1000, order: "term" } },
        publisher: { terms: { field: "publisher.exact", size: 1000, order: "term", exclude: [''] } },
        'Carnegie': { terms: { field: "carnegiebasicclassification.exact", size: 1000, order: "term" } },
        collection: { terms: { field: "collection.exact", size: 1000, order: "term" } }
      },
      ranges: {
        usdvalue: {
          name: 'USD Value',
          step: 100,
          min: 0,
          max: 10000000
        },
        years: {
          name: 'Years',
          step: 1,
          min: 2002,
          max: 2022
        },
        fte: {
          name: 'FTE',
          step: 10,
          min: 100,
          max: 100000
        }
      }
    });
  });
};

var _bigdeal_got = 0;
var bigdeal_get = function() {
  var headTag = document.getElementsByTagName("head")[0];
  var need = ['/holder/jquery.holder.js','/holder/display/filters.js','/holder/display/sort.js','/holder/display/range.js'];
  var jqTag = document.createElement('script');
  jqTag.type = 'text/javascript';
  jqTag.src = _bigdeal_opts.static + need[_bigdeal_got];
  if (_bigdeal_got === need.length-1) {
    jqTag.onload = bigdeal_build;
  } else {
    _bigdeal_got += 1;
    jqTag.onload = bigdeal_get;
  }
  headTag.appendChild(jqTag);
}

var bigdeal_setup = function(opts) {
  if (opts === undefined) opts = {}
  if (opts.api === undefined) opts.api = 'https://api.cottagelabs.com/service/bigdeal';
  //if (opts.site === undefined) opts.site = 'https://bigdeal.test.cottagelabs.com';
  if (opts.static === undefined) opts.static = 'https://openaccessbutton.org/static/bigdeal';
  if (opts.target === undefined) opts.target = '#bigdeal';
  if (opts.template === undefined) opts.template = _bigdeal_template;
  opts.template = opts.template.replace(/XXXstaticXXX/g,opts.static.replace('https:','').replace('http:',''));
  _bigdeal_opts = opts;

  if ($ === undefined) {
    var headTag = document.getElementsByTagName("head")[0];
    var jqTag = document.createElement('script');
    jqTag.type = 'text/javascript';
    jqTag.src = opts.static + '/jquery-1.10.2.min.js';
    jqTag.onload = bigdeal_get;
    headTag.appendChild(jqTag);
  } else {
     bigdeal_get();
  }
}
<|endoftext|>


<commit_before>var maxlen = 10;
var socket = null;
var outputf = null;
var inputf = null;
var mudReaderBusy = false;
var mudReader = new FileReader();
var inQ = []; // binary blobs incoming from socket, waiting to be processed
var outS = []; // line-split view of screen, bounded by vertical size
var ansi_up = new AnsiUp;

function capOutput() {
    outS = outS.slice(Math.max(0, outS.length - maxlen));
}

mudReader.addEventListener("loadend", function() {
    var processed = mudReader.result;
    processed = Telnet.parse(processed);
    if (processed) { // just GMCP?
        processed = processed.replace(/\r/g, "");
        processed = ansi_up.ansi_to_html(processed);
        processed = processed.trim();
        var split = processed.split(/\n/);
        split.forEach(function(line){outS.push(line);});
        capOutput();
    }
    if (inQ.length > 0) {
        mudReader.readAsBinaryString(inQ.shift());
    } else {
        mudReaderBusy = false;
        window.setTimeout(scroll, 1); // release the mudReader faster, but still scroll on event
    }
});

function flushQ() {
    if (!mudReaderBusy) {
        mudReaderBusy = true;
        mudReader.readAsBinaryString(inQ.shift());
    }
}

function sendRaw(stuff) {
    var b = new Blob([stuff], {type: 'application/octet-stream'});
    socket.send(b);
}

function send(text) {
    if (text[0] == ';')
        text = text.slice(1);
    else
        text = text.replace(/;/g, "\n");
    sendRaw(text + "\n");
    text.split(/\n/).forEach(function(line) {
        outS.push('⇨' + line);
    });
    capOutput();
    scroll();
    inputf.focus();
}

function scroll() {
    outputf.innerHTML = outS.join('\n');
    // Only scroll if the user isn't reading backlog
    if (inputf === document.activeElement)
        outputf.scrollTop = 1E20;
}

function startSocket() {
    inputf = document.getElementById('inputfield');
    outputf = document.getElementById('output');
    socket = new WebSocket('ws://' + window.location.hostname + ':7901', ['binary']);
    socket.addEventListener('message', function (event) {
        inQ.push(event.data);
        flushQ();
    });
    socket.onerror=function (e) {
        outputf.innerHTML += "\n\n\nWebSocket Error: " + e.reason;
        scroll();
    }
    socket.onclose=function(e){
        outputf.innerHTML += "\n\n\nWebSocket Close: " + e.reason;
        scroll();
    }

    function oninput(event) {
        if (event.keyCode == 13) {
            send(inputf.value);
            inputf.select();
        }
    }
    inputf.onkeypress = function() {return oninput(event);};

    inputf.select();
}

function addGmcpHandlers() {
    /*
    Telnet.handle("room.info", function() {
        console.log("In room " + Telnet.gmcp()['room']['info']['num']);
    });
    */
}

function rnum() {
    return Telnet.gmcp()['room']['info']['num'];
}

function start() {
    startSocket();
    addGmcpHandlers();
    document.getElementById('pInput').onclick = function() { document.getElementById('pInput').select();};
    document.getElementById('pInput').oninput = function() { findRoom('pInput', 'pList');};
    winHeight = parseInt(document.defaultView.getComputedStyle(outputf, null)['height'].replace("px", ""));
    lineHeight = parseInt(document.defaultView.getComputedStyle(outputf, null)['line-height'].replace("px", ""));
    var page = Math.floor(winHeight / lineHeight) + 1;
    maxlen = page * 10;
}
<commit_msg>Fixed keypresses on Firefox<commit_after>var maxlen = 10;
var socket = null;
var outputf = null;
var inputf = null;
var mudReaderBusy = false;
var mudReader = new FileReader();
var inQ = []; // binary blobs incoming from socket, waiting to be processed
var outS = []; // line-split view of screen, bounded by vertical size
var ansi_up = new AnsiUp;

function capOutput() {
    outS = outS.slice(Math.max(0, outS.length - maxlen));
}

mudReader.addEventListener("loadend", function() {
    var processed = mudReader.result;
    processed = Telnet.parse(processed);
    if (processed) { // just GMCP?
        processed = processed.replace(/\r/g, "");
        processed = ansi_up.ansi_to_html(processed);
        processed = processed.trim();
        var split = processed.split(/\n/);
        split.forEach(function(line){outS.push(line);});
        capOutput();
    }
    if (inQ.length > 0) {
        mudReader.readAsBinaryString(inQ.shift());
    } else {
        mudReaderBusy = false;
        window.setTimeout(scroll, 1); // release the mudReader faster, but still scroll on event
    }
});

function flushQ() {
    if (!mudReaderBusy) {
        mudReaderBusy = true;
        mudReader.readAsBinaryString(inQ.shift());
    }
}

function sendRaw(stuff) {
    var b = new Blob([stuff], {type: 'application/octet-stream'});
    socket.send(b);
}

function send(text) {
    if (text[0] == ';')
        text = text.slice(1);
    else
        text = text.replace(/;/g, "\n");
    sendRaw(text + "\n");
    text.split(/\n/).forEach(function(line) {
        outS.push('⇨' + line);
    });
    capOutput();
    scroll();
    inputf.focus();
}

function scroll() {
    outputf.innerHTML = outS.join('\n');
    // Only scroll if the user isn't reading backlog
    if (inputf === document.activeElement)
        outputf.scrollTop = 1E20;
}

function startSocket() {
    inputf = document.getElementById('inputfield');
    outputf = document.getElementById('output');
    socket = new WebSocket('ws://' + window.location.hostname + ':7901', ['binary']);
    socket.addEventListener('message', function (event) {
        inQ.push(event.data);
        flushQ();
    });
    socket.onerror=function (e) {
        outputf.innerHTML += "\n\n\nWebSocket Error: " + e.reason;
        scroll();
    }
    socket.onclose=function(e){
        outputf.innerHTML += "\n\n\nWebSocket Close: " + e.reason;
        scroll();
    }

    function oninput(event) {
        if (event.keyCode == 13) {
            send(inputf.value);
            inputf.select();
        }
    }
    inputf.onkeypress = function(event) {return oninput(event);};

    inputf.select();
}

function addGmcpHandlers() {
    /*
    Telnet.handle("room.info", function() {
        console.log("In room " + Telnet.gmcp()['room']['info']['num']);
    });
    */
}

function rnum() {
    return Telnet.gmcp()['room']['info']['num'];
}

function start() {
    startSocket();
    addGmcpHandlers();
    document.getElementById('pInput').onclick = function() { document.getElementById('pInput').select();};
    document.getElementById('pInput').oninput = function() { findRoom('pInput', 'pList');};
    winHeight = parseInt(document.defaultView.getComputedStyle(outputf, null)['height'].replace("px", ""));
    lineHeight = parseInt(document.defaultView.getComputedStyle(outputf, null)['line-height'].replace("px", ""));
    var page = Math.floor(winHeight / lineHeight) + 1;
    maxlen = page * 10;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Javascript preamble, that lets the output of dart2js run on JSShell.

(function(self) {
  // Using strict mode to avoid accidentally defining global variables.
  "use strict"; // Should be first statement of this function.

  // Location (Uri.base)

  var workingDirectory = environment["PWD"];

  // Global properties. "self" refers to the global object, so adding a
  // property to "self" defines a global variable.
  self.self = self;

  self.location = { href: "file://" + workingDirectory + "/" };

  // Support for deferred loading.
  self.dartDeferredLibraryLoader = function(uri, successCallback, errorCallback) {
    try {
      load(uri);
      successCallback();
    } catch (error) {
      errorCallback(error);
    }
  };
})(this)

var getKeys = function(obj){
   var keys = [];
   for(var key in obj){
      keys.push(key);
   }
   return keys;
}
<commit_msg>Use os.getenv instead of environment in jsshell preamble.<commit_after>// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Javascript preamble, that lets the output of dart2js run on JSShell.

(function(self) {
  // Using strict mode to avoid accidentally defining global variables.
  "use strict"; // Should be first statement of this function.

  // Location (Uri.base)

  var workingDirectory = os.getenv("PWD");

  // Global properties. "self" refers to the global object, so adding a
  // property to "self" defines a global variable.
  self.self = self;

  self.location = { href: "file://" + workingDirectory + "/" };

  // Support for deferred loading.
  self.dartDeferredLibraryLoader = function(uri, successCallback, errorCallback) {
    try {
      load(uri);
      successCallback();
    } catch (error) {
      errorCallback(error);
    }
  };
})(this)

var getKeys = function(obj){
   var keys = [];
   for(var key in obj){
      keys.push(key);
   }
   return keys;
}
<|endoftext|>


<commit_before>/*jshint node:true*/

var SilentError = require('silent-error');
var fs          = require('fs-extra');
var path        = require('path');
var EmberRouterGenerator = require('ember-router-generator');

module.exports = {
  description: 'Generates a route and registers it with the router.',

  availableOptions: [
    {
      name: 'path',
      type: String,
      default: ''
    }
  ],

  fileMapTokens: function() {
    return {
      __templatepath__: function(options) {
        if (options.pod) {
          return path.join(options.podPath, options.dasherizedModuleName);
        }
        return 'templates';
      },
      __templatename__: function(options) {
        if (options.pod) {
          return 'template';
        }
        return options.dasherizedModuleName;
      },
      __root__: function(options) {
        if (options.inRepoAddon) {
          return path.join('lib', options.inRepoAddon, 'addon');
        }

        if (options.inDummy) {
          return path.join('tests','dummy','app');
        }

        if (options.inAddon) {
          return 'addon';
        }

        return 'app';
      }
    };
  },

  shouldTouchRouter: function(name) {
    var isIndex = name === 'index';
    var isBasic = name === 'basic';
    var isApplication = name === 'application';

    return !isBasic && !isIndex && !isApplication;
  },

  afterInstall: function(options) {
    var entity  = options.entity;

    if (this.shouldTouchRouter(entity.name) && !options.dryRun && !options.project.isEmberCLIAddon() && !options.inRepoAddon) {
      addRouteToRouter(entity.name, {
        root: options.project.root,
        path: options.path
      });
    }
  },

  afterUninstall: function(options) {
    var entity  = options.entity;

    if (this.shouldTouchRouter(entity.name) && !options.dryRun && !options.project.isEmberCLIAddon() && !options.inRepoAddon) {
      removeRouteFromRouter(entity.name, {
        root: options.project.root
      });
    }
  }
};

function removeRouteFromRouter(name, options) {
  var routerPath = path.join(options.root, 'app', 'router.js');
  var source = fs.readFileSync(routerPath, 'utf-8');

  var routes = new EmberRouterGenerator(source);
  var newRoutes = routes.remove(name);

  fs.writeFileSync(routerPath, newRoutes.code());
}

function addRouteToRouter(name, options) {
  var routerPath = path.join(options.root, 'app', 'router.js');
  var source = fs.readFileSync(routerPath, 'utf-8');

  var routes = new EmberRouterGenerator(source);
  var newRoutes = routes.add(name, options);

  fs.writeFileSync(routerPath, newRoutes.code());
}
<commit_msg>print notification when modifying router.js<commit_after>/*jshint node:true*/

var SilentError = require('silent-error');
var fs          = require('fs-extra');
var path        = require('path');
var chalk       = require('chalk');
var EmberRouterGenerator = require('ember-router-generator');

module.exports = {
  description: 'Generates a route and registers it with the router.',

  availableOptions: [
    {
      name: 'path',
      type: String,
      default: ''
    }
  ],

  fileMapTokens: function() {
    return {
      __templatepath__: function(options) {
        if (options.pod) {
          return path.join(options.podPath, options.dasherizedModuleName);
        }
        return 'templates';
      },
      __templatename__: function(options) {
        if (options.pod) {
          return 'template';
        }
        return options.dasherizedModuleName;
      },
      __root__: function(options) {
        if (options.inRepoAddon) {
          return path.join('lib', options.inRepoAddon, 'addon');
        }

        if (options.inDummy) {
          return path.join('tests','dummy','app');
        }

        if (options.inAddon) {
          return 'addon';
        }

        return 'app';
      }
    };
  },

  shouldTouchRouter: function(name) {
    var isIndex = name === 'index';
    var isBasic = name === 'basic';
    var isApplication = name === 'application';

    return !isBasic && !isIndex && !isApplication;
  },

  afterInstall: function(options) {
    var entity  = options.entity;

    if (this.shouldTouchRouter(entity.name) && !options.dryRun && !options.project.isEmberCLIAddon() && !options.inRepoAddon) {
      addRouteToRouter(entity.name, {
        root: options.project.root,
        path: options.path
      });

      this._writeStatusToUI(chalk.green, 'add route', entity.name);
    }
  },

  afterUninstall: function(options) {
    var entity  = options.entity;

    if (this.shouldTouchRouter(entity.name) && !options.dryRun && !options.project.isEmberCLIAddon() && !options.inRepoAddon) {
      removeRouteFromRouter(entity.name, {
        root: options.project.root
      });

      this._writeStatusToUI(chalk.red, 'remove route', entity.name);
    }
  }
};

function removeRouteFromRouter(name, options) {
  var routerPath = path.join(options.root, 'app', 'router.js');
  var source = fs.readFileSync(routerPath, 'utf-8');

  var routes = new EmberRouterGenerator(source);
  var newRoutes = routes.remove(name);

  fs.writeFileSync(routerPath, newRoutes.code());
}

function addRouteToRouter(name, options) {
  var routerPath = path.join(options.root, 'app', 'router.js');
  var source = fs.readFileSync(routerPath, 'utf-8');

  var routes = new EmberRouterGenerator(source);
  var newRoutes = routes.add(name, options);

  fs.writeFileSync(routerPath, newRoutes.code());
}
<|endoftext|>


<commit_before>// REACT COMPONENTS
import React from 'react';
import { Form } from 'semantic-ui-react';

// PROJECT COMPONENTS
import { FormPartsContainer, IntervalColumnHeadings, CashFlowRow } from './formHelpers';

// COMPONENT HELPER FUNCTIONS
import { getTimeSetter } from '../utils/getTimeSetter';

/**
* @todo Figure out which programs need to know which types of incomes
* and categorize/tag them accordingly.
*
* @todo Calc and store `client.currentUnearnedIncomeMonthly`. I think
* we do still have to keep the other specific income soruces separate
* as they're possibly used in other calculations.
*/

// ========================================
// COMPONENTS
// ========================================
/**
* @todo Is it possible for id's to be the same as the text in the label?
* @todo Stuff like interest of bank accounts? (unearned income?)
* @todo Other assets (not counted in gross income? income categories?)
* @todo Add note: "Household income (a before tax income, and does not include
* funds such as income from children under 18 years old, amounts received
* through training programs funded by HUD, and the income of a live-in aide)"
* (@see {@link http://www.masslegalhelp.org/housing/financial-eligibility})
* @todo Relevant? "State housing programs base eligibility on net yearly income.
* Net yearly income does not include funds such as wages earned by full-time
* students, worker's compensation, and a certain amount of wages earned by a
* tenant 62 or older. It also allows you to deduct certain amounts, such as
* necessary medical expenses and personal care services." (@see {@link
* http://www.masslegalhelp.org/housing/financial-eligibility})
*/

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
const IncomeForm = function ({ current, time, setClientProperty }) {

  var type = 'income';

  /** Makes sure values are propagated to 'future' properties if needed */
  var ensureFuture = function (evnt, inputProps) {
    setClientProperty(evnt, { ...inputProps, fillFuture: true });
  };  // End ensureFuture()

  var sharedProps = {
    timeState:         current,
    time:              time,
    type:              type,
    setClientProperty: ensureFuture,
  };

  return (

      <IntervalColumnHeadings type={ type } />

      {/* All kinds of things need to be explained. */}
      {/* @todo Change 'labelInfo' to visible blurb at top */}
  	  <CashFlowRow
        { ...sharedProps }
        generic='earned'
        labelInfo='(Weekly income = hourly wage times average number of work hours per week)'>
          Earned income
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='TAFDC'> TAFDC
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='SSI'> SSI
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='SSDI'> SSDI
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='childSupportIn'> Child support received
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='unemployment'> Unemployment
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='workersComp'> Worker’s comp
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='pension'> Pension
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='socialSecurity'> Social security
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='alimony'> Alimony
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='otherIncome'> Other income
      </CashFlowRow>
      <Form.Field>This prototype will attempt to make its own calculations for SNAP amount</Form.Field>

  );  // end return

};  // End IncomeForm()

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
// `props` is a cloned version of the original props. References broken.
const CurrentIncomeStep = function (props) {

  const setTimeProp = getTimeSetter('current', props.changeClient);

  /** @todo Are these titles accurate now? */
  return (
    <Form className = 'income-form flex-item flex-column'>
      <FormPartsContainer
        title     = 'Current Household Income'
        clarifier = 'Income that you collected in the past 12 months.'
        left      = {{ name: 'Previous', func: props.previousStep }}
        right     = {{ name: 'Next', func: props.nextStep }}>
        <IncomeForm
          setClientProperty={ setTimeProp }
          current={ props.client.current }
          time={ 'current' } />
      </FormPartsContainer>
    </Form>
  );

};  // End CurrentIncomeStep()

export { CurrentIncomeStep };
<commit_msg>Makes changes for lint msgs issue #507 - CurrentIncome.js<commit_after>// REACT COMPONENTS
import React from 'react';
import { Form } from 'semantic-ui-react';

// PROJECT COMPONENTS
import { FormPartsContainer, IntervalColumnHeadings, CashFlowRow } from './formHelpers';

// COMPONENT HELPER FUNCTIONS
import { getTimeSetter } from '../utils/getTimeSetter';

/**
* @todo Figure out which programs need to know which types of incomes
* and categorize/tag them accordingly.
*
* @todo Calc and store `client.currentUnearnedIncomeMonthly`. I think
* we do still have to keep the other specific income soruces separate
* as they're possibly used in other calculations.
*/

// ========================================
// COMPONENTS
// ========================================
/**
* @todo Is it possible for id's to be the same as the text in the label?
* @todo Stuff like interest of bank accounts? (unearned income?)
* @todo Other assets (not counted in gross income? income categories?)
* @todo Add note: "Household income (a before tax income, and does not include
* funds such as income from children under 18 years old, amounts received
* through training programs funded by HUD, and the income of a live-in aide)"
* (@see {@link http://www.masslegalhelp.org/housing/financial-eligibility})
* @todo Relevant? "State housing programs base eligibility on net yearly income.
* Net yearly income does not include funds such as wages earned by full-time
* students, worker's compensation, and a certain amount of wages earned by a
* tenant 62 or older. It also allows you to deduct certain amounts, such as
* necessary medical expenses and personal care services." (@see {@link
* http://www.masslegalhelp.org/housing/financial-eligibility})
*/

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
const IncomeForm = function ({ current, time, setClientProperty }) {

  var type = 'income';

  /** Makes sure values are propagated to 'future' properties if needed */
  var ensureFuture = function (evnt, inputProps) {
    setClientProperty(evnt, { ...inputProps, fillFuture: true });
  };  // End ensureFuture()

  var sharedProps = {
    timeState:         current,
    time:              time,
    type:              type,
    setClientProperty: ensureFuture,
  };

  return (

      <IntervalColumnHeadings type={ type } />

      {/* All kinds of things need to be explained. */}
      {/* @todo Change 'labelInfo' to visible blurb at top */}
      <CashFlowRow
        { ...sharedProps }
        generic='earned'
        labelInfo='(Weekly income = hourly wage times average number of work hours per week)'>
          Earned income
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='TAFDC'> TAFDC
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='SSI'> SSI
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='SSDI'> SSDI
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='childSupportIn'> Child support received
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='unemployment'> Unemployment
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='workersComp'> Worker’s comp
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='pension'> Pension
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='socialSecurity'> Social security
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='alimony'> Alimony
      </CashFlowRow>
      <CashFlowRow
        { ...sharedProps }
        generic='otherIncome'> Other income
      </CashFlowRow>
      <Form.Field>This prototype will attempt to make its own calculations for SNAP amount</Form.Field>

  );  // end return

};  // End IncomeForm()

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
// `props` is a cloned version of the original props. References broken.
const CurrentIncomeStep = function (props) {

  const setTimeProp = getTimeSetter('current', props.changeClient);

  /** @todo Are these titles accurate now? */
  return (
    <Form className = 'income-form flex-item flex-column'>
      <FormPartsContainer
        title     = 'Current Household Income'
        clarifier = 'Income that you collected in the past 12 months.'
        left      = {{ name: 'Previous', func: props.previousStep }}
        right     = {{ name: 'Next', func: props.nextStep }}>
        <IncomeForm
          setClientProperty={ setTimeProp }
          current={ props.client.current }
          time={ 'current' } />
      </FormPartsContainer>
    </Form>
  );

};  // End CurrentIncomeStep()

export { CurrentIncomeStep };
<|endoftext|>


<commit_before>/*jslint browser: true, undef: true *//*global Ext*/
Ext.define('SlateAdmin.controller.Progress', {
    extend: 'Ext.app.Controller',

//    requires: [
//        'SlateAdmin.proxy.Records'
//    ],
    // controller config
    views: [
        'progress.NavPanel'
    ],

    routes: {
        'progress': 'showProgress'
    },

    refs: [{
        ref: 'navPanel',
        selector: 'progress-navpanel',
        autoCreate: true,

        xtype: 'progress-navpanel'
    }],

    // controller template methods
    init: function() {
        var me = this;

        me.control({
            'progress-navpanel': {
                expand: me.onNavPanelExpand
            }
        });
    },

    buildNavPanel: function() {
        return this.getNavPanel();
    },

    // route handlers
    showProgress: function() {
        var me = this,
            navPanel = me.getNavPanel();

        navPanel.setActiveLink(null);
        navPanel.expand();
    },

    // event handlers
    onNavPanelExpand: function(navPanel) {
        Ext.util.History.pushState('progress', 'Student Progress');
    },

    // controller methods
    syncState: function() {
        var path = ['progress'],
            title = 'Progress',
            activeLink = this.getNavPanel().getActiveLink();
        console.log('syncState, activeLink = ', activeLink);
        Ext.util.History.pushState(path, title);
    }
});<commit_msg>Suppress SBG navigation section until feature is mature<commit_after>/*jslint browser: true, undef: true *//*global Ext*/
Ext.define('SlateAdmin.controller.Progress', {
    extend: 'Ext.app.Controller',

//    requires: [
//        'SlateAdmin.proxy.Records'
//    ],
    // controller config
    views: [
        'progress.NavPanel'
    ],

    routes: {
        'progress': 'showProgress'
    },

    refs: [{
        ref: 'navPanel',
        selector: 'progress-navpanel',
        autoCreate: true,

        xtype: 'progress-navpanel'
    }],

    // controller template methods
    init: function() {
        var me = this;

        me.control({
            'progress-navpanel': {
                expand: me.onNavPanelExpand
            }
        });
    },

    buildNavPanel: function() {
        return location.search.match(/\Wenablesbg(\W|$)/) && this.getNavPanel();
    },

    // route handlers
    showProgress: function() {
        var me = this,
            navPanel = me.getNavPanel();

        navPanel.setActiveLink(null);
        navPanel.expand();
    },

    // event handlers
    onNavPanelExpand: function(navPanel) {
        Ext.util.History.pushState('progress', 'Student Progress');
    },

    // controller methods
    syncState: function() {
        var path = ['progress'],
            title = 'Progress',
            activeLink = this.getNavPanel().getActiveLink();
        console.log('syncState, activeLink = ', activeLink);
        Ext.util.History.pushState(path, title);
    }
});<|endoftext|>


<commit_before>// REACT COMPONENTS
import React from 'react';
import { Form, Divider } from 'semantic-ui-react';

// PROJECT COMPONENTS
import { FormPartsContainer, IntervalColumnHeadings, CashFlowRow } from './formHelpers';

// COMPONENT HELPER FUNCTIONS
import { getTimeSetter } from '../utils/getTimeSetter';

/**
* @todo Figure out which programs need to know which types of incomes
* and categorize/tag them accordingly.
*
* @todo Calc and store `client.currentUnearnedIncomeMonthly`. I think
* we do still have to keep the other specific income soruces separate
* as they're possibly used in other calculations.
*/

// ========================================
// COMPONENTS
// ========================================
/**
* @todo Is it possible for id's to be the same as the text in the label?
* @todo Stuff like interest of bank accounts? (unearned income?)
* @todo Other assets (not counted in gross income? income categories?)
* @todo Add note: "Household income (a before tax income, and does not include
* funds such as income from children under 18 years old, amounts received
* through training programs funded by HUD, and the income of a live-in aide)"
* (@see {@link http://www.masslegalhelp.org/housing/financial-eligibility})
* @todo Relevant? "State housing programs base eligibility on net yearly income.
* Net yearly income does not include funds such as wages earned by full-time
* students, worker's compensation, and a certain amount of wages earned by a
* tenant 62 or older. It also allows you to deduct certain amounts, such as
* necessary medical expenses and personal care services." (@see {@link
* http://www.masslegalhelp.org/housing/financial-eligibility})
*/

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
const IncomeForm = function ({ current, time, setClientProperty }) {

  var type = 'income';

  /** Makes sure values are propagated to 'future' properties if needed */
  var ensureFuture = function ( evnt, inputProps ) {
     setClientProperty( evnt, {...inputProps, fillFuture: true });
  };  // End ensureFuture()

  var sharedProps = {
    timeState: current,
    time: time,
    type: type,
    setClientProperty: ensureFuture
  };

  return (

      <IntervalColumnHeadings type={type}/>

      {/* All kinds of things need to be explained. */}
      {/* @todo Change 'labelInfo' to visible blurb at top */}
  	  <CashFlowRow  {...sharedProps} generic='earned' labelInfo='(Weekly income = hourly wage times average number of work hours per week)'>
          Earned income
		  </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='TAFDC'> TAFDC </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='SSI'> SSI </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='SSDI'> SSDI </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='childSupportIn'> Child support received </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='unemployment'> Unemployment </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='workersComp'> Worker’s comp </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='pension'> Pension </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='socialSecurity'> Social security </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='alimony'> Alimony </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='otherIncome'> Other income </CashFlowRow>

  );  // end return

};  // End IncomeForm()

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
// `props` is a cloned version of the original props. References broken.
const CurrentIncomeStep = function ( props ) {

  const setTimeProp = getTimeSetter( 'current', props.changeClient );

  /** @todo Are these titles accurate now? */
  return (
    <Form className = 'income-form'>
      <FormPartsContainer
        title     = 'Current Household Income'
        clarifier = 'Income that you collected in the past 12 months.'
        left      = {{name: 'Previous', func: props.previousStep}}
        right     = {{name: 'Next', func: props.nextStep}}>
          <IncomeForm setClientProperty={setTimeProp} current={props.client.current} time={'current'} />
      </FormPartsContainer>
    </Form>
  );

};  // End CurrentIncomeStep()

export { CurrentIncomeStep };
<commit_msg>Removes unused var<commit_after>// REACT COMPONENTS
import React from 'react';
import { Form } from 'semantic-ui-react';

// PROJECT COMPONENTS
import { FormPartsContainer, IntervalColumnHeadings, CashFlowRow } from './formHelpers';

// COMPONENT HELPER FUNCTIONS
import { getTimeSetter } from '../utils/getTimeSetter';

/**
* @todo Figure out which programs need to know which types of incomes
* and categorize/tag them accordingly.
*
* @todo Calc and store `client.currentUnearnedIncomeMonthly`. I think
* we do still have to keep the other specific income soruces separate
* as they're possibly used in other calculations.
*/

// ========================================
// COMPONENTS
// ========================================
/**
* @todo Is it possible for id's to be the same as the text in the label?
* @todo Stuff like interest of bank accounts? (unearned income?)
* @todo Other assets (not counted in gross income? income categories?)
* @todo Add note: "Household income (a before tax income, and does not include
* funds such as income from children under 18 years old, amounts received
* through training programs funded by HUD, and the income of a live-in aide)"
* (@see {@link http://www.masslegalhelp.org/housing/financial-eligibility})
* @todo Relevant? "State housing programs base eligibility on net yearly income.
* Net yearly income does not include funds such as wages earned by full-time
* students, worker's compensation, and a certain amount of wages earned by a
* tenant 62 or older. It also allows you to deduct certain amounts, such as
* necessary medical expenses and personal care services." (@see {@link
* http://www.masslegalhelp.org/housing/financial-eligibility})
*/

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
const IncomeForm = function ({ current, time, setClientProperty }) {

  var type = 'income';

  /** Makes sure values are propagated to 'future' properties if needed */
  var ensureFuture = function ( evnt, inputProps ) {
     setClientProperty( evnt, {...inputProps, fillFuture: true });
  };  // End ensureFuture()

  var sharedProps = {
    timeState: current,
    time: time,
    type: type,
    setClientProperty: ensureFuture
  };

  return (

      <IntervalColumnHeadings type={type}/>

      {/* All kinds of things need to be explained. */}
      {/* @todo Change 'labelInfo' to visible blurb at top */}
  	  <CashFlowRow  {...sharedProps} generic='earned' labelInfo='(Weekly income = hourly wage times average number of work hours per week)'>
          Earned income
		  </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='TAFDC'> TAFDC </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='SSI'> SSI </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='SSDI'> SSDI </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='childSupportIn'> Child support received </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='unemployment'> Unemployment </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='workersComp'> Worker’s comp </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='pension'> Pension </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='socialSecurity'> Social security </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='alimony'> Alimony </CashFlowRow>
      <CashFlowRow {...sharedProps} generic='otherIncome'> Other income </CashFlowRow>

  );  // end return

};  // End IncomeForm()

/** @todo description
*
* @function
* @param {object} props
* @property {object} props.__ - explanation
*
* @returns Component
*/
// `props` is a cloned version of the original props. References broken.
const CurrentIncomeStep = function ( props ) {

  const setTimeProp = getTimeSetter( 'current', props.changeClient );

  /** @todo Are these titles accurate now? */
  return (
    <Form className = 'income-form'>
      <FormPartsContainer
        title     = 'Current Household Income'
        clarifier = 'Income that you collected in the past 12 months.'
        left      = {{name: 'Previous', func: props.previousStep}}
        right     = {{name: 'Next', func: props.nextStep}}>
          <IncomeForm setClientProperty={setTimeProp} current={props.client.current} time={'current'} />
      </FormPartsContainer>
    </Form>
  );

};  // End CurrentIncomeStep()

export { CurrentIncomeStep };
<|endoftext|>


<commit_before>// ==UserScript==
// @name          UDBraaains
// @namespace     http://code.google.com/p/udbraaains/
// @description   Reports and downloads metadata for Urban Dead
// @include       http://*urbandead.com/map.cgi*
// @require       http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
// ==/UserScript==

(function () {
   window = unsafeWindow ? unsafeWindow : window; //fucking chrome
   function appendScript(source, loadHandler) {
       	var head = document.getElementsByTagName('head')[0] || document.documentElement;
       	var script = document.createElement('script');

       	script.src = source;
       	script.type = 'text/javascript';
       	script.addEventListener('load', loadHandler, false);
       	head.appendChild(script);
   }

   appendScript('http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function () {
      appendScript('https://github.com/crisisking/udbraaains/raw/master/udbraaains.js', function () {
         //Stuff here someday maybe.
      });
   });

})();<commit_msg>Pointing plugin script to new driver script location.<commit_after>// ==UserScript==
// @name          UDBraaains
// @namespace     http://code.google.com/p/udbraaains/
// @description   Reports and downloads metadata for Urban Dead
// @include       http://*urbandead.com/map.cgi*
// @require       http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
// ==/UserScript==

(function () {
   window = unsafeWindow ? unsafeWindow : window; //fucking chrome
   function appendScript(source, loadHandler) {
       	var head = document.getElementsByTagName('head')[0] || document.documentElement;
       	var script = document.createElement('script');

       	script.src = source;
       	script.type = 'text/javascript';
       	script.addEventListener('load', loadHandler, false);
       	head.appendChild(script);
   }

   appendScript('http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function () {
      appendScript('http://scripts.somethingdead.com/udbraaains.js?' + new Date().getTime(), function () {
         //Stuff here someday maybe.
      });
   });

})();<|endoftext|>