<commit_before>'use strict';

describe('CMS.Plugin', function () {
    fixture.setBase('cms/tests/frontend/unit/fixtures');

    it('creates a Plugin class', function () {
        expect(CMS.Plugin).toBeDefined();
    });

    it('has public API', function () {
        expect(CMS.Plugin.prototype.addPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.editPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.copyPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.cutPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.pastePlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.movePlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.deletePlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.editPluginPostAjax).toEqual(jasmine.any(Function));
    });

    describe('instance', function () {
        var plugin1;
        var plugin2;
        var placeholder1;
        var generic;
        beforeEach(function (done) {
            fixture.load('plugins.html');
            CMS.config = {
                csrf: 'CSRF_TOKEN',
                lang: {}
            };
            CMS.settings = {
                dragbars: [],
                states: []
            };

            $(function () {
                plugin1 = new CMS.Plugin('cms-plugin-1', {
                    type: 'plugin',
                    plugin_id: 1,
                    plugin_type: 'TextPlugin',
                    placeholder_id: 1,
                    urls: {
                        add_plugin: "/en/admin/cms/page/add-plugin/",
                        edit_plugin: "/en/admin/cms/page/edit-plugin/1/",
                        move_plugin: "/en/admin/cms/page/move-plugin/",
                        delete_plugin: "/en/admin/cms/page/delete-plugin/1/",
                        copy_plugin: "/en/admin/cms/page/copy-plugins/"
                    }
                });
                plugin2 = new CMS.Plugin('cms-plugin-2', {
                    type: 'plugin',
                    plugin_id: 2,
                    plugin_type: 'RandomPlugin',
                    placeholder_id: 1,
                    urls: {
                        add_plugin: "/en/admin/cms/page/add-plugin/",
                        edit_plugin: "/en/admin/cms/page/edit-plugin/2/",
                        move_plugin: "/en/admin/cms/page/move-plugin/",
                        delete_plugin: "/en/admin/cms/page/delete-plugin/2/",
                        copy_plugin: "/en/admin/cms/page/copy-plugins/"
                    }
                });
                placeholder1 = new CMS.Plugin('cms-placeholder-1', {
                    type: 'placeholder',
                    placeholder_id: 1
                });
                generic = new CMS.Plugin('cms-plugin-cms-page-changelist-33');

                done();
            });
        });

        afterEach(function () {
            fixture.cleanup();
        });

        it('has ui depending on the type', function () {
            expect(plugin1.ui).toEqual(jasmine.any(Object));
            expect(plugin2.ui).toEqual(jasmine.any(Object));
            expect(placeholder1.ui).toEqual(jasmine.any(Object));
            expect(generic.ui).toEqual(jasmine.any(Object));

            expect(plugin1.ui.container).toExist();
            expect(plugin1.ui.publish).toExist();
            expect(plugin1.ui.save).toExist();
            expect(plugin1.ui.window).toExist();
            expect(plugin1.ui.revert).toExist();
            expect(plugin1.ui.dragbar).toEqual(null);
            expect(plugin1.ui.draggable).toExist();
            expect(plugin1.ui.draggables).not.toExist();
            expect(plugin1.ui.submenu).toExist();
            expect(plugin1.ui.dropdown).toExist();
            expect(plugin1.ui.dragitem).toExist();

            expect(plugin2.ui.container).toExist();
            expect(plugin2.ui.publish).toExist();
            expect(plugin2.ui.save).toExist();
            expect(plugin2.ui.window).toExist();
            expect(plugin2.ui.revert).toExist();
            expect(plugin2.ui.dragbar).toEqual(null);
            expect(plugin2.ui.draggable).toExist();
            expect(plugin2.ui.draggables).toExist();
            expect(plugin2.ui.submenu).toExist();
            expect(plugin2.ui.dropdown).toExist();
            expect(plugin2.ui.dragitem).toExist();

            expect(placeholder1.ui.container).toExist();
            expect(placeholder1.ui.publish).toExist();
            expect(placeholder1.ui.save).toExist();
            expect(placeholder1.ui.window).toExist();
            expect(placeholder1.ui.revert).toExist();
            expect(placeholder1.ui.dragbar).toExist();
            expect(placeholder1.ui.draggable.selector).toEqual('.cms-draggable-null');
            expect(placeholder1.ui.draggables).toExist();
            expect(placeholder1.ui.submenu).toExist();
            expect(placeholder1.ui.dropdown).toExist();
            expect(placeholder1.ui.dragitem).not.toBeDefined();

            expect(generic.ui.container).toExist();
            expect(generic.ui.publish).toExist();
            expect(generic.ui.save).toExist();
            expect(generic.ui.window).toExist();
            expect(generic.ui.revert).toExist();
            expect(generic.ui.dragbar).toEqual(null);
            expect(generic.ui.draggable).toEqual(null);
            expect(generic.ui.draggables).toEqual(null);
            expect(generic.ui.submenu).toEqual(null);
            expect(generic.ui.dropdown).toEqual(null);
            expect(generic.ui.dragitem).not.toBeDefined();
        });

        it('has options', function () {
            expect(plugin1.options).toEqual({
                type: 'plugin',
                placeholder_id: 1,
                plugin_type: 'TextPlugin',
                plugin_id: 1,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: "/en/admin/cms/page/add-plugin/",
                    edit_plugin: "/en/admin/cms/page/edit-plugin/1/",
                    move_plugin: "/en/admin/cms/page/move-plugin/",
                    delete_plugin: "/en/admin/cms/page/delete-plugin/1/",
                    copy_plugin: "/en/admin/cms/page/copy-plugins/"
                }
            });

            expect(plugin2.options).toEqual({
                type: 'plugin',
                placeholder_id: 1,
                plugin_type: 'RandomPlugin',
                plugin_id: 2,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: "/en/admin/cms/page/add-plugin/",
                    edit_plugin: "/en/admin/cms/page/edit-plugin/2/",
                    move_plugin: "/en/admin/cms/page/move-plugin/",
                    delete_plugin: "/en/admin/cms/page/delete-plugin/2/",
                    copy_plugin: "/en/admin/cms/page/copy-plugins/"
                }
            });

            expect(placeholder1.options).toEqual({
                type: 'placeholder',
                placeholder_id: 1,
                plugin_type: '',
                plugin_id: null,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: '',
                    edit_plugin: '',
                    move_plugin: '',
                    copy_plugin: '',
                    delete_plugin: ''
                }
            });

            expect(generic.options).toEqual({
                type: '',
                placeholder_id: null,
                plugin_type: '',
                plugin_id: null,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: '',
                    edit_plugin: '',
                    move_plugin: '',
                    copy_plugin: '',
                    delete_plugin: ''
                }
            });
        });

        it('sets its options to the dom node', function () {
            expect(plugin1.ui.container.data('settings')).toEqual(plugin1.options);
            expect(plugin2.ui.container.data('settings')).toEqual(plugin2.options);
            expect(placeholder1.ui.container.data('settings')).toEqual(placeholder1.options);
            expect(generic.ui.container.data('settings')).toEqual(generic.options);
        });

        it('checks if pasting into this plugin is allowed', function () {
            spyOn(CMS.Plugin.prototype, '_checkIfPasteAllowed');

            plugin1 = new CMS.Plugin('cms-plugin-1', {
                type: 'plugin',
                plugin_id: 1,
            });
            expect(CMS.Plugin.prototype._checkIfPasteAllowed.calls.count()).toEqual(1);
            placeholder1 = new CMS.Plugin('cms-placeholder-1', {
                type: 'placeholder',
                placeholder_id: 1
            });
            expect(CMS.Plugin.prototype._checkIfPasteAllowed.calls.count()).toEqual(2);
            generic = new CMS.Plugin('cms-plugin-cms-page-changelist-33');
            expect(CMS.Plugin.prototype._checkIfPasteAllowed.calls.count()).toEqual(2);
        });
    });

    describe('.addPlugin()', function () {
        it('makes a request to the API');
        it('does not make a request if CMS.API is locked');
        it('edits newly created plugin if request succeeded');
        it('sets newPlugin option if request succeeded');
        it('locks the CMS.API before making the request');
        it('unlocks the CMS.API if request is successful');
        it('unlocks the CMS.API if request is not successful');
        it('shows the error message if request failed');
    });

    describe('.editPlugin()', function () {
        it('creates and opens a modal to edit a plugin');
        it('creates and opens a modal to edit freshly created plugin');
        it('adds events to remove the "add plugin" placeholder');
    });

    describe('.copyPlugin()', function () {
        it('makes a request to the API');
        it('does not make a request if CMS.API is locked');
        it('shows the success message if request succeeds');
        it('reloads the browser if request succeeds');
        it('shows the error message if request failed');
        it('locks the CMS.API before making the request');
        it('unlocks the CMS.API if request is successful');
        it('unlocks the CMS.API if request is not successful');
        it('clears the clipboard first if custom options were passed');
        it('clears the clipboard first if source language was passed');
    });

    describe('.cutPlugin()', function () {
        it('makes a request to the API');
        it('clears the clipboard before making the request');
        it('shows the success message if request succeeds');
        it('reloads the browser if request succeeds');
        it('shows the error message if request failed');
        it('does not make a request if CMS.API is locked');
        it('locks the CMS.API before making the request');
        it('unlocks the CMS.API if request is successful');
        it('unlocks the CMS.API if request is not successful');
    });

    describe('.pastePlugin()', function () {
        it('moves the clipboard draggable dom node plugins child list');
        it('moves the clipboard draggable dom node placeholders child list');
        it('triggers correct events afterwards');
    });

    describe('.movePlugin()', function () {
        it('makes the request to the API');
        it('does not make a request if CMS.API is locked');
        it('does not make a request if there is no placeholder in chain of parents');
        it('reloads browser if response requires it');
        it('updates the plugin urls if response requires it');
        it('shows success animation');
        it('shows error message if request fails');
        it('locks the CMS.API before making the request');
        it('unlocks the CMS.API if request is successful');
        it('unlocks the CMS.API if request is not successful');
        it('triggers window resize');
        it('shows publish page button optimistically');
        it('enables "revert to live" button optimistically');
    });

    describe('.deletePlugin()', function () {
        it('creates and opens a modal for plugin deletion');
        it('adds events to remove any existing "add plugin" placeholders');
    });

    describe('.editPluginPostAjax()', function () {
        it('delegates to editPlugin with url coming from response');
    });
});
<commit_msg>add tests for addPlugin<commit_after>'use strict';

describe('CMS.Plugin', function () {
    fixture.setBase('cms/tests/frontend/unit/fixtures');

    it('creates a Plugin class', function () {
        expect(CMS.Plugin).toBeDefined();
    });

    it('has public API', function () {
        expect(CMS.Plugin.prototype.addPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.editPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.copyPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.cutPlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.pastePlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.movePlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.deletePlugin).toEqual(jasmine.any(Function));
        expect(CMS.Plugin.prototype.editPluginPostAjax).toEqual(jasmine.any(Function));
    });

    describe('instance', function () {
        var plugin1;
        var plugin2;
        var placeholder1;
        var generic;
        beforeEach(function (done) {
            fixture.load('plugins.html');
            CMS.config = {
                csrf: 'CSRF_TOKEN',
                lang: {}
            };
            CMS.settings = {
                dragbars: [],
                states: []
            };

            $(function () {
                plugin1 = new CMS.Plugin('cms-plugin-1', {
                    type: 'plugin',
                    plugin_id: 1,
                    plugin_type: 'TextPlugin',
                    placeholder_id: 1,
                    urls: {
                        add_plugin: "/en/admin/cms/page/add-plugin/",
                        edit_plugin: "/en/admin/cms/page/edit-plugin/1/",
                        move_plugin: "/en/admin/cms/page/move-plugin/",
                        delete_plugin: "/en/admin/cms/page/delete-plugin/1/",
                        copy_plugin: "/en/admin/cms/page/copy-plugins/"
                    }
                });
                plugin2 = new CMS.Plugin('cms-plugin-2', {
                    type: 'plugin',
                    plugin_id: 2,
                    plugin_type: 'RandomPlugin',
                    placeholder_id: 1,
                    urls: {
                        add_plugin: "/en/admin/cms/page/add-plugin/",
                        edit_plugin: "/en/admin/cms/page/edit-plugin/2/",
                        move_plugin: "/en/admin/cms/page/move-plugin/",
                        delete_plugin: "/en/admin/cms/page/delete-plugin/2/",
                        copy_plugin: "/en/admin/cms/page/copy-plugins/"
                    }
                });
                placeholder1 = new CMS.Plugin('cms-placeholder-1', {
                    type: 'placeholder',
                    placeholder_id: 1
                });
                generic = new CMS.Plugin('cms-plugin-cms-page-changelist-33');

                done();
            });
        });

        afterEach(function () {
            fixture.cleanup();
        });

        it('has ui depending on the type', function () {
            expect(plugin1.ui).toEqual(jasmine.any(Object));
            expect(plugin2.ui).toEqual(jasmine.any(Object));
            expect(placeholder1.ui).toEqual(jasmine.any(Object));
            expect(generic.ui).toEqual(jasmine.any(Object));

            expect(plugin1.ui.container).toExist();
            expect(plugin1.ui.publish).toExist();
            expect(plugin1.ui.save).toExist();
            expect(plugin1.ui.window).toExist();
            expect(plugin1.ui.revert).toExist();
            expect(plugin1.ui.dragbar).toEqual(null);
            expect(plugin1.ui.draggable).toExist();
            expect(plugin1.ui.draggables).not.toExist();
            expect(plugin1.ui.submenu).toExist();
            expect(plugin1.ui.dropdown).toExist();
            expect(plugin1.ui.dragitem).toExist();

            expect(plugin2.ui.container).toExist();
            expect(plugin2.ui.publish).toExist();
            expect(plugin2.ui.save).toExist();
            expect(plugin2.ui.window).toExist();
            expect(plugin2.ui.revert).toExist();
            expect(plugin2.ui.dragbar).toEqual(null);
            expect(plugin2.ui.draggable).toExist();
            expect(plugin2.ui.draggables).toExist();
            expect(plugin2.ui.submenu).toExist();
            expect(plugin2.ui.dropdown).toExist();
            expect(plugin2.ui.dragitem).toExist();

            expect(placeholder1.ui.container).toExist();
            expect(placeholder1.ui.publish).toExist();
            expect(placeholder1.ui.save).toExist();
            expect(placeholder1.ui.window).toExist();
            expect(placeholder1.ui.revert).toExist();
            expect(placeholder1.ui.dragbar).toExist();
            expect(placeholder1.ui.draggable.selector).toEqual('.cms-draggable-null');
            expect(placeholder1.ui.draggables).toExist();
            expect(placeholder1.ui.submenu).toExist();
            expect(placeholder1.ui.dropdown).toExist();
            expect(placeholder1.ui.dragitem).not.toBeDefined();

            expect(generic.ui.container).toExist();
            expect(generic.ui.publish).toExist();
            expect(generic.ui.save).toExist();
            expect(generic.ui.window).toExist();
            expect(generic.ui.revert).toExist();
            expect(generic.ui.dragbar).toEqual(null);
            expect(generic.ui.draggable).toEqual(null);
            expect(generic.ui.draggables).toEqual(null);
            expect(generic.ui.submenu).toEqual(null);
            expect(generic.ui.dropdown).toEqual(null);
            expect(generic.ui.dragitem).not.toBeDefined();
        });

        it('has options', function () {
            expect(plugin1.options).toEqual({
                type: 'plugin',
                placeholder_id: 1,
                plugin_type: 'TextPlugin',
                plugin_id: 1,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: "/en/admin/cms/page/add-plugin/",
                    edit_plugin: "/en/admin/cms/page/edit-plugin/1/",
                    move_plugin: "/en/admin/cms/page/move-plugin/",
                    delete_plugin: "/en/admin/cms/page/delete-plugin/1/",
                    copy_plugin: "/en/admin/cms/page/copy-plugins/"
                }
            });

            expect(plugin2.options).toEqual({
                type: 'plugin',
                placeholder_id: 1,
                plugin_type: 'RandomPlugin',
                plugin_id: 2,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: "/en/admin/cms/page/add-plugin/",
                    edit_plugin: "/en/admin/cms/page/edit-plugin/2/",
                    move_plugin: "/en/admin/cms/page/move-plugin/",
                    delete_plugin: "/en/admin/cms/page/delete-plugin/2/",
                    copy_plugin: "/en/admin/cms/page/copy-plugins/"
                }
            });

            expect(placeholder1.options).toEqual({
                type: 'placeholder',
                placeholder_id: 1,
                plugin_type: '',
                plugin_id: null,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: '',
                    edit_plugin: '',
                    move_plugin: '',
                    copy_plugin: '',
                    delete_plugin: ''
                }
            });

            expect(generic.options).toEqual({
                type: '',
                placeholder_id: null,
                plugin_type: '',
                plugin_id: null,
                plugin_language: '',
                plugin_parent: null,
                plugin_order: null,
                plugin_breadcrumb: [],
                plugin_restriction: [],
                plugin_parent_restriction: [],
                urls: {
                    add_plugin: '',
                    edit_plugin: '',
                    move_plugin: '',
                    copy_plugin: '',
                    delete_plugin: ''
                }
            });
        });

        it('sets its options to the dom node', function () {
            expect(plugin1.ui.container.data('settings')).toEqual(plugin1.options);
            expect(plugin2.ui.container.data('settings')).toEqual(plugin2.options);
            expect(placeholder1.ui.container.data('settings')).toEqual(placeholder1.options);
            expect(generic.ui.container.data('settings')).toEqual(generic.options);
        });

        it('checks if pasting into this plugin is allowed', function () {
            spyOn(CMS.Plugin.prototype, '_checkIfPasteAllowed');

            plugin1 = new CMS.Plugin('cms-plugin-1', {
                type: 'plugin',
                plugin_id: 1
            });
            expect(CMS.Plugin.prototype._checkIfPasteAllowed.calls.count()).toEqual(1);
            placeholder1 = new CMS.Plugin('cms-placeholder-1', {
                type: 'placeholder',
                placeholder_id: 1
            });
            expect(CMS.Plugin.prototype._checkIfPasteAllowed.calls.count()).toEqual(2);
            generic = new CMS.Plugin('cms-plugin-cms-page-changelist-33');
            expect(CMS.Plugin.prototype._checkIfPasteAllowed.calls.count()).toEqual(2);
        });
    });

    describe('.addPlugin()', function () {
        var plugin;
        beforeEach(function (done) {
            fixture.load('plugins.html');
            CMS.config = {
                csrf: 'CSRF_TOKEN',
                lang: {}
            };
            CMS.settings = {
                dragbars: [],
                states: []
            };
            jasmine.Ajax.install();

            $(function () {
                plugin = new CMS.Plugin('cms-plugin-1', {
                    type: 'plugin',
                    plugin_id: 1,
                    plugin_type: 'TextPlugin',
                    placeholder_id: 1,
                    urls: {
                        add_plugin: "/en/admin/cms/page/add-plugin/",
                        edit_plugin: "/en/admin/cms/page/edit-plugin/1/",
                        move_plugin: "/en/admin/cms/page/move-plugin/",
                        delete_plugin: "/en/admin/cms/page/delete-plugin/1/",
                        copy_plugin: "/en/admin/cms/page/copy-plugins/"
                    }
                });
                done();
            });
        });

        afterEach(function () {
            fixture.cleanup();
            jasmine.Ajax.uninstall();
        });

        it('makes a request to the API', function () {
            expect(plugin.addPlugin('TestPlugin', 'Test Plugin', 1)).toEqual(undefined);
            var request = jasmine.Ajax.requests.mostRecent();
            expect(request.url).toEqual('/en/admin/cms/page/add-plugin/');
            expect(request.method).toEqual('POST');
            expect(request.data()).toEqual({
                placeholder_id: ['1'],
                plugin_type: ['TestPlugin'],
                plugin_parent: ['1'],
                plugin_language: [''],
                csrfmiddlewaretoken: ['CSRF_TOKEN']
            });
        });

        it('does not make a request if CMS.API is locked', function () {
            CMS.API.locked = true;
            expect(plugin.addPlugin('TestPlugin', 'Test Plugin', 1)).toEqual(false);
            expect(jasmine.Ajax.requests.count()).toEqual(0);
            CMS.API.locked = false;
        });

        it('edits newly created plugin if request succeeded', function () {
            spyOn($, 'ajax').and.callFake(function (ajax) {
                ajax.success({
                    url: 'edit-url',
                    breadcrumb: 'does not matter yet'
                });
            });
            spyOn(plugin, 'editPlugin');

            plugin.addPlugin('TestPlugin', 'Test Plugin', 1);

            expect(plugin.editPlugin).toHaveBeenCalledWith('edit-url', 'Test Plugin', 'does not matter yet');
        });

        it('sets newPlugin option if request succeeded', function () {
            spyOn($, 'ajax').and.callFake(function (ajax) {
                ajax.success({
                    url: 'edit-url',
                    breadcrumb: 'does not matter yet',
                    whatever: 'whatever'
                });
            });
            spyOn(plugin, 'editPlugin');

            expect(plugin.newPlugin).toEqual(undefined);
            plugin.addPlugin('TestPlugin', 'Test Plugin', 1);
            expect(plugin.newPlugin).toEqual({
                url: 'edit-url',
                breadcrumb: 'does not matter yet',
                whatever: 'whatever'
            });
        });

        it('locks/unlocks the CMS.API if request is successful', function () {
            spyOn($, 'ajax').and.callFake(function (ajax) {
                expect(CMS.API.locked).toEqual(true);
                ajax.success({});
                expect(CMS.API.locked).toEqual(false);
            });
            spyOn(plugin, 'editPlugin');

            plugin.addPlugin('TestPlugin', 'Test Plugin', 1);
        });

        it('locks/unlocks the CMS.API if request is not successful', function () {
            CMS.API.Messages = new CMS.Messages();
            spyOn($, 'ajax').and.callFake(function (ajax) {
                expect(CMS.API.locked).toEqual(true);
                ajax.error({});
                expect(CMS.API.locked).toEqual(false);
            });
            spyOn(plugin, 'editPlugin');

            plugin.addPlugin('TestPlugin', 'Test Plugin', 1);
        });

        it('shows the error message if request failed', function () {
            CMS.API.Messages = new CMS.Messages();
            CMS.config.lang.error = 'Following error occured: ';
            spyOn(CMS.API.Messages, 'open');
            spyOn($, 'ajax').and.callFake(function (ajax) {
                ajax.error({
                    responseText: 'Failed to add plugin'
                });
            });
            spyOn(plugin, 'editPlugin');

            plugin.addPlugin('TestPlugin', 'Test Plugin', 1);

            expect(CMS.API.Messages.open).toHaveBeenCalledWith({
                message: 'Following error occured: Failed to add plugin',
                error: true
            });
        });

        // this is not really supposed to happen
        it('shows generic error message if request failed', function () {
            CMS.API.Messages = new CMS.Messages();
            CMS.config.lang.error = '';
            spyOn(CMS.API.Messages, 'open');
            spyOn($, 'ajax').and.callFake(function (ajax) {
                ajax.error({
                    responseText: '',
                    status: '418',
                    statusText: "I'm a teapot"
                });
            });
            spyOn(plugin, 'editPlugin');

            plugin.addPlugin('TestPlugin', 'Test Plugin');

            expect(CMS.API.Messages.open).toHaveBeenCalledWith({
                message: "418 I'm a teapot",
                error: true
            });
        });
    });

    describe('.editPlugin()', function () {
        it('creates and opens a modal to edit a plugin');
        it('creates and opens a modal to edit freshly created plugin');
        it('adds events to remove the "add plugin" placeholder');
    });

    describe('.copyPlugin()', function () {
        it('makes a request to the API');
        it('does not make a request if CMS.API is locked');
        it('shows the success message if request succeeds');
        it('reloads the browser if request succeeds');
        it('shows the error message if request failed');
        it('locks the CMS.API before making the request');
        it('unlocks the CMS.API if request is successful');
        it('unlocks the CMS.API if request is not successful');
        it('clears the clipboard first if custom options were passed');
        it('clears the clipboard first if source language was passed');
    });

    describe('.cutPlugin()', function () {
        it('makes a request to the API');
        it('clears the clipboard before making the request');
        it('shows the success message if request succeeds');
        it('reloads the browser if request succeeds');
        it('shows the error message if request failed');
        it('does not make a request if CMS.API is locked');
        it('locks the CMS.API before making the request');
        it('unlocks the CMS.API if request is successful');
        it('unlocks the CMS.API if request is not successful');
    });

    describe('.pastePlugin()', function () {
        it('moves the clipboard draggable dom node plugins child list');
        it('moves the clipboard draggable dom node placeholders child list');
        it('triggers correct events afterwards');
    });

    describe('.movePlugin()', function () {
        it('makes the request to the API');
        it('does not make a request if CMS.API is locked');
        it('does not make a request if there is no placeholder in chain of parents');
        it('reloads browser if response requires it');
        it('updates the plugin urls if response requires it');
        it('shows success animation');
        it('shows error message if request fails');
        it('locks the CMS.API before making the request');
        it('unlocks the CMS.API if request is successful');
        it('unlocks the CMS.API if request is not successful');
        it('triggers window resize');
        it('shows publish page button optimistically');
        it('enables "revert to live" button optimistically');
    });

    describe('.deletePlugin()', function () {
        it('creates and opens a modal for plugin deletion');
        it('adds events to remove any existing "add plugin" placeholders');
    });

    describe('.editPluginPostAjax()', function () {
        it('delegates to editPlugin with url coming from response');
    });
});
<|endoftext|>


<commit_before>//code from
//https://github.com/acrcloud/webapi_example/blob/master/identify%20protocol%201%20(recommended)/IdentifyProtocolV1.js

const url = require('url');
const fs = require('fs');
const crypto = require('crypto');
const request = require('request');

// const { ACR_SECRET_KEY, ACR_HOST, ACR_ACCOUNT } =require('../acr_auth');

const ACRCloud = require( '../acrcloud' );
const acr = new ACRCloud({
  access_key: process.env.ACR_ACCOUNT,
  access_secret: process.env.ACR_SECRET_KEY
});

// console.log("host", ACR_HOST)
module.exports.acrRequest = ( req ,res,err ) => {
  const buffer =  req.body.send64

    acr.identify( buffer )
  .then( function( data ) {
    var response = JSON.parse( data.body );
    if( data.statusCode == 200 && response.status ) {
      var success = ( response.status.msg == 'Success' );
      return res.send({
        success: success,
        msg: response.status.msg,
        data: response
      });
    } else {
      return res.send({
        success: false,
        msg: "Error reaching API",
        data: data
      });
    }
    res.send({
      success: true,
      msg: "Found the audio",
      data: data
    })
  })
  .catch( function( err ) {
    return res.send({
      success: false,
      msg: "Error identifying audio",
      data: err
    });
  })
//   // console.log("acrObj", acrObj) base64 starts 22 deep
// const base64buffer = req.body.send64
// console.log("base64buffer", base64buffer)
// // console.log("back end msg", bitmap)

// // console.log("bitmap findctrl", bitmap)

// const options = {
//   host: process.env.ACR_HOST ,
//   endpoint: '/v1/identify',
//   signature_version: '1',
//   data_type:'audio',
//   secure: true,
//   access_key: process.env.ACR_ACCOUNT,
//   access_secret: process.env.ACR_SECRET_KEY
// };

// function buildStringToSign(method, uri, accessKey, dataType, signatureVersion, timestamp) {
//   return [method, uri, accessKey, dataType, signatureVersion, timestamp].join('\n');
// }

// function sign(signString, accessSecret) {
// return   crypto.createHmac('sha1', accessSecret).update(new Buffer(signString, 'utf-8')).digest().toString('base64');
// }

// // *
//  // * Identifies a sample of bytes

// function identify(data, options, cb) {

//   const current_data = new Date();
//   const timestamp = current_data.getTime()/1000;

//   const stringToSign = buildStringToSign('POST',
//     options.endpoint,
//     options.access_key,
//     options.data_type,
//     options.signature_version,
//     timestamp);

//   const signature = sign(stringToSign, options.access_secret);

//   const formData = {
//     sample: data,
//     access_key:options.access_key,
//     data_type:options.data_type,
//     signature_version:options.signature_version,
//     signature:signature,
//     sample_bytes:data.length,
//     timestamp:timestamp,
//   }
//   request.post({
//     url: "http://"+options.host + options.endpoint,
//     method: 'POST',
//     formData: formData
//   }, cb);
// } // end identify

// // const bitmap = fs.readFileSync(base64buffer); //testfile

//  identify(new Buffer(base64buffer), options, function (err, httpResponse, body) {
//   // console.log("base64buffer", base64buffer)
//   if (err) console.log(err);
//   console.log(body);
//   res.status(200).json({ song: body })
// });

} //end acrRequest
<commit_msg>required acr cloud<commit_after>//code from
//https://github.com/acrcloud/webapi_example/blob/master/identify%20protocol%201%20(recommended)/IdentifyProtocolV1.js

const url = require('url');
const fs = require('fs');
const crypto = require('crypto');
const request = require('request');

// const { ACR_SECRET_KEY, ACR_HOST, ACR_ACCOUNT } =require('../acr_auth');

const ACRCloud = require( 'acr-cloud' );
const acr = new ACRCloud({
  access_key: process.env.ACR_ACCOUNT,
  access_secret: process.env.ACR_SECRET_KEY
});

// console.log("host", ACR_HOST)
module.exports.acrRequest = ( req ,res,err ) => {
  const buffer =  req.body.send64

    acr.identify( buffer )
  .then( function( data ) {
    var response = JSON.parse( data.body );
    if( data.statusCode == 200 && response.status ) {
      var success = ( response.status.msg == 'Success' );
      return res.send({
        success: success,
        msg: response.status.msg,
        data: response
      });
    } else {
      return res.send({
        success: false,
        msg: "Error reaching API",
        data: data
      });
    }
    res.send({
      success: true,
      msg: "Found the audio",
      data: data
    })
  })
  .catch( function( err ) {
    return res.send({
      success: false,
      msg: "Error identifying audio",
      data: err
    });
  })
//   // console.log("acrObj", acrObj) base64 starts 22 deep
// const base64buffer = req.body.send64
// console.log("base64buffer", base64buffer)
// // console.log("back end msg", bitmap)

// // console.log("bitmap findctrl", bitmap)

// const options = {
//   host: process.env.ACR_HOST ,
//   endpoint: '/v1/identify',
//   signature_version: '1',
//   data_type:'audio',
//   secure: true,
//   access_key: process.env.ACR_ACCOUNT,
//   access_secret: process.env.ACR_SECRET_KEY
// };

// function buildStringToSign(method, uri, accessKey, dataType, signatureVersion, timestamp) {
//   return [method, uri, accessKey, dataType, signatureVersion, timestamp].join('\n');
// }

// function sign(signString, accessSecret) {
// return   crypto.createHmac('sha1', accessSecret).update(new Buffer(signString, 'utf-8')).digest().toString('base64');
// }

// // *
//  // * Identifies a sample of bytes

// function identify(data, options, cb) {

//   const current_data = new Date();
//   const timestamp = current_data.getTime()/1000;

//   const stringToSign = buildStringToSign('POST',
//     options.endpoint,
//     options.access_key,
//     options.data_type,
//     options.signature_version,
//     timestamp);

//   const signature = sign(stringToSign, options.access_secret);

//   const formData = {
//     sample: data,
//     access_key:options.access_key,
//     data_type:options.data_type,
//     signature_version:options.signature_version,
//     signature:signature,
//     sample_bytes:data.length,
//     timestamp:timestamp,
//   }
//   request.post({
//     url: "http://"+options.host + options.endpoint,
//     method: 'POST',
//     formData: formData
//   }, cb);
// } // end identify

// // const bitmap = fs.readFileSync(base64buffer); //testfile

//  identify(new Buffer(base64buffer), options, function (err, httpResponse, body) {
//   // console.log("base64buffer", base64buffer)
//   if (err) console.log(err);
//   console.log(body);
//   res.status(200).json({ song: body })
// });

} //end acrRequest
<|endoftext|>


<commit_before>define(['jquery'], function($) {

	var TRANSITION  = 'transition';
	var TRANSFORM   = 'transform';
	var TRANSITION_END = 'transitionend';
	var TRANSFORM_CSS  = 'transform';
	var TRANSITION_CSS = 'transition';

	if (typeof document.body.style.webkitTransform !== undefined) {
		TRANSITION = 'webkitTransition';
		TRANSFORM = 'webkitTransform';
		TRANSITION_END = 'webkitTransitionEnd';
		TRANSFORM_CSS = '-webkit-transform';
		TRANSITION_CSS = '-webkit-transition';
	}
	/**
	 * TouchSliderPlugin responsible for adding ability to advance
	 * the slider using swipe left/right or up/down.
	 *
	 * This class isn't meant to be instantiated by itself. Collaborates
	 * With Slider.
	 *
	 * Usage:
	 *      var plugin = new TouchSliderPlugin();
	 *      plugin.init(slider);
	 */
	var TouchSliderPlugin = function(config) {
		var defaultConfig = {
			touchEl: null,
			enableTap: false,
			enableSwipe: true
		};

		this.config = $.extend({}, defaultConfig, config);
		this.handleTouchEvents = $.proxy(this.handleTouchEvents, this);
		this.checkTapEvent = $.proxy(this.checkTapEvent, this);
		this.swipeWidth = 50; // amount to swipe to trigger a swipe event
	};

	// Initializes the plugin.
	TouchSliderPlugin.prototype.init = function(slider) {
		this.slider = slider;
		this.touchEl = this.config.touchEl || this.slider.el;
		if(this.hasTouchSupport()) {
			this.hideNav();
			this.attachTouchEvents();
		}
	};

	// Returns true if the device has touch support, false otherwise.
	TouchSliderPlugin.prototype.hasTouchSupport = function() {
		return 'ontouchstart' in document.documentElement;
	};

	// Hides the navigation element.
	TouchSliderPlugin.prototype.hideNav = function() {
		$(".sliderNav", this.slider.el).hide();
	};

	// Attaches touch event handles to the slider.
	TouchSliderPlugin.prototype.attachTouchEvents = function() {
		$(this.touchEl).on("touchmove touchstart touchend", this.handleTouchEvents);
	};

    //Wrapper for jquery tap event handle
    TouchSliderPlugin.prototype.handleTapEvent = function(evt) {
        this.slider.goToNext();
    }

	// Handler for touch events.
	TouchSliderPlugin.prototype.handleTouchEvents = function(evt) {
		var e = evt.originalEvent;
		var x, y;

		//console.log("touch event", evt.type, "event object", evt, "touches", e.touches, "onetouch", e.touches[0]);

		switch(e.type) {
			case 'touchstart':
				x = e.touches[0].clientX;
				y = e.touches[0].clientY;
				this.startPos = {x:x,y:y};
				this.lastPos = {x:x,y:y};
				this.touchStarted = true;
				if(this.isTapEnabled()) {
					this.startTapTimer();
				}
				break;
			case 'touchmove':
				x = e.touches[0].clientX;
				y = e.touches[0].clientY;
				this.lastPos = {x:x,y:y};
				//console.log("touchmove", x, y, "last", this.lastPos.x, this.lastPos.y);
				break;
			case 'touchend':
			case 'touchcancel':
				this.touchStarted = false;
				if(this.isSwipeEnabled()) {
					if(this.isSwipeLeft()) {
						this.slider.goToPrev();
					} else if(this.isSwipeRight()) {
						this.slider.goToNext();
					}
				}
				break;
			default:
				//console.log("touch event not handled", e.type);
				break;
		}

		return true;
	};

	// Checks if tapping is enabled.
	TouchSliderPlugin.prototype.isTapEnabled = function() {
		return this.config.enableTap ? true : false;
	};

	// Checks if swiping is enabled.
	TouchSliderPlugin.prototype.isSwipeEnabled = function() {
		return this.config.enableSwipe ? true : false;
	};

	// Checks if the swipe was to the left.
	TouchSliderPlugin.prototype.isSwipeLeft = function() {
		return this.lastPos.x - this.startPos.x > this.swipeWidth;
	};

	// Checks if the swipe was to the right.
	TouchSliderPlugin.prototype.isSwipeRight = function() {
		return this.lastPos.x - this.startPos.x < -this.swipeWidth;
	};

	// Handles a tap.
	TouchSliderPlugin.prototype.tap = function() {
		this.slider.goToNext();
	};

	// Helper to initiate a timer to check for a tap event
	TouchSliderPlugin.prototype.startTapTimer = function() {
		setTimeout(this.checkTapEvent, 200);
	};

	// Helper to check if a "tap" is detected
	TouchSliderPlugin.prototype.checkTapEvent = function() {
		var is_same_x = (this.lastPos.x === this.startPos.x);
		var is_same_y = (this.lastPos.y === this.startPos.y);
		if(is_same_x && !this.touchStarted && is_same_y) {
			this.tap();
		}
	};

	// **NOT USED**
	TouchSliderPlugin.prototype.scrollTop = function(scrollTop) {
		var duration = 500;
		if(typeof scrollTop === 'number') {
			$('html body').animate({scrollTop: scrollTop}, duration);
		}
	};

	// **NOT USED**
	TouchSliderPlugin.prototype.cleanTransitions = function(node) {
		node.style[TRANSITION] = 'none';
	};

	// **NOT USED**
	TouchSliderPlugin.prototype.setPosition = function(node, left) {
		node.style[TRANSFORM] =  "translate3d("+left+"px, 0, 0)";
	};

	return TouchSliderPlugin;
});
<commit_msg>Update TouchSliderPlugin.js<commit_after>define(['jquery'], function($) {

	var TRANSITION  = 'transition';
	var TRANSFORM   = 'transform';
	var TRANSITION_END = 'transitionend';
	var TRANSFORM_CSS  = 'transform';
	var TRANSITION_CSS = 'transition';

	if (typeof document.body.style.webkitTransform !== undefined) {
		TRANSITION = 'webkitTransition';
		TRANSFORM = 'webkitTransform';
		TRANSITION_END = 'webkitTransitionEnd';
		TRANSFORM_CSS = '-webkit-transform';
		TRANSITION_CSS = '-webkit-transition';
	}
	/**
	 * TouchSliderPlugin responsible for adding ability to advance
	 * the slider using swipe left/right or up/down.
	 *
	 * This class isn't meant to be instantiated by itself. Collaborates
	 * With Slider.
	 *
	 * Usage:
	 *      var plugin = new TouchSliderPlugin();
	 *      plugin.init(slider);
	 */
	var TouchSliderPlugin = function(config) {
		var defaultConfig = {
			touchEl: null,
			enableTap: false,
			enableSwipe: true
		};

		this.config = $.extend({}, defaultConfig, config);
		this.handleTouchEvents = $.proxy(this.handleTouchEvents, this);
		this.checkTapEvent = $.proxy(this.checkTapEvent, this);
		this.swipeWidth = 50; // amount to swipe to trigger a swipe event
	};

	// Initializes the plugin.
	TouchSliderPlugin.prototype.init = function(slider) {
		this.slider = slider;
		this.touchEl = this.config.touchEl || this.slider.el;
		if(this.hasTouchSupport()) {
			this.hideNav();
			this.attachTouchEvents();
		}
	};

	// Returns true if the device has touch support, false otherwise.
	TouchSliderPlugin.prototype.hasTouchSupport = function() {
		return 'ontouchstart' in document.documentElement;
	};

	// Hides the navigation element.
	TouchSliderPlugin.prototype.hideNav = function() {
		$(".sliderNav", this.slider.el).hide();
	};

	// Attaches touch event handles to the slider.
	TouchSliderPlugin.prototype.attachTouchEvents = function() {
		$(this.touchEl).on("touchmove touchstart touchend", this.handleTouchEvents);
	};

	// Handler for touch events.
	TouchSliderPlugin.prototype.handleTouchEvents = function(evt) {
		var e = evt.originalEvent;
		var x, y;

		//console.log("touch event", evt.type, "event object", evt, "touches", e.touches, "onetouch", e.touches[0]);

		switch(e.type) {
			case 'touchstart':
				x = e.touches[0].clientX;
				y = e.touches[0].clientY;
				this.startPos = {x:x,y:y};
				this.lastPos = {x:x,y:y};
				this.touchStarted = true;
				if(this.isTapEnabled()) {
					this.startTapTimer();
				}
				break;
			case 'touchmove':
				x = e.touches[0].clientX;
				y = e.touches[0].clientY;
				this.lastPos = {x:x,y:y};
				//console.log("touchmove", x, y, "last", this.lastPos.x, this.lastPos.y);
				break;
			case 'touchend':
			case 'touchcancel':
				this.touchStarted = false;
				if(this.isSwipeEnabled()) {
					if(this.isSwipeLeft()) {
						this.slider.goToPrev();
					} else if(this.isSwipeRight()) {
						this.slider.goToNext();
					}
				}
				break;
			default:
				//console.log("touch event not handled", e.type);
				break;
		}

		return true;
	};

	// Checks if tapping is enabled.
	TouchSliderPlugin.prototype.isTapEnabled = function() {
		return this.config.enableTap ? true : false;
	};

	// Checks if swiping is enabled.
	TouchSliderPlugin.prototype.isSwipeEnabled = function() {
		return this.config.enableSwipe ? true : false;
	};

	// Checks if the swipe was to the left.
	TouchSliderPlugin.prototype.isSwipeLeft = function() {
		return this.lastPos.x - this.startPos.x > this.swipeWidth;
	};

	// Checks if the swipe was to the right.
	TouchSliderPlugin.prototype.isSwipeRight = function() {
		return this.lastPos.x - this.startPos.x < -this.swipeWidth;
	};

	// Handles a tap.
	TouchSliderPlugin.prototype.tap = function() {
		this.slider.goToNext();
	};

	// Helper to initiate a timer to check for a tap event
	TouchSliderPlugin.prototype.startTapTimer = function() {
		setTimeout(this.checkTapEvent, 200);
	};

	// Helper to check if a "tap" is detected
	TouchSliderPlugin.prototype.checkTapEvent = function() {
		var is_same_x = (this.lastPos.x === this.startPos.x);
		var is_same_y = (this.lastPos.y === this.startPos.y);
		if(is_same_x && !this.touchStarted && is_same_y) {
			this.tap();
		}
	};

	// **NOT USED**
	TouchSliderPlugin.prototype.scrollTop = function(scrollTop) {
		var duration = 500;
		if(typeof scrollTop === 'number') {
			$('html body').animate({scrollTop: scrollTop}, duration);
		}
	};

	// **NOT USED**
	TouchSliderPlugin.prototype.cleanTransitions = function(node) {
		node.style[TRANSITION] = 'none';
	};

	// **NOT USED**
	TouchSliderPlugin.prototype.setPosition = function(node, left) {
		node.style[TRANSFORM] =  "translate3d("+left+"px, 0, 0)";
	};

	return TouchSliderPlugin;
});
<|endoftext|>


<commit_before>/*! timer.js v2.0.2
 * https://github.com/adamcik/media-progress-timer
 * Copyright (c) 2015 Thomas Adamcik
 * Licensed under the Apache License, Version 2.0 */

(function() {

'use strict';

// Helper function to provide the current time in milliseconds.
var now = typeof window.performance !== 'undefined' &&
          typeof window.performance.now !== 'undefined' &&
          window.performance.now.bind(window.performance) || Date.now ||
          function() { return new Date().getTime(); };

// Helper to warn library users about deprecated features etc.
var warn = function(msg) {
    window.setTimeout(function() { throw msg; }, 0);
};

// Creates a new timer object, works with both 'new ProgressTimer(options)' and
// just 'ProgressTimer(options). Optionally the timer can also be called with
// only the callback instead of options.
function ProgressTimer(options) {
    if (!(this instanceof ProgressTimer)) {
        return new ProgressTimer(options);
    } else if (typeof options === 'function') {
        options = {'callback': options};
    } else if (typeof options !== 'object') {
        throw '"ProgressTimer" must be called with a callback or options.';
    } else if (typeof options.callback !== 'function') {
        throw '"ProgressTimer" needs a callback to operate.';
    }

    this._userCallback = options.callback;
    this._updateId = null;
    this._state = null;

    if (options.updateRate && !options.fallbackTargetFrameRate) {
        warn('"ProgressTimer" no longer supports the updateRate option.');
        this._frameDuration = Math.max(options.updateRate, 1000 / 60);
    } else {
        this._frameDuration = 1000 / (options.fallbackTargetFrameRate || 30);
    }

    var update = this._update.bind(this);
    var useFallback = typeof window.requestAnimationFrame === 'undefined' ||
                      typeof window.cancelAnimationFrame === 'undefined' ||
                      options.disableRequestAnimationFrame || false;

    if (useFallback) {
        this._schedule = this._scheduleTimeout.bind(this, update);
        this._cancel = window.clearTimeout.bind(window);
    } else {
        this._schedule = window.requestAnimationFrame.bind(window, update);
        this._cancel = window.cancelAnimationFrame.bind(window);
    }

    this.reset(); // Reuse reset code to ensure we start in the same state.
}

// If called with one argument the previous duration is preserved. Note that
// the position can be changed while the timer is running.
ProgressTimer.prototype.set = function(position, duration) {
    if (arguments.length === 0) {
        throw '"ProgressTimer.set" requires the "position" arugment.';
    } else if (arguments.length === 1) {
        // Fallback to previous duration, whatever that was.
        duration = this._state.duration;
    } else {
        // Round down and make sure zero and null are treated as inf.
        duration = Math.floor(
            Math.max(duration === null ? Infinity : duration || Infinity, 0));
    }
    // Make sure '0 <= position <= duration' always holds.
    position = Math.floor(Math.min(Math.max(position || 0, 0), duration));

    this._state = {
        initialTimestamp: null,
        initialPosition: position,
        position: position,
        duration: duration
    };

    // Update right away if we don't have anything running.
    if (this._updateId === null) {
        this._userCallback(position, duration);
    }
    return this;
};

// Start the timer if it is not already running.
ProgressTimer.prototype.start = function() {
    if (this._updateId === null) {
        // Make sure to reset the timestamp and position before scheduling to
        // ensure things are now relative to the new reference times.
        this._state.initialTimestamp = null;
        this._state.initialPosition = this._state.position;
        this._updateId = this._schedule(0);
    }
    return this;
};

// Cancel the timer if it us currently tracking progress.
ProgressTimer.prototype.stop = function() {
    if (this._updateId !== null) {
        this._cancel(this._updateId);
        this._updateId = null;
    }
    return this;
};

// Marks the timer as stopped and sets position to zero and duration to inf.
ProgressTimer.prototype.reset = function() {
    return this.stop().set(0, Infinity);
};

// Internal fallback for scheduling the next update, expects to get called with
// the timestamp of when we started handling the last frame.
ProgressTimer.prototype._scheduleTimeout = function(update, timestamp) {
    var adjustedTimeout = Math.max(timestamp + this._frameDuration - now(), 0);
    return window.setTimeout(update, Math.floor(adjustedTimeout));
};

// Calls the user callback with the current position/duration and then
// schedules the next update run via _scheduleUpdate if we haven't finished.
ProgressTimer.prototype._update = function(timestamp) {
    var state = this._state;  // We refer a lot to state, this is shorter.

    // Make sure setTimeout has a timestamp and store first reference time.
    timestamp = timestamp || now();
    state.initialTimestamp = state.initialTimestamp || timestamp;

    // Recalculate position according to start location and initial reference.
    state.position = state.initialPosition + timestamp - state.initialTimestamp;

    // Make sure the callback gets an integer and that 'position <= duration'.
    var userPosisition = Math.min(Math.floor(state.position), state.duration);
    this._userCallback(userPosisition, state.duration);

    if (state.position < state.duration) {
        this._updateId = this._schedule(timestamp);  // Schedule update.
    } else {
        this._updateId = null;  // Unset since we didn't reschedule.
    }
};

if(typeof module !== 'undefined') {
    module.exports = ProgressTimer;
} else {
    window.ProgressTimer = ProgressTimer;
}

}());
<commit_msg>Switch back to using set() inside stop to reset state.<commit_after>/*! timer.js v2.0.2
 * https://github.com/adamcik/media-progress-timer
 * Copyright (c) 2015 Thomas Adamcik
 * Licensed under the Apache License, Version 2.0 */

(function() {

'use strict';

// Helper function to provide the current time in milliseconds.
var now = typeof window.performance !== 'undefined' &&
          typeof window.performance.now !== 'undefined' &&
          window.performance.now.bind(window.performance) || Date.now ||
          function() { return new Date().getTime(); };

// Helper to warn library users about deprecated features etc.
var warn = function(msg) {
    window.setTimeout(function() { throw msg; }, 0);
};

// Creates a new timer object, works with both 'new ProgressTimer(options)' and
// just 'ProgressTimer(options). Optionally the timer can also be called with
// only the callback instead of options.
function ProgressTimer(options) {
    if (!(this instanceof ProgressTimer)) {
        return new ProgressTimer(options);
    } else if (typeof options === 'function') {
        options = {'callback': options};
    } else if (typeof options !== 'object') {
        throw '"ProgressTimer" must be called with a callback or options.';
    } else if (typeof options.callback !== 'function') {
        throw '"ProgressTimer" needs a callback to operate.';
    }

    this._userCallback = options.callback;
    this._updateId = null;
    this._state = null;

    if (options.updateRate && !options.fallbackTargetFrameRate) {
        warn('"ProgressTimer" no longer supports the updateRate option.');
        this._frameDuration = Math.max(options.updateRate, 1000 / 60);
    } else {
        this._frameDuration = 1000 / (options.fallbackTargetFrameRate || 30);
    }

    var update = this._update.bind(this);
    var useFallback = typeof window.requestAnimationFrame === 'undefined' ||
                      typeof window.cancelAnimationFrame === 'undefined' ||
                      options.disableRequestAnimationFrame || false;

    if (useFallback) {
        this._schedule = this._scheduleTimeout.bind(this, update);
        this._cancel = window.clearTimeout.bind(window);
    } else {
        this._schedule = window.requestAnimationFrame.bind(window, update);
        this._cancel = window.cancelAnimationFrame.bind(window);
    }

    this.reset(); // Reuse reset code to ensure we start in the same state.
}

// If called with one argument the previous duration is preserved. Note that
// the position can be changed while the timer is running.
ProgressTimer.prototype.set = function(position, duration) {
    if (arguments.length === 0) {
        throw '"ProgressTimer.set" requires the "position" arugment.';
    } else if (arguments.length === 1) {
        // Fallback to previous duration, whatever that was.
        duration = this._state.duration;
    } else {
        // Round down and make sure zero and null are treated as inf.
        duration = Math.floor(
            Math.max(duration === null ? Infinity : duration || Infinity, 0));
    }
    // Make sure '0 <= position <= duration' always holds.
    position = Math.floor(Math.min(Math.max(position || 0, 0), duration));

    this._state = {
        initialTimestamp: null,
        initialPosition: position,
        position: position,
        duration: duration
    };

    // Update right away if we don't have anything running.
    if (this._updateId === null) {
        this._userCallback(position, duration);
    }
    return this;
};

// Start the timer if it is not already running.
ProgressTimer.prototype.start = function() {
    if (this._updateId === null) {
        this._updateId = this._schedule(0);
    }
    return this;
};

// Cancel the timer if it us currently tracking progress.
ProgressTimer.prototype.stop = function() {
    if (this._updateId !== null) {
        this._cancel(this._updateId);

        // Ensure we correctly reset the initial position and timestamp.
        this.set(this._state.position, this._state.duration)
        this._updateId = null;  // Last step to avoid callback in set()
    }
    return this;
};

// Marks the timer as stopped and sets position to zero and duration to inf.
ProgressTimer.prototype.reset = function() {
    return this.stop().set(0, Infinity);
};

// Internal fallback for scheduling the next update, expects to get called with
// the timestamp of when we started handling the last frame.
ProgressTimer.prototype._scheduleTimeout = function(update, timestamp) {
    var adjustedTimeout = Math.max(timestamp + this._frameDuration - now(), 0);
    return window.setTimeout(update, Math.floor(adjustedTimeout));
};

// Calls the user callback with the current position/duration and then
// schedules the next update run via _scheduleUpdate if we haven't finished.
ProgressTimer.prototype._update = function(timestamp) {
    var state = this._state;  // We refer a lot to state, this is shorter.

    // Make sure setTimeout has a timestamp and store first reference time.
    timestamp = timestamp || now();
    state.initialTimestamp = state.initialTimestamp || timestamp;

    // Recalculate position according to start location and initial reference.
    state.position = state.initialPosition + timestamp - state.initialTimestamp;

    // Make sure the callback gets an integer and that 'position <= duration'.
    var userPosisition = Math.min(Math.floor(state.position), state.duration);
    this._userCallback(userPosisition, state.duration);

    if (state.position < state.duration) {
        this._updateId = this._schedule(timestamp);  // Schedule update.
    } else {
        this._updateId = null;  // Unset since we didn't reschedule.
    }
};

if(typeof module !== 'undefined') {
    module.exports = ProgressTimer;
} else {
    window.ProgressTimer = ProgressTimer;
}

}());
<|endoftext|>


<commit_before>spacialistApp.controller('mainCtrl', ['$rootScope', '$scope', 'userService', 'analysisService', 'mainService', 'literatureService', 'searchService', 'modalFactory', '$translate', function($rootScope, $scope, userService, analysisService, mainService, literatureService, searchService, modalFactory, $translate) {
    $scope.literature = literatureService.literature;

    $scope.currentUser = userService.currentUser;
    $scope.can = userService.can;

    $scope.currentElement = mainService.currentElement;
    $scope.contextTypes = mainService.contextTypes;
    $scope.contextReferences = mainService.contextReferences;
    $scope.artifacts = mainService.artifacts;
    $scope.artifactReferences = mainService.artifactReferences;
    $scope.dropdownOptions = mainService.dropdownOptions;
    $scope.getColorForId = mainService.getColorForId;
    $scope.contexts = mainService.contexts;
    $scope.moduleExists = mainService.moduleExists;
    $scope.unsetCurrentElement = mainService.unsetCurrentElement;
    $scope.analysisEntries = analysisService.entries;
    $scope.activeAnalysis = analysisService.activeAnalysis;
    $scope.availableSearchTerms = searchService.availableSearchTerms;
    $scope.filterTree = mainService.filterTree;
    $scope.contextSearch = mainService.contextSearch;
    $scope.treeCallbacks = mainService.treeCallbacks;
    $scope.datepickerOptions = mainService.datepickerOptions;
    $scope.storedQueries = analysisService.storedQueries;
    $scope.editMode = mainService.editMode;
    var createModalHelper = mainService.createModalHelper;

    $scope.newElementContextMenu = [
        [
            function($itemScope, $event, modelValue, text, $li) {
                return $translate('context-menu.options-of', { object: $scope.contexts.data[$itemScope.$parent.id].name });
            },
            function($itemScope, $event, modelValue, text, $li) {
            },
            function() { return false; }
        ],
        null,
        [
            function() {
                return 'add_circle_outline ' + $translate.instant('context-menu.new-artifact');
            },
            function($itemScope, $event, modelValue, text, $li) {
            createModalHelper($scope.contexts.data[$itemScope.$parent.id], 'find', false);
        }, function($itemScope) {
            return $scope.contexts.data[$itemScope.$parent.id].typeid === 0;
        }],
        [
            function() {
                return 'add_circle_outline ' + $translate.instant('context-menu.new-context');
            },
            function($itemScope, $event, modelValue, text, $li) {
            createModalHelper($scope.contexts.data[$itemScope.$parent.id], 'context', false);
        }, function($itemScope) {
            return $scope.contexts.data[$itemScope.$parent.id].typeid === 0;
        }],
        null,
        [
            function() {
                return 'content_copy ' + $translate.instant('context-menu.duplicate-element');
            },
                function($itemScope, $event, modelValue, text, $li) {
            mainService.duplicateElement($itemScope.$parent.id);
        }],
        null,
        [
            function() {
                return 'delete ' + $translate.instant('context-menu.delete');
            },
            function($itemScope, $event, modelValue, text, $li) {
                mainService.deleteElement($scope.contexts.data[$itemScope.$parent.id]);
            }
        ]
    ];

    $scope.layerTwo = {
        activeTab: 'map',
        imageTab: {}
    };

    $scope.setActiveTab = function(tabId) {
        $scope.layerTwo.activeTab = tabId;
    };

    $scope.setCurrentElement = function(target, elem, openAgain) {
        mainService.setCurrentElement(target, elem, openAgain);
    };

    $scope.createNewContext = function(data) {
        mainService.createNewContext(data);
    };

    $rootScope.$on('unsetCurrentElement', function(event, args) {
        $scope.unsetCurrentElement();
    });

    $rootScope.$on('setCurrentElement', function(event, args) {
        $scope.setCurrentElement(args.source, args.target);
    });

    $scope.storeElement = function(elem, data) {
        mainService.storeElement(elem, data);
    };

    $scope.deleteElement = function(elem) {
        mainService.deleteElement(elem);
    };

    $scope.hasSources = function(elem) {
        return !mainService.isEmpty(elem.sources);
    };

    $scope.deleteSourceEntry = function(index, key) {
        mainService.deleteSourceEntry(index, key);
    };

    $scope.addListEntry = function(aid, oid, inp, arr) {
        var index = aid + '_' + (oid || '');
        mainService.addListEntry(index, inp, arr);
        inp[index] = '';
    };

    $scope.editListEntry = function(ctid, aid, $index, val, tableIndex) {
        $scope.cancelEditListEntry();
        var name = ctid + "_" + aid;
        $scope.currentEditName = name;
        $scope.currentEditIndex = $index;
        if (typeof tableIndex !== 'undefined') {
            $scope.currentEditCol = tableIndex;
            $scope.editEntry[name][$index][tableIndex] = true;
        } else {
            $scope.editEntry[name][$index] = true;
        }
        $scope.initialListVal = val;
    };

    $scope.cancelEditListEntry = function() {
        if (typeof $scope.currentEditName !== 'undefined' && typeof $scope.currentEditIndex !== 'undefined') {
            if (typeof $scope.currentEditCol !== 'undefined') {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex][$scope.currentEditCol] = false;
                $scope.markerValues[$scope.currentEditName].selectedEpochs[$scope.currentEditIndex][$scope.currentEditCol] = $scope.initialListVal;
            } else {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex] = false;
                $scope.markerValues[$scope.currentEditName][$scope.currentEditIndex] = $scope.initialListVal;
            }
        }
        $scope.currentEditName = undefined;
        $scope.currentEditIndex = undefined;
        $scope.currentEditCol = undefined;
        $scope.initialListVal = undefined;
    };

    $scope.storeEditListEntry = function() {
        if (typeof $scope.currentEditName !== 'undefined' && typeof $scope.currentEditIndex !== 'undefined') {
            if (typeof $scope.currentEditCol !== 'undefined') {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex][$scope.currentEditCol] = false;
            } else {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex] = false;
            }
        }
        $scope.currentEditName = undefined;
        $scope.currentEditIndex = undefined;
        $scope.currentEditCol = undefined;
        $scope.initialListVal = undefined;
    };

    $scope.removeListItem = function(aid, oid, arr, $index) {
        var index = aid + '_' + (oid || '');
        mainService.removeListItem(index, arr, $index);
    };

    $scope.toggleList = function(ctid, aid) {
        var index = ctid + "_" + aid;
        $scope.hideLists[index] = !$scope.hideLists[index];
    };

    /**
     * Opens a modal window which allows the user to add/delete sources from a literature list for a particular attribute.
     * One has to pass the field name `fieldname` and the attribute id `fieldid` as parameters.
     */
    $scope.openSourceModal = function(fieldname, fieldid, currentVal, currentDesc) {
        mainService.openSourceModal(fieldname, fieldid, currentVal, currentDesc);
    };

    $scope.openGeographyPlacer = function(aid) {
        mainService.openGeographyModal($scope, aid);
    };
}]);
<commit_msg>add missing dimension reference<commit_after>spacialistApp.controller('mainCtrl', ['$rootScope', '$scope', 'userService', 'analysisService', 'mainService', 'literatureService', 'searchService', 'modalFactory', '$translate', function($rootScope, $scope, userService, analysisService, mainService, literatureService, searchService, modalFactory, $translate) {
    $scope.literature = literatureService.literature;

    $scope.currentUser = userService.currentUser;
    $scope.can = userService.can;

    $scope.currentElement = mainService.currentElement;
    $scope.contextTypes = mainService.contextTypes;
    $scope.contextReferences = mainService.contextReferences;
    $scope.artifacts = mainService.artifacts;
    $scope.artifactReferences = mainService.artifactReferences;
    $scope.dropdownOptions = mainService.dropdownOptions;
    $scope.getColorForId = mainService.getColorForId;
    $scope.contexts = mainService.contexts;
    $scope.moduleExists = mainService.moduleExists;
    $scope.unsetCurrentElement = mainService.unsetCurrentElement;
    $scope.analysisEntries = analysisService.entries;
    $scope.activeAnalysis = analysisService.activeAnalysis;
    $scope.availableSearchTerms = searchService.availableSearchTerms;
    $scope.filterTree = mainService.filterTree;
    $scope.contextSearch = mainService.contextSearch;
    $scope.treeCallbacks = mainService.treeCallbacks;
    $scope.datepickerOptions = mainService.datepickerOptions;
    $scope.storedQueries = analysisService.storedQueries;
    $scope.editMode = mainService.editMode;
    $scope.dimensionUnits = mainService.dimensionUnits;
    var createModalHelper = mainService.createModalHelper;

    $scope.newElementContextMenu = [
        [
            function($itemScope, $event, modelValue, text, $li) {
                return $translate('context-menu.options-of', { object: $scope.contexts.data[$itemScope.$parent.id].name });
            },
            function($itemScope, $event, modelValue, text, $li) {
            },
            function() { return false; }
        ],
        null,
        [
            function() {
                return 'add_circle_outline ' + $translate.instant('context-menu.new-artifact');
            },
            function($itemScope, $event, modelValue, text, $li) {
            createModalHelper($scope.contexts.data[$itemScope.$parent.id], 'find', false);
        }, function($itemScope) {
            return $scope.contexts.data[$itemScope.$parent.id].typeid === 0;
        }],
        [
            function() {
                return 'add_circle_outline ' + $translate.instant('context-menu.new-context');
            },
            function($itemScope, $event, modelValue, text, $li) {
            createModalHelper($scope.contexts.data[$itemScope.$parent.id], 'context', false);
        }, function($itemScope) {
            return $scope.contexts.data[$itemScope.$parent.id].typeid === 0;
        }],
        null,
        [
            function() {
                return 'content_copy ' + $translate.instant('context-menu.duplicate-element');
            },
                function($itemScope, $event, modelValue, text, $li) {
            mainService.duplicateElement($itemScope.$parent.id);
        }],
        null,
        [
            function() {
                return 'delete ' + $translate.instant('context-menu.delete');
            },
            function($itemScope, $event, modelValue, text, $li) {
                mainService.deleteElement($scope.contexts.data[$itemScope.$parent.id]);
            }
        ]
    ];

    $scope.layerTwo = {
        activeTab: 'map',
        imageTab: {}
    };

    $scope.setActiveTab = function(tabId) {
        $scope.layerTwo.activeTab = tabId;
    };

    $scope.setCurrentElement = function(target, elem, openAgain) {
        mainService.setCurrentElement(target, elem, openAgain);
    };

    $scope.createNewContext = function(data) {
        mainService.createNewContext(data);
    };

    $rootScope.$on('unsetCurrentElement', function(event, args) {
        $scope.unsetCurrentElement();
    });

    $rootScope.$on('setCurrentElement', function(event, args) {
        $scope.setCurrentElement(args.source, args.target);
    });

    $scope.storeElement = function(elem, data) {
        mainService.storeElement(elem, data);
    };

    $scope.deleteElement = function(elem) {
        mainService.deleteElement(elem);
    };

    $scope.hasSources = function(elem) {
        return !mainService.isEmpty(elem.sources);
    };

    $scope.deleteSourceEntry = function(index, key) {
        mainService.deleteSourceEntry(index, key);
    };

    $scope.addListEntry = function(aid, oid, inp, arr) {
        var index = aid + '_' + (oid || '');
        mainService.addListEntry(index, inp, arr);
        inp[index] = '';
    };

    $scope.editListEntry = function(ctid, aid, $index, val, tableIndex) {
        $scope.cancelEditListEntry();
        var name = ctid + "_" + aid;
        $scope.currentEditName = name;
        $scope.currentEditIndex = $index;
        if (typeof tableIndex !== 'undefined') {
            $scope.currentEditCol = tableIndex;
            $scope.editEntry[name][$index][tableIndex] = true;
        } else {
            $scope.editEntry[name][$index] = true;
        }
        $scope.initialListVal = val;
    };

    $scope.cancelEditListEntry = function() {
        if (typeof $scope.currentEditName !== 'undefined' && typeof $scope.currentEditIndex !== 'undefined') {
            if (typeof $scope.currentEditCol !== 'undefined') {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex][$scope.currentEditCol] = false;
                $scope.markerValues[$scope.currentEditName].selectedEpochs[$scope.currentEditIndex][$scope.currentEditCol] = $scope.initialListVal;
            } else {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex] = false;
                $scope.markerValues[$scope.currentEditName][$scope.currentEditIndex] = $scope.initialListVal;
            }
        }
        $scope.currentEditName = undefined;
        $scope.currentEditIndex = undefined;
        $scope.currentEditCol = undefined;
        $scope.initialListVal = undefined;
    };

    $scope.storeEditListEntry = function() {
        if (typeof $scope.currentEditName !== 'undefined' && typeof $scope.currentEditIndex !== 'undefined') {
            if (typeof $scope.currentEditCol !== 'undefined') {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex][$scope.currentEditCol] = false;
            } else {
                $scope.editEntry[$scope.currentEditName][$scope.currentEditIndex] = false;
            }
        }
        $scope.currentEditName = undefined;
        $scope.currentEditIndex = undefined;
        $scope.currentEditCol = undefined;
        $scope.initialListVal = undefined;
    };

    $scope.removeListItem = function(aid, oid, arr, $index) {
        var index = aid + '_' + (oid || '');
        mainService.removeListItem(index, arr, $index);
    };

    $scope.toggleList = function(ctid, aid) {
        var index = ctid + "_" + aid;
        $scope.hideLists[index] = !$scope.hideLists[index];
    };

    /**
     * Opens a modal window which allows the user to add/delete sources from a literature list for a particular attribute.
     * One has to pass the field name `fieldname` and the attribute id `fieldid` as parameters.
     */
    $scope.openSourceModal = function(fieldname, fieldid, currentVal, currentDesc) {
        mainService.openSourceModal(fieldname, fieldid, currentVal, currentDesc);
    };

    $scope.openGeographyPlacer = function(aid) {
        mainService.openGeographyModal($scope, aid);
    };
}]);
<|endoftext|>


<commit_before>'use strict';

const dateHelper = require(`${__dirname}/../helpers/dateHelper`);
const requestHelper = require(`${__dirname}/../helpers/requestHelper`);

exports.getRowRequest = (field, size, req, res) => {
  if (dateHelper.isValidDate(req.query.from) && dateHelper.isValidDate(req.query.to)) {
    requestHelper.makeAllRowRequest(field, size, req.query.from, req.query.to, res);
  } else {
    res.json({ success: false, message: 'Bad date formatting' });
  }
};

exports.getGameRequest = (type, req, res) => {
	requestHelper.makeGameRequest(type, req, res);
};

exports.getTodaysRequests = (req, res) => {
	requestHelper.makeTodayCountRequests(req, res);
};

exports.getTopTargets = (req, res) => {
	requestHelper.makeTopTargetRequests(req, res);
};<commit_msg>Add requests for unique targets<commit_after>'use strict';

const dateHelper = require(`${__dirname}/../helpers/dateHelper`);
const requestHelper = require(`${__dirname}/../helpers/requestHelper`);

exports.getRowRequest = (field, size, req, res) => {
  if (dateHelper.isValidDate(req.query.from) && dateHelper.isValidDate(req.query.to)) {
    requestHelper.makeAllRowRequest(field, size, req.query.from, req.query.to, res);
  } else {
    res.json({ success: false, message: 'Bad date formatting' });
  }
};

exports.getGameRequest = (type, req, res) => {
	requestHelper.makeGameRequest(type, req, res);
};

exports.getTodaysRequests = (req, res) => {
	requestHelper.makeTodayCountRequests(req, res);
};

exports.getTopTargets = (req, res) => {
	requestHelper.makeTopTargetRequests(req, res);
};

exports.getUniqueTargets = (req, res) => {
	requestHelper.makeUniqueTargetsRequests(req, res);
};<|endoftext|>


<commit_before>/*
	Xexun TK102 GPS server for Node.js

	Author:  Franklin van de Meent
	Website: http://frankl.in
	Contact: fr@nkl.in
	Twitter: @unknownt

	Github:  http://github.com/fvdm/nodejs-tk102
	Version: 1.0.0
*/

// settings
var serverIP = '0.0.0.0';
var serverPort = 1337;
var maxConnections = 100;
var idleTimeout = 10;

// INIT
var net = require('net');
var server = net.createServer( function( socket ) {
	if( idleTimeout > 0 ) {
		socket.setTimeout( idleTimeout * 1000, function() {
			socket.end();
		});
	}
}).listen( serverPort, serverIP );

server.maxConnections = maxConnections;

// connect
server.on( 'connection', function( socket ) {
	socket.setEncoding( 'utf8' );

	// data
	socket.on( 'data', function( raw ) {
		var gps = tk102( raw );
		console.log( gps );
	});
});

function tk102( raw ) {
	// 1203292316,0031698765432,GPRMC,211657.000,A,5213.0247,N,00516.7757,E,0.00,273.30,290312,,,A*62,F,imei:123456789012345,123
	var raw = raw.replace( /(^[\s\t\r\n]+|[\s\t\r\n]+$)/, '' );
	var str = raw.split(',');
	var data = {};

	// only continue with correct input, else the server may quit...
	if( raw.indexOf(',GPRMC,') && str.length == 18 ) {

		// parse
		var datetime = str[0].replace( /([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, year, month, day, hour, minute ) {
			return '20'+ year +'-'+ month +'-'+ day +' '+ hour +':'+ minute
		});
		var gpsdate = str[11].replace( /([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, day, month, year ) {
			return '20'+ year +'-'+ month +'-'+ day;
		});
		var gpstime = str[3].replace( /([0-9]{2})([0-9]{2})([0-9]{2})\.([0-9]{3})/, function( match, hour, minute, second, ms ) {
			var hour = str[4] == 'V' ? hour + 12 : hour;
			return hour +':'+ minute +':'+ second +'.'+ ms;
		});

		data = {
			'raw':		raw,
			'datetime':	datetime,
			'phone':	str[1],
			'gps': {
				'date':		gpsdate,
				'time':		gpstime,
				'signal':	str[15]
			},
			'geo': {
				'latitude':	parseFloat( fixGeo( str[5], str[6] ) ),
				'longitude':	parseFloat( fixGeo( str[7], str[8] ) ),
				'heading':	parseInt( str[10] )
			},
			'kmh':		parseFloat( str[9] ),
			'imei':		str[16].replace( 'imei:', '' )
		};
	}

	// done
	return data;
}

// clean geo positions
function fixGeo( one, two ) {
	var one = (two == 'S' || two == 'W' ? '-' : '') + one;
	one = one / 100 +'';
	one = one.replace( /^([0-9]+)\.([0-9]+)$/, function( match, num, dec ) {
		return num +'.'+ dec.substr(0,6);
	});
	return one;
}
<commit_msg>Minor comment tweaks<commit_after>/*
	Xexun TK102 GPS server for Node.js

	Author:  Franklin van de Meent
	Website: http://frankl.in
	Contact: fr@nkl.in
	Twitter: @unknownt

	Source:  http://fvdm.github.com/nodejs-tk102
*/

// settings
var serverIP = '0.0.0.0';
var serverPort = 1337;
var maxConnections = 100;
var idleTimeout = 10;

// INIT
var net = require('net');
var server = net.createServer( function( socket ) {
	if( idleTimeout > 0 ) {
		socket.setTimeout( idleTimeout * 1000, function() {
			socket.end();
		});
	}
}).listen( serverPort, serverIP );

server.maxConnections = maxConnections;

// connect
server.on( 'connection', function( socket ) {
	socket.setEncoding( 'utf8' );

	// data
	socket.on( 'data', function( raw ) {
		var gps = tk102( raw );
		console.log( gps );
	});
});

function tk102( raw ) {
	// 1203292316,0031698765432,GPRMC,211657.000,A,5213.0247,N,00516.7757,E,0.00,273.30,290312,,,A*62,F,imei:123456789012345,123
	var raw = raw.replace( /(^[\s\t\r\n]+|[\s\t\r\n]+$)/, '' );
	var str = raw.split(',');
	var data = {};

	// only continue with correct input, else the server may quit...
	if( raw.indexOf(',GPRMC,') && str.length == 18 ) {

		// parse
		var datetime = str[0].replace( /([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, year, month, day, hour, minute ) {
			return '20'+ year +'-'+ month +'-'+ day +' '+ hour +':'+ minute
		});
		var gpsdate = str[11].replace( /([0-9]{2})([0-9]{2})([0-9]{2})/, function( match, day, month, year ) {
			return '20'+ year +'-'+ month +'-'+ day;
		});
		var gpstime = str[3].replace( /([0-9]{2})([0-9]{2})([0-9]{2})\.([0-9]{3})/, function( match, hour, minute, second, ms ) {
			var hour = str[4] == 'V' ? hour + 12 : hour;
			return hour +':'+ minute +':'+ second +'.'+ ms;
		});

		data = {
			'raw':		raw,
			'datetime':	datetime,
			'phone':	str[1],
			'gps': {
				'date':		gpsdate,
				'time':		gpstime,
				'signal':	str[15]
			},
			'geo': {
				'latitude':	parseFloat( fixGeo( str[5], str[6] ) ),
				'longitude':	parseFloat( fixGeo( str[7], str[8] ) ),
				'heading':	parseInt( str[10] )
			},
			'kmh':		parseFloat( str[9] ),
			'imei':		str[16].replace( 'imei:', '' )
		};
	}

	// done
	return data;
}

// clean geo positions
function fixGeo( one, two ) {
	var one = (two == 'S' || two == 'W' ? '-' : '') + one;
	one = one / 100 +'';
	one = one.replace( /^([0-9]+)\.([0-9]+)$/, function( match, num, dec ) {
		return num +'.'+ dec.substr(0,6);
	});
	return one;
}
<|endoftext|>


<commit_before>var colors = require('./color');
var picture = require('./picture');
var fonts = require('./font');
var hex = require('./utils').randomHex;
module.exports =
{
	generate: function (conf, next) {

		conf = conf || {};

		if (!conf.width) {
			conf.width = 100;
		}
		if (!conf.font) {
			conf.font = new fonts.Bariol(68);
		}

		if(!conf.color){
			conf.color = "#3214FF";
		}
		picture(conf).one(function (img) {
			next(img);
		});

	}
};<commit_msg>Fixing return object<commit_after>var colors = require('./color');
var picture = require('./picture');
var fonts = require('./font');
var hex = require('./utils').randomHex;
module.exports = function () {
	return {
		generate: function (conf, next) {

			conf = conf || {};

			if (!conf.width) {
				conf.width = 100;
			}
			if (!conf.font) {
				conf.font = new fonts.Bariol(68);
			}

			if (!conf.color) {
				conf.color = "#3214FF";
			}
			picture(conf).one(function (img) {
				next(img);
			});

		}
	}
};<|endoftext|>


<commit_before>'use strict'

var Trello = require('node-trello')
var Promise = require('bluebird')
var moment = require('moment')
var _ = require('lodash')

module.exports = function initializeModule (options) {
  var t = Promise.promisifyAll(new Trello(options.trelloKey, options.trelloToken))
  var dailyLabel = options.trelloLabel

  function findBoard (boardName) {
    return Promise.try(function () {
      return t.getAsync('/1/members/me')
    }).then(function (data) {
      return data.idBoards
    }).map(function (boardId) {
      return t.getAsync('/1/boards/' + boardId, {lists: 'all'})
    }).filter(function (board) {
      return board.name === boardName
    }).then(function (boards) {
      if (boardName === undefined) {
        throw new Error('boardName not set in ENV')
      } else if (boards.length === 0) {
        throw new Error('No results found.')
      } else {
        return boards[0]
      }
    }).catch(function (err) {
      console.log('Error finding board', err)
    })
  }

  function getOrCreateList (board, listName) {
    return Promise.filter(board.lists, function (list) {
      return list.name === listName
    }).filter(function (list) {
      return list.closed === false
    }).then(function (lists) {
      if (lists.length > 0) {
        return lists[0]
      } else {
        return createList({
          name: listName,
          board: board,
          position: 'top'
        })
      }
    }).catch(function (err) {
      console.log('Error in getOrCreateList', err)
    })
  }

  function createList (opts) {
    return Promise.try(function () {
      return t.postAsync('/1/lists', {
        name: opts.name,
        idBoard: opts.board,
        idListSource: opts.sourceList,
        position: opts.position
      })
    }).catch(function (err) {
      console.log('Error creating list', err)
    })
  }

  function moveCardPosition (opts) {
    return Promise.try(function () {
      return t.getAsync('/1/lists/' + opts.targetList, {cards: 'open'})
    }).then(function (result) {
      return result.cards
    }).filter(function (card) {
      return (opts.dailyOnly && _.includes(card.idLabels, opts.dailyLabel))
    }).map(function (card) {
      return Promise.try(function () {
        return t.putAsync('/1/cards/' + card.id, {pos: opts.pos})
      }).then(function () {
        console.log('Copied card: ' + card.name)
      })
    }).catch(function (err) {
      console.log('Error in moveCardPosition', err)
    })
  }

  function init (boardName, listName) {
    return Promise.try(function () {
      return findBoard(boardName)
    }).then(function (board) {
      return Promise.all([
        getOrCreateList(board, (listName ? listName : 'In')),
        getOrCreateList(board, 'Daily Processes')
      ]).spread(function (targetList, sourceList) {
        return {
          boardId: board.id,
          targetList: targetList.id,
          sourceList: sourceList.id
        }
      })
    }).catch(function (err) {
      console.log('Error initiating', err)
    })
  }

  function getOpenLists () {
    return Promise.try(function () {
      return findBoard(options.trelloBoard)
    }).then(function (board) {
      return Promise.filter(board.lists, function (list) {
        return list.closed === false
      })
    }).catch(function (err) {
      if (err) throw new Error('Unable to get lists')
    })
  }

  /* Print all open list names from the default baord */
  function getLists () {
    return Promise.try(function () {
      return getOpenLists()
    }).then(function (lists) {
        return lists.forEach(function (list) {
          console.log(list.name)
          return list.name
        })
      }).catch(function (err) {
        if (err) throw new Error('Could not list list names')
      })
  }

  /* Print out open cards from a given list */
  function listCards (listName) {
    return Promise.try(function () {
      return getOpenLists()
    }).filter(function (list) {
      return list.name === listName
    }).then(function (list) {
      return t.getAsync('/1/lists/' + list[0].id, {cards: 'open'})
    }).then(function (list) {
      return Promise.map(list.cards, function (card) {
        if (card.closed === false) {
          console.log(card.name)
        }
      })
    }).catch(function (err) {
      if (err) throw new Error('Could not find list')
    })
  }

  function createToday () {
    return Promise.try(function () {
      return init(options.trelloBoard, options.todayList)
    }).then(function (result) {
      Promise.try(function () {
        return createList({
          name: moment().format('MMMM Do, YYYY'),
          board: result.boardId,
          sourceList: result.sourceList,
          position: '3'
        })
      }).then(function (list) {
        return t.postAsync('/1/lists/' + list.id + '/moveAllCards', {
          idBoard: result.boardId,
          idList: result.targetList
        })
      }).then(function () {
        return moveCardPosition({
          targetList: result.targetList,
          dailyLabel: dailyLabel,
          dailyOnly: true,
          pos: 'top'
        })
      }).then(function () {
        return removeDuplicates(options.todayList)
      }).then(function () {
        console.log('Done')
      })
    }).catch(function (err) {
      console.log('Error in createToday', err)
    })
  }

  function createCard (cardText, list) {
    return Promise.try(function () {
      return init(options.trelloBoard, list)
    }).then(function (result) {
      return t.postAsync('/1/cards', {
        name: cardText,
        pos: 'top',
        due: null,
        idList: result.targetList,
        urlSource: null
      })
    }).then(function () {
      console.log('Created card:', cardText)
    }).catch(function (err) {
      console.log('Error creating card', err)
    })
  }

  function removeDuplicates (listName, dailyOnly) {
    return Promise.try(function () {
      return init(options.trelloBoard, listName || options.todayList)
    }).then(function (result) {
      if (listName == null) {
        return result.targetList
      } else {
        return Promise.try(function () {
          return getOpenLists()
        }).filter(function (result) {
          return listName === result.name
        }).then(function (result) {
          return result[0].id
        }).catch(function (err) {
          console.log('Unable to find ' + listName, err)
        })
      }
    }).then(function (result) {
      if (dailyOnly == null) {
        dailyOnly = true
      }

      return Promise.try(function () {
        return t.getAsync('/1/lists/' + result, {cards: 'open'})
      }).then(function (result) {
        return _.difference(result.cards, _.uniq(result.cards, 'name'))
      }).filter(function (card) {
        return (dailyOnly && _.includes(card.idLabels, dailyLabel))
      }).map(function (card) {
        return Promise.try(function () {
          return t.delAsync('/1/cards/' + card.id)
        }).then(function () {
          console.log('Deleted card: ' + card.name + ' (' + card.id + ')')
        })
      }).then(function (result) {
        console.log('Done deleting duplicates.')
      })
    }).catch(function (err) {
      console.log('Error removing duplicates', err)
    })
  }

  return {
    getLists: getLists,
    listCards: listCards,
    createCard: createCard,
    createToday: createToday,
    removeDuplicates: removeDuplicates
  }
}
<commit_msg>Removed hardcoded old list name<commit_after>'use strict'

var Trello = require('node-trello')
var Promise = require('bluebird')
var moment = require('moment')
var _ = require('lodash')

module.exports = function initializeModule (options) {
  var t = Promise.promisifyAll(new Trello(options.trelloKey, options.trelloToken))
  var dailyLabel = options.trelloLabel

  function findBoard (boardName) {
    return Promise.try(function () {
      return t.getAsync('/1/members/me')
    }).then(function (data) {
      return data.idBoards
    }).map(function (boardId) {
      return t.getAsync('/1/boards/' + boardId, {lists: 'all'})
    }).filter(function (board) {
      return board.name === boardName
    }).then(function (boards) {
      if (boardName === undefined) {
        throw new Error('boardName not set in ENV')
      } else if (boards.length === 0) {
        throw new Error('No results found.')
      } else {
        return boards[0]
      }
    }).catch(function (err) {
      console.log('Error finding board', err)
    })
  }

  function getOrCreateList (board, listName) {
    return Promise.filter(board.lists, function (list) {
      return list.name === listName
    }).filter(function (list) {
      return list.closed === false
    }).then(function (lists) {
      if (lists.length > 0) {
        return lists[0]
      } else {
        return createList({
          name: listName,
          board: board,
          position: 'top'
        })
      }
    }).catch(function (err) {
      console.log('Error in getOrCreateList', err)
    })
  }

  function createList (opts) {
    return Promise.try(function () {
      return t.postAsync('/1/lists', {
        name: opts.name,
        idBoard: opts.board,
        idListSource: opts.sourceList,
        position: opts.position
      })
    }).catch(function (err) {
      console.log('Error creating list', err)
    })
  }

  function moveCardPosition (opts) {
    return Promise.try(function () {
      return t.getAsync('/1/lists/' + opts.targetList, {cards: 'open'})
    }).then(function (result) {
      return result.cards
    }).filter(function (card) {
      return (opts.dailyOnly && _.includes(card.idLabels, opts.dailyLabel))
    }).map(function (card) {
      return Promise.try(function () {
        return t.putAsync('/1/cards/' + card.id, {pos: opts.pos})
      }).then(function () {
        console.log('Copied card: ' + card.name)
      })
    }).catch(function (err) {
      console.log('Error in moveCardPosition', err)
    })
  }

  function init (boardName, listName) {
    return Promise.try(function () {
      return findBoard(boardName)
    }).then(function (board) {
      return Promise.all([
        getOrCreateList(board, listName || options.todayList),
        getOrCreateList(board, 'Daily Processes')
      ]).spread(function (targetList, sourceList) {
        return {
          boardId: board.id,
          targetList: targetList.id,
          sourceList: sourceList.id
        }
      })
    }).catch(function (err) {
      console.log('Error initiating', err)
    })
  }

  function getOpenLists () {
    return Promise.try(function () {
      return findBoard(options.trelloBoard)
    }).then(function (board) {
      return Promise.filter(board.lists, function (list) {
        return list.closed === false
      })
    }).catch(function (err) {
      if (err) throw new Error('Unable to get lists')
    })
  }

  /* Print all open list names from the default baord */
  function getLists () {
    return Promise.try(function () {
      return getOpenLists()
    }).then(function (lists) {
        return lists.forEach(function (list) {
          console.log(list.name)
          return list.name
        })
      }).catch(function (err) {
        if (err) throw new Error('Could not list list names')
      })
  }

  /* Print out open cards from a given list */
  function listCards (listName) {
    return Promise.try(function () {
      return getOpenLists()
    }).filter(function (list) {
      return list.name === listName
    }).then(function (list) {
      return t.getAsync('/1/lists/' + list[0].id, {cards: 'open'})
    }).then(function (list) {
      return Promise.map(list.cards, function (card) {
        if (card.closed === false) {
          console.log(card.name)
        }
      })
    }).catch(function (err) {
      if (err) throw new Error('Could not find list')
    })
  }

  function createToday () {
    return Promise.try(function () {
      return init(options.trelloBoard, options.todayList)
    }).then(function (result) {
      Promise.try(function () {
        return createList({
          name: moment().format('MMMM Do, YYYY'),
          board: result.boardId,
          sourceList: result.sourceList,
          position: '3'
        })
      }).then(function (list) {
        return t.postAsync('/1/lists/' + list.id + '/moveAllCards', {
          idBoard: result.boardId,
          idList: result.targetList
        })
      }).then(function () {
        return moveCardPosition({
          targetList: result.targetList,
          dailyLabel: dailyLabel,
          dailyOnly: true,
          pos: 'top'
        })
      }).then(function () {
        return removeDuplicates(options.todayList)
      }).then(function () {
        console.log('Done')
      })
    }).catch(function (err) {
      console.log('Error in createToday', err)
    })
  }

  function createCard (cardText, list) {
    return Promise.try(function () {
      return init(options.trelloBoard, list)
    }).then(function (result) {
      return t.postAsync('/1/cards', {
        name: cardText,
        pos: 'top',
        due: null,
        idList: result.targetList,
        urlSource: null
      })
    }).then(function () {
      console.log('Created card:', cardText)
    }).catch(function (err) {
      console.log('Error creating card', err)
    })
  }

  function removeDuplicates (listName, dailyOnly) {
    return Promise.try(function () {
      return init(options.trelloBoard, listName || options.todayList)
    }).then(function (result) {
      if (listName == null) {
        return result.targetList
      } else {
        return Promise.try(function () {
          return getOpenLists()
        }).filter(function (result) {
          return listName === result.name
        }).then(function (result) {
          return result[0].id
        }).catch(function (err) {
          console.log('Unable to find ' + listName, err)
        })
      }
    }).then(function (result) {
      if (dailyOnly == null) {
        dailyOnly = true
      }

      return Promise.try(function () {
        return t.getAsync('/1/lists/' + result, {cards: 'open'})
      }).then(function (result) {
        return _.difference(result.cards, _.uniq(result.cards, 'name'))
      }).filter(function (card) {
        return (dailyOnly && _.includes(card.idLabels, dailyLabel))
      }).map(function (card) {
        return Promise.try(function () {
          return t.delAsync('/1/cards/' + card.id)
        }).then(function () {
          console.log('Deleted card: ' + card.name + ' (' + card.id + ')')
        })
      }).then(function (result) {
        console.log('Done deleting duplicates.')
      })
    }).catch(function (err) {
      console.log('Error removing duplicates', err)
    })
  }

  return {
    getLists: getLists,
    listCards: listCards,
    createCard: createCard,
    createToday: createToday,
    removeDuplicates: removeDuplicates
  }
}
<|endoftext|>