<commit_before>angular.module("umbraco").controller("Our.Umbraco.DocTypeGridEditor.GridEditors.DocTypeGridEditor", [

    "$scope",
    "$rootScope",
    "$timeout",
    "$routeParams",
    "editorState",
    'assetsService',
    "Our.Umbraco.DocTypeGridEditor.Services.DocTypeDialogService",
    "Our.Umbraco.DocTypeGridEditor.Resources.DocTypeGridEditorResources",

    function ($scope, $rootScope, $timeout, $routeParams, editorState, assetsService, dtgeDialogService, dtgeResources) {

        $scope.title = "Click to insert item";
        $scope.icon = "icon-item-arrangement";

        $scope.setValue = function (data, callback) {
            $scope.control.value = data;
            if (!("id" in $scope.control.value) || $scope.control.value.id == "") {
                $scope.control.value.id = guid();
            }
            if ("name" in $scope.control.value.value && $scope.control.value.value.name) {
                $scope.title = $scope.control.value.value.name;
            }
            if ("dtgeContentTypeAlias" in $scope.control.value && $scope.control.value.dtgeContentTypeAlias) {
                dtgeResources.getContentTypeIcon($scope.control.value.dtgeContentTypeAlias).then(function (data2) {
                    if (data2.icon) {
                        $scope.icon = data2.icon;
                    }
                });
            }
            if (callback)
                callback();
        };

        $scope.setDocType = function () {
            dtgeDialogService.open({
                editorName: $scope.control.editor.name,
                allowedDocTypes: $scope.control.editor.config.allowedDocTypes || [],
                nameTemplate: $scope.control.editor.config.nameTemplate,
                dialogData: {
                    docTypeAlias: $scope.control.value.dtgeContentTypeAlias,
                    value: $scope.control.value.value
                },
                callback: function (data) {
                    $scope.setValue({
                        dtgeContentTypeAlias: data.docTypeAlias,
                        value: data.value
                    });
                    $scope.setPreview($scope.control.value);
                }
            });
        };

        $scope.setPreview = function (model) {
            if ("enablePreview" in $scope.control.editor.config && $scope.control.editor.config.enablePreview) {
                dtgeResources.getEditorMarkupForDocTypePartial(editorState.current.id, model.id,
                    $scope.control.editor.alias, model.dtgeContentTypeAlias, model.value,
                    $scope.control.editor.config.viewPath,
                    $scope.control.editor.config.previewViewPath,
                    editorState.current.published)
                    .success(function(htmlResult) {
                        if (htmlResult.trim().length > 0) {
                            $scope.preview = htmlResult;
                        }
                    });
            }
        };

        function init() {
            $timeout(function () {
                if ($scope.control.$initializing) {
                    $scope.setDocType();
                } else if ($scope.control.value) {
                    $scope.setPreview($scope.control.value);
                }
            }, 200);
        }

        if ($scope.control.value) {
            if (!$scope.control.value.dtgeContentTypeAlias && $scope.control.value.docType) {
                $scope.control.value.dtgeContentTypeAlias = $scope.control.value.docType;
            }
            if ($scope.control.value.docType) {
                delete $scope.control.value.docType;
            }
            if (isGuid($scope.control.value.dtgeContentTypeAlias)) {
                dtgeResources.getContentTypeAliasByGuid($scope.control.value.dtgeContentTypeAlias).then(function(data1) {
                    $scope.control.value.dtgeContentTypeAlias = data1.alias;
                    $scope.setValue($scope.control.value, init);
                });
            } else {
                $scope.setValue($scope.control.value, init);
            }
        } else {
            $scope.setValue({
                id: guid(),
                dtgeContentTypeAlias: "",
                value: {}
            }, init);
        }

        // Load preview css / js files
        if ("enablePreview" in $scope.control.editor.config && $scope.control.editor.config.enablePreview)
        {
            if ("previewCssFilePath" in $scope.control.editor.config && $scope.control.editor.config.previewCssFilePath) {
                assetsService.loadCss($scope.control.editor.config.previewCssFilePath, $scope);
            };

            if ("previewJsFilePath" in $scope.control.editor.config && $scope.control.editor.config.previewJsFilePath) {
                assetsService.loadJs($scope.control.editor.config.previewJsFilePath, $scope);
            }
        }

        function guid() {
            function s4() {
                return Math.floor((1 + Math.random()) * 0x10000)
                  .toString(16)
                  .substring(1);
            }
            return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
              s4() + '-' + s4() + s4() + s4();
        }

        function isGuid(input) {
            return new RegExp("^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$", "i").test(input.toString());
        }

    }
]);

angular.module("umbraco").controller("Our.Umbraco.DocTypeGridEditor.Dialogs.DocTypeGridEditorDialog",
    [
        "$scope",
        "$interpolate",
        "formHelper",
        "contentResource",
        "Our.Umbraco.DocTypeGridEditor.Resources.DocTypeGridEditorResources",

        function ($scope, $interpolate, formHelper, contentResource, dtgeResources) {

            $scope.dialogOptions = $scope.$parent.dialogOptions;

            $scope.docTypes = [];
            $scope.dialogMode = "selectDocType";
            $scope.selectedDocType = null;
            $scope.node = null;

            var nameExp = !!$scope.dialogOptions.nameTemplate
                ? $interpolate($scope.dialogOptions.nameTemplate)
                : undefined;

            $scope.selectDocType = function () {
                $scope.dialogMode = "edit";
                $scope.dialogData.docTypeAlias = $scope.selectedDocType.alias;
                loadNode();
            };

            $scope.save = function () {

                // Cause form submitting
                if (formHelper.submitForm({ scope: $scope, formCtrl: $scope.dtgeForm })) {

                    // Copy property values to scope model value
                    if ($scope.node) {
                        var value = {
                            name: $scope.dialogOptions.editorName
                        };

                        for (var t = 0; t < $scope.node.tabs.length; t++) {
                            var tab = $scope.node.tabs[t];
                            for (var p = 0; p < tab.properties.length; p++) {
                                var prop = tab.properties[p];
                                if (typeof prop.value !== "function") {
                                    value[prop.alias] = prop.value;
                                }
                            }
                        }

                        if (nameExp) {
                            var newName = nameExp(value); // Run it against the stored dictionary value, NOT the node object
                            if (newName && (newName = $.trim(newName))) {
                                value.name = newName;
                            }
                        }

                        $scope.dialogData.value = value;
                    } else {
                        $scope.dialogData.value = null;
                    }

                    $scope.submit($scope.dialogData);

                }
            };

            function loadNode() {
                contentResource.getScaffold(-20, $scope.dialogData.docTypeAlias).then(function (data) {
                    // Remove the last tab
                    data.tabs.pop();

                    // Merge current value
                    if ($scope.dialogData.value) {
                        for (var t = 0; t < data.tabs.length; t++) {
                            var tab = data.tabs[t];
                            for (var p = 0; p < tab.properties.length; p++) {
                                var prop = tab.properties[p];
                                console.log(prop.alias);
                                if ($scope.dialogData.value[prop.alias]) {
                                    prop.value = $scope.dialogData.value[prop.alias];
                                }
                            }
                        }
                    };

                    // Assign the model to scope
                    $scope.nodeContext = $scope.node = data;
                });
            }

            if ($scope.dialogData.docTypeAlias) {
                $scope.dialogMode = "edit";
                loadNode();
            } else {
                $scope.dialogMode = "selectDocType";
                // No data type, so load a list to choose from
                dtgeResources.getContentTypes($scope.dialogOptions.allowedDocTypes).then(function (docTypes) {
                    $scope.docTypes = docTypes;
                    if ($scope.docTypes.length == 1) {
                        $scope.dialogData.docTypeAlias = $scope.docTypes[0].alias;
                        $scope.dialogMode = "edit";
                        loadNode();
                    }
                });
            }

        }

    ]);<commit_msg>Added a fix for issue #18 If the current node isn't published, the preview is run in the context of the homepage, but the nodeId is appended onto the querystring, so if you did need some contextual information from the node, you should be able to work it out<commit_after>angular.module("umbraco").controller("Our.Umbraco.DocTypeGridEditor.GridEditors.DocTypeGridEditor", [

    "$scope",
    "$rootScope",
    "$timeout",
    "$routeParams",
    "editorState",
    'assetsService',
    "Our.Umbraco.DocTypeGridEditor.Services.DocTypeDialogService",
    "Our.Umbraco.DocTypeGridEditor.Resources.DocTypeGridEditorResources",

    function ($scope, $rootScope, $timeout, $routeParams, editorState, assetsService, dtgeDialogService, dtgeResources) {

        $scope.title = "Click to insert item";
        $scope.icon = "icon-item-arrangement";

        $scope.setValue = function (data, callback) {
            $scope.control.value = data;
            if (!("id" in $scope.control.value) || $scope.control.value.id == "") {
                $scope.control.value.id = guid();
            }
            if ("name" in $scope.control.value.value && $scope.control.value.value.name) {
                $scope.title = $scope.control.value.value.name;
            }
            if ("dtgeContentTypeAlias" in $scope.control.value && $scope.control.value.dtgeContentTypeAlias) {
                dtgeResources.getContentTypeIcon($scope.control.value.dtgeContentTypeAlias).then(function (data2) {
                    if (data2.icon) {
                        $scope.icon = data2.icon;
                    }
                });
            }
            if (callback)
                callback();
        };

        $scope.setDocType = function () {
            dtgeDialogService.open({
                editorName: $scope.control.editor.name,
                allowedDocTypes: $scope.control.editor.config.allowedDocTypes || [],
                nameTemplate: $scope.control.editor.config.nameTemplate,
                dialogData: {
                    docTypeAlias: $scope.control.value.dtgeContentTypeAlias,
                    value: $scope.control.value.value
                },
                callback: function (data) {
                    $scope.setValue({
                        dtgeContentTypeAlias: data.docTypeAlias,
                        value: data.value
                    });
                    $scope.setPreview($scope.control.value);
                }
            });
        };

        $scope.setPreview = function (model) {
            if ("enablePreview" in $scope.control.editor.config && $scope.control.editor.config.enablePreview) {
                console.log(editorState.current);
                dtgeResources.getEditorMarkupForDocTypePartial(editorState.current.id, model.id,
                    $scope.control.editor.alias, model.dtgeContentTypeAlias, model.value,
                    $scope.control.editor.config.viewPath,
                    $scope.control.editor.config.previewViewPath,
                    !!editorState.current.publishDate)
                    .success(function(htmlResult) {
                        if (htmlResult.trim().length > 0) {
                            $scope.preview = htmlResult;
                        }
                    });
            }
        };

        function init() {
            $timeout(function () {
                if ($scope.control.$initializing) {
                    $scope.setDocType();
                } else if ($scope.control.value) {
                    $scope.setPreview($scope.control.value);
                }
            }, 200);
        }

        if ($scope.control.value) {
            if (!$scope.control.value.dtgeContentTypeAlias && $scope.control.value.docType) {
                $scope.control.value.dtgeContentTypeAlias = $scope.control.value.docType;
            }
            if ($scope.control.value.docType) {
                delete $scope.control.value.docType;
            }
            if (isGuid($scope.control.value.dtgeContentTypeAlias)) {
                dtgeResources.getContentTypeAliasByGuid($scope.control.value.dtgeContentTypeAlias).then(function(data1) {
                    $scope.control.value.dtgeContentTypeAlias = data1.alias;
                    $scope.setValue($scope.control.value, init);
                });
            } else {
                $scope.setValue($scope.control.value, init);
            }
        } else {
            $scope.setValue({
                id: guid(),
                dtgeContentTypeAlias: "",
                value: {}
            }, init);
        }

        // Load preview css / js files
        if ("enablePreview" in $scope.control.editor.config && $scope.control.editor.config.enablePreview)
        {
            if ("previewCssFilePath" in $scope.control.editor.config && $scope.control.editor.config.previewCssFilePath) {
                assetsService.loadCss($scope.control.editor.config.previewCssFilePath, $scope);
            };

            if ("previewJsFilePath" in $scope.control.editor.config && $scope.control.editor.config.previewJsFilePath) {
                assetsService.loadJs($scope.control.editor.config.previewJsFilePath, $scope);
            }
        }

        function guid() {
            function s4() {
                return Math.floor((1 + Math.random()) * 0x10000)
                  .toString(16)
                  .substring(1);
            }
            return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
              s4() + '-' + s4() + s4() + s4();
        }

        function isGuid(input) {
            return new RegExp("^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$", "i").test(input.toString());
        }

    }
]);

angular.module("umbraco").controller("Our.Umbraco.DocTypeGridEditor.Dialogs.DocTypeGridEditorDialog",
    [
        "$scope",
        "$interpolate",
        "formHelper",
        "contentResource",
        "Our.Umbraco.DocTypeGridEditor.Resources.DocTypeGridEditorResources",

        function ($scope, $interpolate, formHelper, contentResource, dtgeResources) {

            $scope.dialogOptions = $scope.$parent.dialogOptions;

            $scope.docTypes = [];
            $scope.dialogMode = "selectDocType";
            $scope.selectedDocType = null;
            $scope.node = null;

            var nameExp = !!$scope.dialogOptions.nameTemplate
                ? $interpolate($scope.dialogOptions.nameTemplate)
                : undefined;

            $scope.selectDocType = function () {
                $scope.dialogMode = "edit";
                $scope.dialogData.docTypeAlias = $scope.selectedDocType.alias;
                loadNode();
            };

            $scope.save = function () {

                // Cause form submitting
                if (formHelper.submitForm({ scope: $scope, formCtrl: $scope.dtgeForm })) {

                    // Copy property values to scope model value
                    if ($scope.node) {
                        var value = {
                            name: $scope.dialogOptions.editorName
                        };

                        for (var t = 0; t < $scope.node.tabs.length; t++) {
                            var tab = $scope.node.tabs[t];
                            for (var p = 0; p < tab.properties.length; p++) {
                                var prop = tab.properties[p];
                                if (typeof prop.value !== "function") {
                                    value[prop.alias] = prop.value;
                                }
                            }
                        }

                        if (nameExp) {
                            var newName = nameExp(value); // Run it against the stored dictionary value, NOT the node object
                            if (newName && (newName = $.trim(newName))) {
                                value.name = newName;
                            }
                        }

                        $scope.dialogData.value = value;
                    } else {
                        $scope.dialogData.value = null;
                    }

                    $scope.submit($scope.dialogData);

                }
            };

            function loadNode() {
                contentResource.getScaffold(-20, $scope.dialogData.docTypeAlias).then(function (data) {
                    // Remove the last tab
                    data.tabs.pop();

                    // Merge current value
                    if ($scope.dialogData.value) {
                        for (var t = 0; t < data.tabs.length; t++) {
                            var tab = data.tabs[t];
                            for (var p = 0; p < tab.properties.length; p++) {
                                var prop = tab.properties[p];
                                console.log(prop.alias);
                                if ($scope.dialogData.value[prop.alias]) {
                                    prop.value = $scope.dialogData.value[prop.alias];
                                }
                            }
                        }
                    };

                    // Assign the model to scope
                    $scope.nodeContext = $scope.node = data;
                });
            }

            if ($scope.dialogData.docTypeAlias) {
                $scope.dialogMode = "edit";
                loadNode();
            } else {
                $scope.dialogMode = "selectDocType";
                // No data type, so load a list to choose from
                dtgeResources.getContentTypes($scope.dialogOptions.allowedDocTypes).then(function (docTypes) {
                    $scope.docTypes = docTypes;
                    if ($scope.docTypes.length == 1) {
                        $scope.dialogData.docTypeAlias = $scope.docTypes[0].alias;
                        $scope.dialogMode = "edit";
                        loadNode();
                    }
                });
            }

        }

    ]);<|endoftext|>


<commit_before>angular.module('MyModule')
    .controller('phasercollisioncontroller', function ($scope, $window, $timeout, UtilityService) {
        'use strict';
        $scope.windowWidth = function () {
            return $window.innerWidth;
        };

        $scope.$on('$locationChangeStart', function (event, next, current) {
            game.destroy();
            angular.element(document.querySelectorAll('canvas')).remove();
        });

        var game = new $window.Phaser.Game(600, 600, $window.Phaser.AUTO, 'container', { preload: preload, create: create, update: update });
        var fpsText;
        var avgFpsText;
        var ballCountText;
        var avgFps = 0;
        var ballCount = 0;
        var circles;
        var circleCollisionGroup;
        var fpsToggle = false;
        var colorSwapToggle = false;
        var whiteToggle = false;
        var mainCircle1;
        var mainCircle2;

        function preload() {
            game.load.image('agent', 'assets/circle.png');
        }

        function create() {
            game.input.keyboard.onDownCallback = function(e) {
                // 'F' key pressed
                if (e.keyCode == 70) {
                    fpsToggle = !fpsToggle;
                // 'C' key pressed
                } else if (e.keyCode == 67) {
                    colorSwapToggle = !colorSwapToggle;
                // 'W' key pressed
                } else if (e.keyCode == 87) {
                    whiteToggle = !whiteToggle;
                }
            };

            game.input.touch.onTouchEnd = function(e) {
                fpsToggle = !fpsToggle;
            };

            game.time.advancedTiming = true;
            game.physics.startSystem(Phaser.Physics.P2JS);
            game.physics.p2.restitution = 0.0;

            circleCollisionGroup = game.physics.p2.createCollisionGroup();
            game.physics.p2.updateBoundsCollisionGroup();

            circles = game.add.group();
            circles.enableBody = true;
            circles.physicsBodyType = Phaser.Physics.P2JS;

            mainCircle1 = createMainCircle(0, 0);
            mainCircle2 = createMainCircle(game.world.width, game.world.height);

            fpsText = game.add.text(16, 14, 'FPS: 0', { font: 'bold 14px Arial', fill: '#ff0000' });
            avgFpsText = game.add.text(16, 28, 'AVG FPS: 0', { font: 'bold 14px Arial', fill: '#ff0000' });
            ballCountText = game.add.text(16, 42, 'BALL COUNT: 0', { font: 'bold 14px Arial', fill: '#ff0000' });
        }

        function circleContact(a, b, c, d) {
            if (whiteToggle && b.collisionGroup == c.collisionGroup) {
                d[0].bodyA.parent.sprite.tint = 0xffffff;
            }
            else if (colorSwapToggle && b.collisionGroup == c.collisionGroup &&
                     (d[0].bodyA.id != mainCircle1.body.id &&
                      d[0].bodyB.id != mainCircle1.body.id &&
                      d[0].bodyA.id != mainCircle2.body.id &&
                      d[0].bodyB.id != mainCircle2.body.id )) {
                var v1 = new Vec2(d[0].bodyA.velocity[0], d[0].bodyA.velocity[1]);
                var v2 = new Vec2(d[0].bodyB.velocity[0], d[0].bodyB.velocity[1]);
                var len1 = vMath.length(v1);
                var len2 = vMath.length(v2);
                if (len1 > len2 && len1 > 6) {
                    d[0].bodyB.parent.sprite.tint = d[0].bodyA.parent.sprite.tint;
                } else if (len2 > len1 && len2 > 6) {
                    d[0].bodyA.parent.sprite.tint = d[0].bodyB.parent.sprite.tint;
                }
            }
        }

        function createMainCircle(x, y) {
            var circle;
            ballCount++;
            circle = circles.create(x, y, 'agent');
            circle.width = 100;
            circle.height = 100;
            circle.body.setCircle(50,0,0,0);
            circle.body.mass = 5000;
            circle.tint = 0xffffff;

            circle.body.setCollisionGroup(circleCollisionGroup);
            circle.body.collides(circleCollisionGroup);
            circle.body.angle = UtilityService.randomInt(0,359);

            return circle;
        }

        function accelerateSlow(circle) {
            if (circle.body.velocity.x > -2.0 &&
                circle.body.velocity.x < 2.0 &&
                circle.body.velocity.y > -2.0 &&
                circle.body.velocity.y < 2.0) {
                circle.body.angle = UtilityService.randomInt(0,359);
                circle.body.moveForward(UtilityService.randomInt(200,500));
            }
        }

        function createCircle() {
            ballCount++;
            var radius = UtilityService.randomInt(6,8);
            var circle;

            var corner = UtilityService.randomInt(1,4);
            switch(corner)
            {
                case 1:
                  circle = circles.create(0, 0, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0x0000ff;
                  break;
                case 2:
                  circle = circles.create(0, game.world.height, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0xff00ff;
                  break;
                case 3:
                  circle = circles.create(game.world.width, game.world.height, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0xffff00;
                  break;
                default:
                  circle = circles.create(game.world.width, 0, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0xff0000;
            }

            circle.width = radius * 2;
            circle.height = circle.width;
            circle.body.setCircle(radius,0,0,0);

            circle.body.onBeginContact.add(circleContact, this);

            circle.body.setCollisionGroup(circleCollisionGroup);
            circle.body.collides(circleCollisionGroup);
            circle.body.angle = UtilityService.randomInt(0,359);
            circle.body.mass = radius;
        }

        function destroyCircle() {
            var circle;

            for (var i = 2; i < circles.children.length; i++) {
                circle = circles.children[i];
                if (!circle.body) {
                    continue;
                }

                var left = circles.children[i].x - circles.children[i].width / 2;
                var top = circles.children[i].y - circles.children[i].width / 2;
                var right = circles.children[i].x + circles.children[i].width / 2;
                var bot = circles.children[i].y + circles.children[i].width / 2;

                if (left <= 0) {
                    break;
                } else if (right >= game.world.width) {
                    break;
                } else if (top <= 0) {
                    break;
                } else if (bot >= game.world.height) {
                    break;
                }

                circle = null;
            }

            if (circle && circle.body && circle.body.id != mainCircle1.body.id && circle.body.id != mainCircle2.body.id) {
                circle.body.destroy();
                circle.body = null;
                //circle.destroy();
                ballCount--;
            }
        }

        var frameCount = 0;
        var totFps = 0;
        function update() {
            if (frameCount > 180) {
                frameCount = 0;
                totFps = 0;
            }

            frameCount++;
            totFps += game.time.fps;
            avgFps = totFps / frameCount;

            if (fpsToggle) {
                fpsText.text = 'FPS: ' + game.time.fps;
                avgFpsText.text = 'AVG FPS: ' + Math.round(avgFps);
                ballCountText.text = 'BALL COUNT: ' + ballCount;
            } else {
                fpsText.text = '';
                avgFpsText.text = '';
                ballCountText.text = '';
            }

            if ((avgFps >= 60 && game.time.fps >= 60 && ballCount < 1400) || ballCount < 20) {
                createCircle();
            }

            if (avgFps <= 55 && game.time.fps <= 55 && ballCount > 100) {
                destroyCircle();
            }

            accelerateSlow(mainCircle1);
            accelerateSlow(mainCircle2);
        }

        function init() {
            $scope.pageName = "Phaser.js Collisions";
            var v1 = {};
            var radius = {};
            var startPos = {};
            var i = 0;
        }

        init();
    });<commit_msg>Destroy circles on the edges.<commit_after>angular.module('MyModule')
    .controller('phasercollisioncontroller', function ($scope, $window, $timeout, UtilityService) {
        'use strict';
        $scope.windowWidth = function () {
            return $window.innerWidth;
        };

        $scope.$on('$locationChangeStart', function (event, next, current) {
            game.destroy();
            angular.element(document.querySelectorAll('canvas')).remove();
        });

        var game = new $window.Phaser.Game(600, 600, $window.Phaser.AUTO, 'container', { preload: preload, create: create, update: update });
        var fpsText;
        var avgFpsText;
        var ballCountText;
        var avgFps = 0;
        var ballCount = 0;
        var circles;
        var circleCollisionGroup;
        var fpsToggle = false;
        var colorSwapToggle = false;
        var whiteToggle = false;
        var mainCircle1;
        var mainCircle2;

        function preload() {
            game.load.image('agent', 'assets/circle.png');
        }

        function create() {
            game.input.keyboard.onDownCallback = function(e) {
                // 'F' key pressed
                if (e.keyCode == 70) {
                    fpsToggle = !fpsToggle;
                // 'C' key pressed
                } else if (e.keyCode == 67) {
                    colorSwapToggle = !colorSwapToggle;
                // 'W' key pressed
                } else if (e.keyCode == 87) {
                    whiteToggle = !whiteToggle;
                }
            };

            game.input.touch.onTouchEnd = function(e) {
                fpsToggle = !fpsToggle;
            };

            game.time.advancedTiming = true;
            game.physics.startSystem(Phaser.Physics.P2JS);
            game.physics.p2.restitution = 0.0;

            circleCollisionGroup = game.physics.p2.createCollisionGroup();
            game.physics.p2.updateBoundsCollisionGroup();

            circles = game.add.group();
            circles.enableBody = true;
            circles.physicsBodyType = Phaser.Physics.P2JS;

            mainCircle1 = createMainCircle(0, 0);
            mainCircle2 = createMainCircle(game.world.width, game.world.height);

            fpsText = game.add.text(16, 14, 'FPS: 0', { font: 'bold 14px Arial', fill: '#ff0000' });
            avgFpsText = game.add.text(16, 28, 'AVG FPS: 0', { font: 'bold 14px Arial', fill: '#ff0000' });
            ballCountText = game.add.text(16, 42, 'BALL COUNT: 0', { font: 'bold 14px Arial', fill: '#ff0000' });
        }

        function circleContact(a, b, c, d) {
            if (whiteToggle && b.collisionGroup == c.collisionGroup) {
                d[0].bodyA.parent.sprite.tint = 0xffffff;
            }
            else if (colorSwapToggle && b.collisionGroup == c.collisionGroup &&
                     (d[0].bodyA.id != mainCircle1.body.id &&
                      d[0].bodyB.id != mainCircle1.body.id &&
                      d[0].bodyA.id != mainCircle2.body.id &&
                      d[0].bodyB.id != mainCircle2.body.id )) {
                var v1 = new Vec2(d[0].bodyA.velocity[0], d[0].bodyA.velocity[1]);
                var v2 = new Vec2(d[0].bodyB.velocity[0], d[0].bodyB.velocity[1]);
                var len1 = vMath.length(v1);
                var len2 = vMath.length(v2);
                if (len1 > len2 && len1 > 6) {
                    d[0].bodyB.parent.sprite.tint = d[0].bodyA.parent.sprite.tint;
                } else if (len2 > len1 && len2 > 6) {
                    d[0].bodyA.parent.sprite.tint = d[0].bodyB.parent.sprite.tint;
                }
            }
        }

        function createMainCircle(x, y) {
            var circle;
            ballCount++;
            circle = circles.create(x, y, 'agent');
            circle.width = 100;
            circle.height = 100;
            circle.body.setCircle(50,0,0,0);
            circle.body.mass = 5000;
            circle.tint = 0xffffff;

            circle.body.setCollisionGroup(circleCollisionGroup);
            circle.body.collides(circleCollisionGroup);
            circle.body.angle = UtilityService.randomInt(0,359);

            return circle;
        }

        function accelerateSlow(circle) {
            if (circle.body.velocity.x > -2.0 &&
                circle.body.velocity.x < 2.0 &&
                circle.body.velocity.y > -2.0 &&
                circle.body.velocity.y < 2.0) {
                circle.body.angle = UtilityService.randomInt(0,359);
                circle.body.moveForward(UtilityService.randomInt(200,500));
            }
        }

        function createCircle() {
            ballCount++;
            var radius = UtilityService.randomInt(6,8);
            var circle;

            var corner = UtilityService.randomInt(1,4);
            switch(corner)
            {
                case 1:
                  circle = circles.create(0, 0, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0x0000ff;
                  break;
                case 2:
                  circle = circles.create(0, game.world.height, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0xff00ff;
                  break;
                case 3:
                  circle = circles.create(game.world.width, game.world.height, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0xffff00;
                  break;
                default:
                  circle = circles.create(game.world.width, 0, 'agent');
                  circle.tint = whiteToggle ? 0xffffff : 0xff0000;
            }

            circle.width = radius * 2;
            circle.height = circle.width;
            circle.body.setCircle(radius,0,0,0);

            circle.body.onBeginContact.add(circleContact, this);

            circle.body.setCollisionGroup(circleCollisionGroup);
            circle.body.collides(circleCollisionGroup);
            circle.body.angle = UtilityService.randomInt(0,359);
            circle.body.mass = radius;
        }

        function destroyCircle() {
            var circle;

            for (var i = 2; i < circles.children.length; i++) {
                circle = circles.children[i];
                if (!circle.body) {
                    continue;
                }

                var left = circles.children[i].x - circles.children[i].width / 2;
                var top = circles.children[i].y - circles.children[i].width / 2;
                var right = circles.children[i].x + circles.children[i].width / 2;
                var bot = circles.children[i].y + circles.children[i].width / 2;

                if (left <= 0) {
                    break;
                } else if (right >= game.world.width) {
                    break;
                } else if (top <= 0) {
                    break;
                } else if (bot >= game.world.height) {
                    break;
                }

                circle = null;
            }

            if (circle && circle.body && circle.body.id != mainCircle1.body.id && circle.body.id != mainCircle2.body.id) {
                circle.body.destroy();
                circle.body = null;
                circle.destroy();
                ballCount--;
            }
        }

        var frameCount = 0;
        var totFps = 0;
        function update() {
            if (frameCount > 180) {
                frameCount = 0;
                totFps = 0;
            }

            frameCount++;
            totFps += game.time.fps;
            avgFps = totFps / frameCount;

            if (fpsToggle) {
                fpsText.text = 'FPS: ' + game.time.fps;
                avgFpsText.text = 'AVG FPS: ' + Math.round(avgFps);
                ballCountText.text = 'BALL COUNT: ' + ballCount;
            } else {
                fpsText.text = '';
                avgFpsText.text = '';
                ballCountText.text = '';
            }

            if ((avgFps >= 60 && game.time.fps >= 60 && ballCount < 1400) || ballCount < 20) {
                createCircle();
            }

            if (avgFps <= 55 && game.time.fps <= 55 && ballCount > 100) {
                destroyCircle();
            }

            accelerateSlow(mainCircle1);
            accelerateSlow(mainCircle2);
        }

        function init() {
            $scope.pageName = "Phaser.js Collisions";
            var v1 = {};
            var radius = {};
            var startPos = {};
            var i = 0;
        }

        init();
    });<|endoftext|>


<commit_before>import { viewWidth, viewHeight } from 'dom';
import { uiElements } from 'ui';
import Movie from 'movie';
// import Song from 'audio';
// import autumn from 'songs/autumn';
import endingMovie from 'movies/ending';

// const bgMusic = new Song(autumn);

export default {
  init: ()=> {
    // bgMusic.play(`repeat`);
    uiElements.push(Movie(0, 0, viewWidth, viewHeight, endingMovie));
  },
  dismiss: ()=> {}
};
<commit_msg>Ending fix.<commit_after>import { viewWidth, viewHeight } from 'dom';
import { uiElements } from 'ui';
import state from 'state';
import Movie from 'movie';
// import Song from 'audio';
// import autumn from 'songs/autumn';
import endingMovie from 'movies/ending';

// const bgMusic = new Song(autumn);

export default {
  init: ()=> {
    // bgMusic.play(`repeat`);
    state.logic = null;
    uiElements.push(Movie(0, 0, viewWidth, viewHeight, endingMovie));
  },
  dismiss: ()=> {}
};
<|endoftext|>


<commit_before>export default class EventEmitter {
  constructor() {
    this._listeners = {};
    this._maxListeners = 10;
  }

  addListener(event, listener) {
    this._listeners[event] = this._listeners[event] || [];
    this._listeners[event].push(listener);

    return this._checkMaxListeners(event);
  }

  emit(event, ...args) {
    if (!this._listeners[event]) {
      return this;
    }

    this._listeners[event].forEach((listener) => {
      listener(...args);
    });

    return this;
  }

  eventNames() {
    return Object.keys(this._listeners);
  }

  getMaxListeners() {
    return this._maxListeners;
  }

  listenerCount(event) {
    if (!this._listeners[event]) {
      return 0;
    }

    return this._listeners[event].length;
  }

  listeners(event) {
    return this._listeners[event];
  }

  on(event, listener) {
    return this.addListener(event, listener);
  }

  once(event, listener) {
    return this.addListener(event, (...args) => {
      this.removeListener(event, listener);
      listener(...args);
    });
  }

  prependListener(event, listener) {
    this._listeners[event] = this._listeners[event] || [];
    this._listeners[event].unshift(listener);

    return this._checkMaxListeners(event);
  }

  prependOnceListener(event, listener) {
    return this.prependListener(event, (...args) => {
      this.removeListener(event, listener);
      listener(...args);
    });
  }

  removeAllListeners(event) {
    if (event) {
      delete this._listeners[event];
    } else {
      this._listeners = {};
    }

    return this;
  }

  removeListener(event, listener) {
    if (!this._listeners[event]) {
      return this;
    }

    this._listeners[event]
      .splice(this._listeners[event].indexOf(listener), 1);

    return this;
  }

  setMaxListeners(max) {
    this._maxListeners = max;
    return this;
  }

  _checkMaxListeners(event) {
    if (this._listeners[event].length > this._maxListeners) {
      throw new Error('More than ' + this._maxListeners + ' listeners added');
    }

    return this;
  }
}
<commit_msg>Fix bug: make copy of listeners when emitting, once will remove one<commit_after>export default class EventEmitter {
  constructor() {
    this._listeners = {};
    this._maxListeners = 10;
  }

  addListener(event, listener) {
    this._listeners[event] = this._listeners[event] || [];
    this._listeners[event].push(listener);

    return this._checkMaxListeners(event);
  }

  emit(event, ...args) {
    if (!this._listeners[event]) {
      return this;
    }

    Array.from(this._listeners[event]).forEach((listener) => {
      listener(...args);
    });

    return this;
  }

  eventNames() {
    return Object.keys(this._listeners);
  }

  getMaxListeners() {
    return this._maxListeners;
  }

  listenerCount(event) {
    if (!this._listeners[event]) {
      return 0;
    }

    return this._listeners[event].length;
  }

  listeners(event) {
    return this._listeners[event];
  }

  on(event, listener) {
    return this.addListener(event, listener);
  }

  once(event, listener) {
    return this.addListener(event, (...args) => {
      this.removeListener(event, listener);
      listener(...args);
    });
  }

  prependListener(event, listener) {
    this._listeners[event] = this._listeners[event] || [];
    this._listeners[event].unshift(listener);

    return this._checkMaxListeners(event);
  }

  prependOnceListener(event, listener) {
    return this.prependListener(event, (...args) => {
      this.removeListener(event, listener);
      listener(...args);
    });
  }

  removeAllListeners(event) {
    if (event) {
      delete this._listeners[event];
    } else {
      this._listeners = {};
    }

    return this;
  }

  removeListener(event, listener) {
    if (!this._listeners[event]) {
      return this;
    }

    this._listeners[event]
      .splice(this._listeners[event].indexOf(listener), 1);

    return this;
  }

  setMaxListeners(max) {
    this._maxListeners = max;
    return this;
  }

  _checkMaxListeners(event) {
    if (this._listeners[event].length > this._maxListeners) {
      throw new Error('More than ' + this._maxListeners + ' listeners added');
    }

    return this;
  }
}
<|endoftext|>


<commit_before>var eventsSeparatorMatch = /[,\s]+/g;

function registerEvent(node, eventName, callback) {
  var eventCache = getData(node,'_cashEvents') || setData(node, '_cashEvents', {});
  eventCache[eventName] = eventCache[eventName] || [];
  eventCache[eventName].push(callback);
  node.addEventListener(eventName, callback);
}

function removeEventListeners(events, node, eventName) {
  each(events[eventName], callback => { node.removeEventListener(eventName, callback); });
  delete events[eventName];
}

function removeEvent(node, eventName, callback){
  var events = getData(node,'_cashEvents');
  if ( !events ) { return; }
  if ( eventName === undefined ) {
    for ( eventName in events ) {
      if ( !events.hasOwnProperty(eventName) ) { continue; }
      removeEventListeners(events,node,eventName);
    }
  } else {
    var eventCache = events[eventName];
    if ( !eventCache ) { return; }

    if (callback) {
      node.removeEventListener(eventName, callback);
      var index = eventCache.indexOf(callback);
      if ( index >= 0 ) { eventCache.splice( index, 1); }
    } else {
      removeEventListeners(events,node,eventName);
    }
  }
}

fn.extend({

  off(eventName, callback) {
    if ( eventName === undefined ) {
      this.each(v => removeEvent (v));
    } else {
      each( eventName.split(eventsSeparatorMatch), eventName => {
        this.each(v => removeEvent(v, eventName, callback) );
      });
    }
    return this;
  },

  on(eventName, delegate, callback, runOnce) { // jshint ignore:line

    var originalCallback;

    if ( !isString(eventName) ) {
      for (var key in eventName) {
        this.on(key,delegate,eventName[key]);
      }
      return this;
    }

    if ( isFunction(delegate) ) {
      callback = delegate;
      delegate = null;
    }

    if ( eventName === 'ready' ) {
      onReady(callback);
      return this;
    }

    if ( delegate ) {
      originalCallback = callback;
      callback = function(e) {
        var t = e.target;

        while (!matches(t, delegate)) {
          if (t === this) {
            return (t = false);
          }
          t = t.parentNode;
        }

        if (t) {
          originalCallback.call(t, e);
        }
      };
    }

    each( eventName.split(eventsSeparatorMatch), eventName => {
      this.each(v => {
        var finalCallback = callback;
        if ( runOnce ) {
          finalCallback = function(){
            callback.apply(this,arguments);
            removeEvent(v, eventName, finalCallback);
          };
        }
        registerEvent(v, eventName, finalCallback);
      });
    });
    return this;
  },

  one(eventName, delegate, callback) {
    return this.on(eventName, delegate, callback, true);
  },

  ready: onReady,

  trigger(eventName, data) {
    var evt = eventName;
    if (isString(eventName)) {
      evt = doc.createEvent('HTMLEvents');
      evt.initEvent(eventName, true, false);
    }
    evt.data = data;
    return this.each(v => v.dispatchEvent(evt));
  }

});
<commit_msg>Added support for removing wrapped event handlers<commit_after>var eventsSeparatorMatch = /[,\s]+/g;

function registerEvent(node, eventName, callback) {
  callback.guid = ( callback.guid || guid++ );
  var eventCache = getData(node,'_cashEvents') || setData(node, '_cashEvents', {});
  eventCache[eventName] = eventCache[eventName] || [];
  eventCache[eventName].push(callback);
  node.addEventListener(eventName, callback);
}

function removeEventListeners(events, node, eventName) {
  each(events[eventName], callback => { node.removeEventListener(eventName, callback); });
  delete events[eventName];
}

function removeEvent(node, eventName, callback){
  var events = getData(node,'_cashEvents');
  if ( !events ) { return; }
  if ( eventName === undefined ) {
    for ( eventName in events ) {
      if ( !events.hasOwnProperty(eventName) ) { continue; }
      removeEventListeners(events,node,eventName);
    }
  } else {
    var eventCache = events[eventName];
    if ( !eventCache ) { return; }

    if (callback) {
      callback.guid = ( callback.guid || guid++ );
      events[eventName] = eventCache.filter ( cb => {
        if ( cb.guid !== callback.guid ) { return true; }
        node.removeEventListener(eventName, cb);
      });
    } else {
      removeEventListeners(events,node,eventName);
    }
  }
}

fn.extend({

  off(eventName, callback) {
    if ( eventName === undefined ) {
      this.each(v => removeEvent (v));
    } else {
      each( eventName.split(eventsSeparatorMatch), eventName => {
        this.each(v => removeEvent(v, eventName, callback) );
      });
    }
    return this;
  },

  on(eventName, delegate, callback, runOnce) { // jshint ignore:line

    if ( !isString(eventName) ) {
      for (var key in eventName) {
        this.on(key,delegate,eventName[key]);
      }
      return this;
    }

    if ( isFunction(delegate) ) {
      callback = delegate;
      delegate = null;
    }

    if ( eventName === 'ready' ) {
      onReady(callback);
      return this;
    }

    if ( delegate ) {
      var originalCallback = callback;
      callback = function(e) {
        var t = e.target;

        while (!matches(t, delegate)) {
          if (t === this) {
            return (t = false);
          }
          t = t.parentNode;
        }

        if (t) {
          originalCallback.call(t, e);
        }
      };
      callback.guid = originalCallback.guid = ( originalCallback.guid || guid++ );
    }

    each( eventName.split(eventsSeparatorMatch), eventName => {
      this.each(v => {
        var finalCallback = callback;
        if ( runOnce ) {
          finalCallback = function(){
            callback.apply(this,arguments);
            removeEvent(v, eventName, finalCallback);
          };
        }
        registerEvent(v, eventName, finalCallback);
      });
    });
    return this;
  },

  one(eventName, delegate, callback) {
    return this.on(eventName, delegate, callback, true);
  },

  ready: onReady,

  trigger(eventName, data) {
    var evt = eventName;
    if (isString(eventName)) {
      evt = doc.createEvent('HTMLEvents');
      evt.initEvent(eventName, true, false);
    }
    evt.data = data;
    return this.each(v => v.dispatchEvent(evt));
  }

});
<|endoftext|>


<commit_before>var csrftoken = $('meta[name=csrf-token]').attr('content');

function setErrorAlert (id, code, reason) {
    /*
     * Pass code (int) and id (string) to alert an error on the page.
     * Optionally pass a reason (string) for the error.
    */
    'use strict';

    var localId = id,
        text = '';

    if (id[0] !== '#') {
        localId = '#' + id;
    }

    text = '
' +
        '<button type="button" class="close" ' +
        'data-dismiss="alert" aria-hidden="true">×</button>';

    if (reason !== undefined) {
        text += reason + '
';
    }

    text += 'Error while loading data from the server (error code: ' +
        code + '). ' +
        'Please contact the website administrators.';

    text += '
';

    $('#errors-container').append(text);
    $(localId).alert();
}

function setXhrHeader (xhr) {
    /*
        Set the CSRF token header for ajax request.
        xhr: The xhr object to add the header to.
    */
    'use strict';
    xhr.setRequestHeader("X-CSRFToken", csrftoken);
}

function loadContent (elementId, staticContent) {
    /*
        Load some static content replacing what is inside the provided element.
        elementId: The ID of the element to empty and re-populate.
        staticContent: URI of the static content HTML to load.
    */
    'use strict';
    var localId = elementId;

    if (elementId[0] !== '#') {
        localId = '#' + elementId;
    }

    $(localId).empty().load(staticContent);
}
<commit_msg>Add functionalities to base JS library.<commit_after>var csrftoken = $('meta[name=csrf-token]').attr('content');

function setErrorAlert(id, code, reason) {
    /*
     * Pass code (int) and id (string) to alert an error on the page.
     * Optionally pass a reason (string) for the error.
    */
    'use strict';

    var localId = id,
        text = '';

    if (id[0] !== '#') {
        localId = '#' + id;
    }

    text = '
' +
        '<button type="button" class="close" ' +
        'data-dismiss="alert" aria-hidden="true">×</button>';

    if (reason !== undefined) {
        text += reason + '
';
    }

    text += 'Error while loading data from the server (error code: ' +
        code + '). ' +
        'Please contact the website administrators.';

    text += '
';

    $('#errors-container').append(text);
    $(localId).alert();
}

function setXhrHeader(xhr) {
    /*
        Set the CSRF token header for ajax request.
        xhr: The xhr object to add the header to.
    */
    'use strict';
    xhr.setRequestHeader('X-CSRFToken', csrftoken);
}

function loadContent(elementId, staticContent) {
    /*
        Load some static content replacing what is inside the provided element.
        elementId: The ID of the element to empty and re-populate.
        staticContent: URI of the static content HTML to load.
    */
    'use strict';
    var localId = elementId;

    if (elementId[0] !== '#') {
        localId = '#' + elementId;
    }

    $(localId).empty().load(staticContent);
}

function populateSideBarNav(elements) {
    /*
        Populate the sidebar navigation with the provided elements.
        The "Top" link, is already populated since it's available in the base
        template.

        elements: An array of objects. Each object must have the href, and name
        attributes set. An optional subnav attribute can be defined, and must
        be another array of similar objects, to add a navigation sub-level.
    */
    'use strict';

    if (elements === undefined || elements === null) {
        return;
    }

    function checkHref(href) {
        if (href[0] !== '#') {
            href = '#' + href;
        }
        return href;
    }

    var sidebarNav = '',
        arrayLen = elements.length,
        element = null,
        i = 0,
        j = 0,
        subNav = null,
        subNavLen;

    // Append the stuff only if we have the element.
    // On mobile platforms the element is not available.
    if ($('#sidebar-nav').length !== 0) {
        sidebarNav = '
' +
            '
Top
';

        for (i; i < arrayLen; i = i + 1) {
            element = elements[i];

            sidebarNav += '
' + element.name + '';

            // Add subnav links (only if really available).
            if (element.hasOwnProperty('subnav') && element.subnav !== null) {
                subNav = element.subnav;
                subNavLen = subNav.length;

                sidebarNav += '
';
                for (j; j < subNavLen; j = j + 1) {
                    sidebarNav += '
' + subNav[j].name +
                        '
';
                }

                sidebarNav += '

';
            }

            sidebarNav += '
';
        }

        sidebarNav += '
';

        $('#sidebar-nav').empty().append(sidebarNav);
        $('[data-spy="scroll"]').each(function() {
            $(this).scrollspy('refresh');
        });
    }
}
<|endoftext|>


<commit_before>import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import BaseCollection from '/imports/api/base/BaseCollection';
import { Interests } from '/imports/api/interest/InterestCollection';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

/** @module Profile */

/**
 * Profiles provide portfolio data for a user.
 * @extends module:Base~BaseCollection
 */
class ProfileCollection extends BaseCollection {

  /**
   * Creates the Profile collection.
   */
  constructor() {
    super('Profile', new SimpleSchema({
      username: { type: String },
      // Remainder are optional
      firstName: { type: String, optional: true },
      lastName: { type: String, optional: true },
      bio: { type: String, optional: true },
      interests: { type: [String], optional: true },
      title: { type: String, optional: true },
      picture: { type: SimpleSchema.RegEx.Url, optional: true },
      github: { type: SimpleSchema.RegEx.Url, optional: true },
      facebook: { type: SimpleSchema.RegEx.Url, optional: true },
      instagram: { type: SimpleSchema.RegEx.Url, optional: true },
    }));
  }

  /**
   * Defines a new Profile.
   * @example
   * Profiles.define({ firstName: 'Philip',
   *                   lastName: 'Johnson',
   *                   username: 'johnson',
   *                   bio: 'I have been a professor of computer science at UH since 1990.',
   *                   interests: ['Application Development', 'Software Engineering', 'Databases'],
   *                   title: 'Professor of Information and Computer Sciences',
   *                   picture: 'http://philipmjohnson.org/headshot.jpg',
   *                   github: 'https://github.com/philipmjohnson',
   *                   facebook: 'https://facebook.com/philipmjohnson',
   *                   instagram: 'https://instagram.com/philipmjohnson' });
   * @param { Object } description Object with required key username.
   * Remaining keys are optional.
   * Username must be unique for all users. It should be the UH email account.
   * Interests is an array of defined interest names.
   * @throws { Meteor.Error } If a user with the supplied username already exists, or
   * if one or more interests are not defined, or if github, facebook, and instagram are not URLs.
   * @returns The newly created docID.
   */
  define({ firstName = '', lastName = '', username, bio = '', interests, picture = '', title = '', github = '',
      facebook = '', instagram = '' }) {
    // make sure required fields are OK.
    const checkPattern = { firstName: String, lastName: String, username: String, bio: String, picture: String,
      title: String };
    check({ firstName, lastName, username, bio, picture, title }, checkPattern);

    if (this.find({ username }).count() > 0) {
      throw new Meteor.Error(`${username} is previously defined in another Profile`);
    }

    // Throw an error if any of the passed Interest names are not defined.
    Interests.assertNames(interests);
    return this._collection.insert({ firstName, lastName, username, bio, interests, picture, title, github,
      facebook, instagram });
  }

  /**
   * Returns an object representing the Profile docID in a format acceptable to define().
   * @param docID The docID of a Profile.
   * @returns { Object } An object representing the definition of docID.
   */
  dumpOne(docID) {
    const doc = this.findDoc(docID);
    const firstName = doc.firstName;
    const lastName = doc.lastName;
    const username = doc.username;
    const bio = doc.bio;
    const interests = doc.interests;
    const picture = doc.picture;
    const title = doc.title;
    const github = doc.github;
    const facebook = doc.facebook;
    const instagram = doc.instagram;
    return { firstName, lastName, username, bio, interests, picture, title, github, facebook, instagram };
  }
}
<commit_msg>fixed<commit_after>import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import BaseCollection from '/imports/api/base/BaseCollection';
import { Interests } from '/imports/api/interest/InterestCollection';
import { check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

/** @module Profile */

/**
 * Profiles provide portfolio data for a user.
 * @extends module:Base~BaseCollection
 */
class ProfileCollection extends BaseCollection {

  /**
   * Creates the Profile collection.
   */
  constructor() {
    super('Profile', new SimpleSchema({
      username: { type: String },
      // Remainder are optional
      firstName: { type: String, optional: true },
      lastName: { type: String, optional: true },
      bio: { type: String, optional: true },
      interests: { type: [String], optional: true },
      title: { type: String, optional: true },
      picture: { type: SimpleSchema.RegEx.Url, optional: true },
      github: { type: SimpleSchema.RegEx.Url, optional: true },
      facebook: { type: SimpleSchema.RegEx.Url, optional: true },
      instagram: { type: SimpleSchema.RegEx.Url, optional: true },
    }));
  }

  /**
   * Defines a new Profile.
   * @example
   * Profiles.define({ firstName: 'Philip',
   *                   lastName: 'Johnson',
   *                   username: 'johnson',
   *                   bio: 'I have been a professor of computer science at UH since 1990.',
   *                   interests: ['Application Development', 'Software Engineering', 'Databases'],
   *                   title: 'Professor of Information and Computer Sciences',
   *                   picture: 'http://philipmjohnson.org/headshot.jpg',
   *                   github: 'https://github.com/philipmjohnson',
   *                   facebook: 'https://facebook.com/philipmjohnson',
   *                   instagram: 'https://instagram.com/philipmjohnson' });
   * @param { Object } description Object with required key username.
   * Remaining keys are optional.
   * Username must be unique for all users. It should be the UH email account.
   * Interests is an array of defined interest names.
   * @throws { Meteor.Error } If a user with the supplied username already exists, or
   * if one or more interests are not defined, or if github, facebook, and instagram are not URLs.
   * @returns The newly created docID.
   */
  define({ firstName = '', lastName = '', username, bio = '', interests, picture = '', title = '', github = '',
      facebook = '', instagram = '' }) {
    // make sure required fields are OK.
    const checkPattern = { firstName: String, lastName: String, username: String, bio: String, picture: String,
      title: String };
    check({ firstName, lastName, username, bio, picture, title }, checkPattern);

    if (this.find({ username }).count() > 0) {
      throw new Meteor.Error(`${username} is previously defined in another Profile`);
    }

    // Throw an error if any of the passed Interest names are not defined.
    Interests.assertNames(interests);
    return this._collection.insert({ firstName, lastName, username, bio, interests, picture, title, github,
      facebook, instagram });
  }

  /**
   * Returns an object representing the Profile docID in a format acceptable to define().
   * @param docID The docID of a Profile.
   * @returns { Object } An object representing the definition of docID.
   */
  dumpOne(docID) {
    const doc = this.findDoc(docID);
    const firstName = doc.firstName;
    const lastName = doc.lastName;
    const username = doc.username;
    const bio = doc.bio;
    const interests = doc.interests;
    const picture = doc.picture;
    const title = doc.title;
    const github = doc.github;
    const facebook = doc.facebook;
    const instagram = doc.instagram;
    return { firstName, lastName, username, bio, interests, picture, title, github, facebook, instagram };
  }
}

export const Profiles = new ProfileCollection();
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { observer } from 'mobx-react';

import FormSelect from './FormSelect';

@observer
class CascadingSelect extends React.Component {
  static propTypes = {
    namePrefix: PropTypes.string,
    optionNodeId: PropTypes.string,
    optionSetId: PropTypes.string.isRequired,
    levels: PropTypes.arrayOf(PropTypes.object),
    updateLevels: PropTypes.func.isRequired,
    onChange: PropTypes.func,
  };

  async componentDidMount() {
    const { updateLevels } = this.props;
    await updateLevels();
  }

  nodeChanged = (isLastLevel) => (newNodeId) => {
    const { onChange, updateLevels } = this.props;

    if (onChange) {
      onChange(newNodeId);
    }

    if (!isLastLevel) {
      updateLevels();
    }
  }

  buildLevelProps = (level, isLastLevel) => {
    const { namePrefix } = this.props;
    return {
      type: 'select',
      name: `${namePrefix}[option_node_ids][]`,
      key: 'display_conditions_attributes_option_node_ids_',
      value: level.selected,
      options: level.options,
      prompt: this.optionPrompt(level),
      onChange: this.nodeChanged(isLastLevel),
    };
  }

  buildLevels = () => {
    const { levels } = this.props;
    const self = this;
    let result = [];
    if (levels) {
      result = levels.map((level, i) => {
        return (
          <div
            className="level"
            key={level.name}
          >
            <FormSelect {...self.buildLevelProps(level, self.isLastLevel(i))} />
          </div>
        );
      });
    }
    return result;
  }

  isLastLevel = (i) => {
    const { levels } = this.props;
    return levels && levels.length === (i + 1);
  }

  optionPrompt = (level) => {
    if (level.name) {
      return I18n.t('option_set.option_prompt_with_level', { level: level.name });
    }
    return I18n.t('option_set.option_prompt');
  }

  render() {
    return (
      <div
        className="cascading-selects"
        id="cascading-selects-1"
      >
        {this.buildLevels()}
      </div>
    );
  }
}

export default CascadingSelect;
<commit_msg>9397: Pass levelIndex instead of isLastLevel<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { observer } from 'mobx-react';

import FormSelect from './FormSelect';

@observer
class CascadingSelect extends React.Component {
  static propTypes = {
    namePrefix: PropTypes.string,
    optionNodeId: PropTypes.string,
    optionSetId: PropTypes.string.isRequired,
    levels: PropTypes.arrayOf(PropTypes.object),
    updateLevels: PropTypes.func.isRequired,
    onChange: PropTypes.func,
  };

  async componentDidMount() {
    const { updateLevels } = this.props;
    await updateLevels();
  }

  nodeChanged = (levelIndex) => (newNodeId) => {
    const { onChange, updateLevels } = this.props;
    const isLastLevel = this.isLastLevel(levelIndex);

    if (onChange) {
      onChange(newNodeId);
    }

    if (!isLastLevel) {
      updateLevels();
    }
  }

  buildLevelProps = (level, levelIndex) => {
    const { namePrefix } = this.props;
    return {
      type: 'select',
      name: `${namePrefix}[option_node_ids][]`,
      key: 'display_conditions_attributes_option_node_ids_',
      value: level.selected,
      options: level.options,
      prompt: this.optionPrompt(level),
      onChange: this.nodeChanged(levelIndex),
    };
  }

  buildLevels = () => {
    const { levels } = this.props;
    let result = [];
    if (levels) {
      result = levels.map((level, index) => {
        return (
          <div
            className="level"
            key={level.name}
          >
            <FormSelect {...this.buildLevelProps(level, index)} />
          </div>
        );
      });
    }
    return result;
  }

  isLastLevel = (i) => {
    const { levels } = this.props;
    return levels && levels.length === (i + 1);
  }

  optionPrompt = (level) => {
    if (level.name) {
      return I18n.t('option_set.option_prompt_with_level', { level: level.name });
    }
    return I18n.t('option_set.option_prompt');
  }

  render() {
    return (
      <div
        className="cascading-selects"
        id="cascading-selects-1"
      >
        {this.buildLevels()}
      </div>
    );
  }
}

export default CascadingSelect;
<|endoftext|>


<commit_before>import $ from 'jquery';

$(document).on('blur keydown', 'input, textarea', () => {
  $(this).addClass('touched');
});

$(document).on('click', 'input[type="submit"]:not([formnovalidate])', () => {
  const $form = $(this).closest('form');
  $('input, textarea', $form).addClass('touched');
});
<commit_msg>Refactor form validation helpers<commit_after>import { delegate } from '@utils';

delegate('blur keydown', 'input, textarea', ({ target }) => {
  touch(target);
});

delegate(
  'click',
  'input[type="submit"]:not([formnovalidate])',
  ({ target }) => {
    let form = target.closest('form');
    let inputs = form ? form.querySelectorAll('input, textarea') : [];
    [...inputs].forEach(touch);
  }
);

function touch({ classList }) {
  classList.add('touched');
}
<|endoftext|>


<commit_before>import {Form} from 'widget/form/form'
import {Layout} from 'widget/layout'
import {Panel} from 'widget/panel/panel'
import {RecipeFormPanel, recipeFormPanel} from 'app/home/body/process/recipeFormPanel'
import {Subject} from 'rxjs'
import {compose} from 'compose'
import {msg} from 'translate'
import {takeUntil} from 'rxjs/operators'
import React from 'react'
import _ from 'lodash'
import api from '../../../../../../../../api'
import styles from './source.module.css'

const fields = {
    asset: new Form.Field()
        .notEmpty('process.ccdcSlice.panel.source.form.asset.required'),
    bands: new Form.Field()
        .notEmpty('process.ccdcSlice.panel.source.form.bands.required'),
    dateFormat: new Form.Field(),
    startDate: new Form.Field(),
    endDate: new Form.Field(),
    surfaceReflectance: new Form.Field()
}

class Source extends React.Component {
    constructor(props) {
        super(props)
        this.assetChanged$ = new Subject()
    }

    render() {
        return (
            <RecipeFormPanel
                className={styles.panel}
                placement='bottom-right'>
                <Panel.Header
                    icon='cog'
                    title={msg('process.ccdcSlice.panel.source.title')}/>
                <Panel.Content className={styles.content}>
                    <Layout>
                        {this.renderSource()}
                        <div/> {/* [HACK] Make sure widget messages are shown */}
                    </Layout>
                </Panel.Content>
                <Form.PanelButtons/>
            </RecipeFormPanel>
        )
    }

    renderSource() {
        const {inputs: {asset, bands}} = this.props
        return (
            <Form.Input
                label={msg('process.ccdcSlice.panel.source.form.asset.label')}
                autoFocus
                input={asset}
                placeholder={msg('process.ccdcSlice.panel.source.form.asset.placeholder')}
                spellCheck={false}
                onChange={() => bands.set(null)}
                onChangeDebounced={asset => asset && this.loadMetadata(asset)}
                errorMessage
                busyMessage={this.props.stream('LOAD_ASSET_METADATA').active && msg('widget.loading')}
            />
        )
    }

    loadMetadata(asset) {
        this.props.stream('LOAD_ASSET_METADATA',
            api.gee.imageMetadata$({asset}).pipe(
                takeUntil(this.assetChanged$)),
            metadata => this.updateMetadata(metadata),
            error => {
                this.props.inputs.asset.setInvalid(
                    error.response
                        ? msg(error.response.messageKey, error.response.messageArgs, error.response.defaultMessage)
                        : msg('asset.failedToLoad')
                )
            }
        )
    }

    updateMetadata(metadata) {
        const assetBands = _.intersection(...['coefs', 'magnitude', 'rmse']
            .map(postfix => metadata.bands
                .map(assetBand => assetBand.match(`(.*)_${postfix}`))
                .map(match => match && match[1])
                .filter(band => band)
            )
        )
        const {inputs: {asset, bands, dateFormat, startDate, endDate, surfaceReflectance}} = this.props
        if (assetBands) {
            bands.set(assetBands)
            dateFormat.set(metadata.dateFormat)
            startDate.set(metadata.startDate)
            endDate.set(metadata.endDate)
            surfaceReflectance.set(metadata.surfaceReflectance)
        } else {
            asset.setInvalid(msg('process.ccdcSlice.panel.source.form.asset.notCCDC'))
        }

    }
}

Source.propTypes = {}

export default compose(
    Source,
    recipeFormPanel({id: 'source', fields})
)
<commit_msg>Used notBlank() instead isEmpty() for validation of CCDC slice source.<commit_after>import {Form} from 'widget/form/form'
import {Layout} from 'widget/layout'
import {Panel} from 'widget/panel/panel'
import {RecipeFormPanel, recipeFormPanel} from 'app/home/body/process/recipeFormPanel'
import {Subject} from 'rxjs'
import {compose} from 'compose'
import {msg} from 'translate'
import {takeUntil} from 'rxjs/operators'
import React from 'react'
import _ from 'lodash'
import api from 'api'
import styles from './source.module.css'

const fields = {
    asset: new Form.Field()
        .notBlank('process.ccdcSlice.panel.source.form.asset.required'),
    bands: new Form.Field()
        .notEmpty('process.ccdcSlice.panel.source.form.bands.required'),
    dateFormat: new Form.Field(),
    startDate: new Form.Field(),
    endDate: new Form.Field(),
    surfaceReflectance: new Form.Field()
}

class Source extends React.Component {
    constructor(props) {
        super(props)
        this.assetChanged$ = new Subject()
    }

    render() {
        return (
            <RecipeFormPanel
                className={styles.panel}
                placement='bottom-right'>
                <Panel.Header
                    icon='cog'
                    title={msg('process.ccdcSlice.panel.source.title')}/>
                <Panel.Content className={styles.content}>
                    <Layout>
                        {this.renderSource()}
                        <div/> {/* [HACK] Make sure widget messages are shown */}
                    </Layout>
                </Panel.Content>
                <Form.PanelButtons/>
            </RecipeFormPanel>
        )
    }

    renderSource() {
        const {inputs: {asset, bands}} = this.props
        return (
            <Form.Input
                label={msg('process.ccdcSlice.panel.source.form.asset.label')}
                autoFocus
                input={asset}
                placeholder={msg('process.ccdcSlice.panel.source.form.asset.placeholder')}
                spellCheck={false}
                onChange={() => bands.set(null)}
                onChangeDebounced={asset => asset && this.loadMetadata(asset)}
                errorMessage
                busyMessage={this.props.stream('LOAD_ASSET_METADATA').active && msg('widget.loading')}
            />
        )
    }

    loadMetadata(asset) {
        this.props.stream('LOAD_ASSET_METADATA',
            api.gee.imageMetadata$({asset}).pipe(
                takeUntil(this.assetChanged$)),
            metadata => this.updateMetadata(metadata),
            error => {
                this.props.inputs.asset.setInvalid(
                    error.response
                        ? msg(error.response.messageKey, error.response.messageArgs, error.response.defaultMessage)
                        : msg('asset.failedToLoad')
                )
            }
        )
    }

    updateMetadata(metadata) {
        const assetBands = _.intersection(...['coefs', 'magnitude', 'rmse']
            .map(postfix => metadata.bands
                .map(assetBand => assetBand.match(`(.*)_${postfix}`))
                .map(match => match && match[1])
                .filter(band => band)
            )
        )
        const {inputs: {asset, bands, dateFormat, startDate, endDate, surfaceReflectance}} = this.props
        if (assetBands) {
            bands.set(assetBands)
            dateFormat.set(metadata.dateFormat)
            startDate.set(metadata.startDate)
            endDate.set(metadata.endDate)
            surfaceReflectance.set(metadata.surfaceReflectance)
        } else {
            asset.setInvalid(msg('process.ccdcSlice.panel.source.form.asset.notCCDC'))
        }

    }
}

Source.propTypes = {}

export default compose(
    Source,
    recipeFormPanel({id: 'source', fields})
)
<|endoftext|>


<commit_before>/**
 * @augments ListEditorBaseBuilder
 * @constructor
 */
function ComboBoxBuilder() {
    _.superClass(ComboBoxBuilder, this);
}

_.inherit(ComboBoxBuilder, ListEditorBaseBuilder);

_.extend(ComboBoxBuilder.prototype, /** @lends ComboBoxBuilder.prototype */{

    createElement: function (params) {
        return new ComboBox(params.parent);
    },

    applyMetadata: function (params) {
        var element = params.element;

        var data = ListEditorBaseBuilder.prototype.applyMetadata.call(this, params);
        this.initValueTemplate(data.valueBinding, params);
        element.setLabelText(params.metadata.LabelText);

        //(function (binding) {
        //    var source = binding.getSource();
        //    element.onPropertyChanged('search', function (context, args) {
        //        var value = args.newValue;
        //        source.setFilter([
        //            {
        //                criteriaType: 64,
        //                property: 'Display',
        //                value: value
        //            }
        //        ]);
        //
        //        console.log('change:search', args);
        //        console.log(source.getItems());
        //    });
        //
        //})(data.itemsBinding);
    },

    initValueTemplate: function (binding, params) {

        var metadata = params.metadata;
        var element = params.element;
        var valueTemplate;
        var property;

        if ('ValueTemplate' in metadata) {
            valueTemplate = this.buildValueTemplate(metadata.ValueTemplate, params);
        } else if ('ValueFormat' in metadata) {
            valueTemplate = this.buildValueTemplateByFormat(binding, metadata.ValueFormat, params);
        } else {
            valueTemplate = this.buildValueTemplateByDefault(binding, params);
        }

        element.setValueTemplate(valueTemplate);
    },

    buildValueTemplate: function (templateMetadata, params) {
        var element = params.element;
        var builder = params.builder;
        var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty('');
        var that = this;

        return function (context, args) {
            var index = args.index;
            var bindingIndex;
            var argumentForBuilder = {
                parent: params.element,
                parentView: params.parentView
            };

            if (index !== undefined && index !== null) {
                //bindingIndex = that.bindingIndexByItemsIndex(index, params);
                bindingIndex = index;

                if (bindingIndex !== undefined && bindingIndex !== null) {
                    argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', bindingIndex);
                } else {
                    argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index);
                }
            }

            return builder.build(templateMetadata, argumentForBuilder);
        };
    },

    buildValueTemplateByFormat: function (binding, valueFormatMetadata, params) {
        var format = this.buildDisplayFormat(valueFormatMetadata, params);
        return function (context, args) {
            var index = args.index;
            var value = args.value;

            var label = new Label(this);
            label.setHorizontalAlignment('Left');
            label.setDisplayFormat(format);
            var labelBinding = new DataBinding(this);
            labelBinding.setMode(BindingModes.toElement);

            var source = binding.getSource();
            var property = binding.getSourceProperty();

            if (params.element.getMultiSelect()) {
                if (property && property !== '') {
                    property = [property, index].join('.');
                } else {
                    property = String(index);
                }
            }

            labelBinding.bindSource(source, property);
            labelBinding.bindElement(label, 'value');

            return label;
        };
        //return function(context, args){
        //    var index = args.index;
        //    var label = new Label(this);
        //
        //    label.setDisplayFormat(format);
        //    label.setValue(format.call(null, args));
        //    return label;
        //};
    },

    buildValueTemplateByDefault: function (binding, params) {

        return function (context, args) {
            var index = args.index;
            var value = args.value;

            var label = new Label(this);
            label.setHorizontalAlignment('Left');

            //if (binding) {
                //var labelBinding = new DataBinding(this);
                //labelBinding.setMode(BindingModes.toElement);
                //
                //var source = binding.getSource();
                //var property = binding.getSourceProperty();
                //
                //if (params.element.getMultiSelect()) {
                //    if (property && property !== '') {
                //        property = [property, index].join('.');
                //    } else {
                //        property = String(index);
                //    }
                //}
                //
                //labelBinding.bindSource(source, property);
                //labelBinding.bindElement(label, 'value');

            //} else {
                label.setValue(value);
            //}

            return label;
        };
    }
});<commit_msg>~fix Не работал ValueFormat без метаданных Value<commit_after>/**
 * @augments ListEditorBaseBuilder
 * @constructor
 */
function ComboBoxBuilder() {
    _.superClass(ComboBoxBuilder, this);
}

_.inherit(ComboBoxBuilder, ListEditorBaseBuilder);

_.extend(ComboBoxBuilder.prototype, /** @lends ComboBoxBuilder.prototype */{

    createElement: function (params) {
        return new ComboBox(params.parent);
    },

    applyMetadata: function (params) {
        var element = params.element;

        var data = ListEditorBaseBuilder.prototype.applyMetadata.call(this, params);
        this.initValueTemplate(data.valueBinding, params);
        element.setLabelText(params.metadata.LabelText);

        //(function (binding) {
        //    var source = binding.getSource();
        //    element.onPropertyChanged('search', function (context, args) {
        //        var value = args.newValue;
        //        source.setFilter([
        //            {
        //                criteriaType: 64,
        //                property: 'Display',
        //                value: value
        //            }
        //        ]);
        //
        //        console.log('change:search', args);
        //        console.log(source.getItems());
        //    });
        //
        //})(data.itemsBinding);
    },

    initValueTemplate: function (binding, params) {

        var metadata = params.metadata;
        var element = params.element;
        var valueTemplate;
        var property;

        if ('ValueTemplate' in metadata) {
            valueTemplate = this.buildValueTemplate(metadata.ValueTemplate, params);
        } else if ('ValueFormat' in metadata) {
            valueTemplate = this.buildValueTemplateByFormat(binding, metadata.ValueFormat, params);
        } else {
            valueTemplate = this.buildValueTemplateByDefault(binding, params);
        }

        element.setValueTemplate(valueTemplate);
    },

    buildValueTemplate: function (templateMetadata, params) {
        var element = params.element;
        var builder = params.builder;
        var basePathOfProperty = params.basePathOfProperty || new BasePathOfProperty('');
        var that = this;

        return function (context, args) {
            var index = args.index;
            var bindingIndex;
            var argumentForBuilder = {
                parent: params.element,
                parentView: params.parentView
            };

            if (index !== undefined && index !== null) {
                //bindingIndex = that.bindingIndexByItemsIndex(index, params);
                bindingIndex = index;

                if (bindingIndex !== undefined && bindingIndex !== null) {
                    argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', bindingIndex);
                } else {
                    argumentForBuilder.basePathOfProperty = basePathOfProperty.buildChild('', index);
                }
            }

            return builder.build(templateMetadata, argumentForBuilder);
        };
    },

    buildValueTemplateByFormat: function (binding, valueFormatMetadata, params) {
        var format = this.buildDisplayFormat(valueFormatMetadata, params);
        return function (context, args) {
            var index = args.index;
            var value = args.value;

            var label = new Label(this);
            label.setHorizontalAlignment('Left');
            label.setDisplayFormat(format);
            //var labelBinding = new DataBinding(this);
            //labelBinding.setMode(BindingModes.toElement);
            //
            //var source = binding.getSource();
            //var property = binding.getSourceProperty();
            //
            //if (params.element.getMultiSelect()) {
            //    if (property && property !== '') {
            //        property = [property, index].join('.');
            //    } else {
            //        property = String(index);
            //    }
            //}
            //
            //labelBinding.bindSource(source, property);
            //labelBinding.bindElement(label, 'value');
            label.setValue(value);
            return label;
        };
        //return function(context, args){
        //    var index = args.index;
        //    var label = new Label(this);
        //
        //    label.setDisplayFormat(format);
        //    label.setValue(format.call(null, args));
        //    return label;
        //};
    },

    buildValueTemplateByDefault: function (binding, params) {

        return function (context, args) {
            var index = args.index;
            var value = args.value;

            var label = new Label(this);
            label.setHorizontalAlignment('Left');

            //if (binding) {
                //var labelBinding = new DataBinding(this);
                //labelBinding.setMode(BindingModes.toElement);
                //
                //var source = binding.getSource();
                //var property = binding.getSourceProperty();
                //
                //if (params.element.getMultiSelect()) {
                //    if (property && property !== '') {
                //        property = [property, index].join('.');
                //    } else {
                //        property = String(index);
                //    }
                //}
                //
                //labelBinding.bindSource(source, property);
                //labelBinding.bindElement(label, 'value');

            //} else {
                label.setValue(value);
            //}

            return label;
        };
    }
});<|endoftext|>


<commit_before>/**
 * Author: Milica Kadic
 * Date: 10/14/14
 * Time: 2:18 PM
 */

'use strict';

angular.module('registryApp.cliche')
    .controller('InputFieldCtrl', ['$scope', '$modal', '$templateCache', 'Cliche', 'Const', 'lodash', function ($scope, $modal, $templateCache, Cliche, Const, _) {

        $scope.view = {};

        $scope.key = $scope.key || 'name';

        $scope.view.name = Cliche.parseName($scope.prop);
        $scope.view.property = $scope.prop || {};
        $scope.view.property.type = Cliche.getSchema('input', $scope.prop, $scope.type, true);
        $scope.view.property.inputBinding = Cliche.getAdapter($scope.prop, false, 'input');
        $scope.view.type = Cliche.parseType($scope.view.property.type);
        $scope.view.required = Cliche.isRequired($scope.view.property.type);
        $scope.view.items = Cliche.getItemsRef($scope.view.type, $scope.view.property.type);

        $scope.view.tpl = 'views/cliche/inputs/input-' + $scope.view.type.toLowerCase()  + '.html';

        var keyName = $scope.appName + Const.exposedSeparator + $scope.view.name;

        var enumObj = Cliche.parseEnum($scope.view.property.type);

        $scope.view.symbols = enumObj.symbols;

        $scope.view.expose = $scope.exposed ? !_.isUndefined($scope.exposed[keyName]) : false;
        if ($scope.view.expose) { $scope.isDisabled = true; }

        $scope.view.exposible = !_.isUndefined($scope.exposed);

        $scope.view.ignore = $scope.ignoreFiles === 'true' && ($scope.view.type === 'File' || ($scope.view.items && $scope.view.items.type === 'File'));

        /**
         * Get default input scheme
         *
         * @param {*} value
         * @returns {*}
         */
        var getDefaultScheme = function (value) {

            if (_.isObject(value)) {
                return '';
            } else {
                return value;
            }

        };

        /**
         * Get file input scheme
         *
         * @param {*} value
         * @returns {*}
         */
        var getFileScheme = function (value) {

            var validFileKeys = ['path', 'size', 'secondaryFiles', 'metadata'];

            var intersection = _.intersection(validFileKeys, _.keys(value));

            if (intersection.length > 0) {
                return value;
            } else {
                return {path: value};
            }

        };

        /**
         * Get object input scheme
         *
         * @param {*} value
         * @returns {*}
         */
        var getObjectScheme = function (value) {

            if (_.isObject(value)) {
                return value;
            } else {
                return {};
            }

        };

        //var inputScheme = $scope.model;
        var inputScheme;

        /* type FILE */
        if ($scope.view.type === 'File') {

            inputScheme = getFileScheme($scope.model);

        /* type RECORD */
        } else if($scope.view.type === 'record') {

            inputScheme = getObjectScheme($scope.model);

        /* type ARRAY */
        } else if($scope.view.type === 'array') {
            inputScheme = [];

            $scope.view.items = $scope.view.items || {type: 'string'};

            switch($scope.view.items.type) {
            case 'record':
                _.each($scope.model, function(value) {
                    var innerScheme = getObjectScheme(value);
                    delete innerScheme.path;
                    inputScheme.push(innerScheme);
                });
                break;
            case 'File' || 'file':
                _.each($scope.model, function(value) {
                    inputScheme.push(getFileScheme(value));
                });
                break;
            default:
                //Type checking to avoid an array of characters
                if (_.isArray($scope.model)) {
                    _.each($scope.model, function(value) {
                        inputScheme.push(getDefaultScheme(value));
                    });
                } else if (_.isString($scope.model)) {
                    inputScheme.push(getDefaultScheme($scope.model));
                }
                break;
            }
            /* type STRING, NUMBER, INTEGER, BOOLEAN */
        } else {
            inputScheme = getDefaultScheme($scope.model);
        }

        $scope.view.model = inputScheme;

        // TODO: Figure this out for complex props, try to avoid this deep watch
        var deepWatcher = $scope.$watch('view.model', function(n, o) {
            if (n !== o) { $scope.model = n; }
        }, true);

//        // TODO: Figure this out for complex props
//        if ($scope.view.type === 'File') {
//            $scope.$watch('view.model.path', function(n, o) {
//                if (n !== o) {
//                    if (typeof $scope.model !== 'undefined'){
//                        $scope.model.path = n;
//                    } else {
//                        $scope.model = $scope.view.model;
//                    }
//                }
//            });
//        }

        /**
         * Open modal to enter more parameters for the input file
         */
        $scope.more = function() {

            var modalInstance = $modal.open({
                template: $templateCache.get('views/cliche/partials/input-file-more.html'),
                controller: 'InputFileMoreCtrl',
                windowClass: 'modal-prop',
                resolve: {data: function () {return {schema: $scope.view.model, key: $scope.view.name};}}
            });

            modalInstance.result.then(function (schema) {
                $scope.view.model = angular.copy(schema);
            });

        };

        /**
         * Expose current parameter
         */
        $scope.exposeParams = function () {

            if ($scope.view.expose) {
                $scope.exposed[keyName] = $scope.prop;
                $scope.isDisabled = true;
                $scope.handleExpose({appName: $scope.appName, key: $scope.view.name});
            } else {
                delete $scope.exposed[keyName];

                if (typeof $scope.onUnExpose === 'function') {
                    $scope.onUnExpose({appName: $scope.appName, key: $scope.view.name, value: $scope.view.model});
                }

                $scope.isDisabled = false;
            }

        };

        $scope.$on('destroy', function () {
            if (_.isFunction(deepWatcher)) {
                deepWatcher.call();
                deepWatcher = null;
            }
        })

    }])
    .directive('inputField', ['RecursionHelper', function (RecursionHelper) {
        return {
            restrict: 'E',
            template: '<ng-form name="inputForm" class="input-property" ng-if="!view.ignore"><ng-include class="include" src="view.tpl"></ng-include></ng-form>',
            scope: {
                model: '=ngModel',
                prop: '=',
                key: '@',
                ignoreFiles: '@',
                form: '=',
                appName: '@',
                exposed: '=?',
                isDisabled: '=?',
                handleExpose: '&',
                onUnExpose: '&'
            },
            controller: 'InputFieldCtrl',
            compile: function(element) {
                return RecursionHelper.compile(element, function() {});
            }
        };
    }]);<commit_msg>added $ before destroy event<commit_after>/**
 * Author: Milica Kadic
 * Date: 10/14/14
 * Time: 2:18 PM
 */

'use strict';

angular.module('registryApp.cliche')
    .controller('InputFieldCtrl', ['$scope', '$modal', '$templateCache', 'Cliche', 'Const', 'lodash', function ($scope, $modal, $templateCache, Cliche, Const, _) {

        $scope.view = {};

        $scope.key = $scope.key || 'name';

        $scope.view.name = Cliche.parseName($scope.prop);
        $scope.view.property = $scope.prop || {};
        $scope.view.property.type = Cliche.getSchema('input', $scope.prop, $scope.type, true);
        $scope.view.property.inputBinding = Cliche.getAdapter($scope.prop, false, 'input');
        $scope.view.type = Cliche.parseType($scope.view.property.type);
        $scope.view.required = Cliche.isRequired($scope.view.property.type);
        $scope.view.items = Cliche.getItemsRef($scope.view.type, $scope.view.property.type);

        $scope.view.tpl = 'views/cliche/inputs/input-' + $scope.view.type.toLowerCase()  + '.html';

        var keyName = $scope.appName + Const.exposedSeparator + $scope.view.name;

        var enumObj = Cliche.parseEnum($scope.view.property.type);

        $scope.view.symbols = enumObj.symbols;

        $scope.view.expose = $scope.exposed ? !_.isUndefined($scope.exposed[keyName]) : false;
        if ($scope.view.expose) { $scope.isDisabled = true; }

        $scope.view.exposible = !_.isUndefined($scope.exposed);

        $scope.view.ignore = $scope.ignoreFiles === 'true' && ($scope.view.type === 'File' || ($scope.view.items && $scope.view.items.type === 'File'));

        /**
         * Get default input scheme
         *
         * @param {*} value
         * @returns {*}
         */
        var getDefaultScheme = function (value) {

            if (_.isObject(value)) {
                return '';
            } else {
                return value;
            }

        };

        /**
         * Get file input scheme
         *
         * @param {*} value
         * @returns {*}
         */
        var getFileScheme = function (value) {

            var validFileKeys = ['path', 'size', 'secondaryFiles', 'metadata'];

            var intersection = _.intersection(validFileKeys, _.keys(value));

            if (intersection.length > 0) {
                return value;
            } else {
                return {path: value};
            }

        };

        /**
         * Get object input scheme
         *
         * @param {*} value
         * @returns {*}
         */
        var getObjectScheme = function (value) {

            if (_.isObject(value)) {
                return value;
            } else {
                return {};
            }

        };

        //var inputScheme = $scope.model;
        var inputScheme;

        /* type FILE */
        if ($scope.view.type === 'File') {

            inputScheme = getFileScheme($scope.model);

        /* type RECORD */
        } else if($scope.view.type === 'record') {

            inputScheme = getObjectScheme($scope.model);

        /* type ARRAY */
        } else if($scope.view.type === 'array') {
            inputScheme = [];

            $scope.view.items = $scope.view.items || {type: 'string'};

            switch($scope.view.items.type) {
            case 'record':
                _.each($scope.model, function(value) {
                    var innerScheme = getObjectScheme(value);
                    delete innerScheme.path;
                    inputScheme.push(innerScheme);
                });
                break;
            case 'File' || 'file':
                _.each($scope.model, function(value) {
                    inputScheme.push(getFileScheme(value));
                });
                break;
            default:
                //Type checking to avoid an array of characters
                if (_.isArray($scope.model)) {
                    _.each($scope.model, function(value) {
                        inputScheme.push(getDefaultScheme(value));
                    });
                } else if (_.isString($scope.model)) {
                    inputScheme.push(getDefaultScheme($scope.model));
                }
                break;
            }
            /* type STRING, NUMBER, INTEGER, BOOLEAN */
        } else {
            inputScheme = getDefaultScheme($scope.model);
        }

        $scope.view.model = inputScheme;

        // TODO: Figure this out for complex props, try to avoid this deep watch
        var deepWatcher = $scope.$watch('view.model', function(n, o) {
            if (n !== o) { $scope.model = n; }
        }, true);

//        // TODO: Figure this out for complex props
//        if ($scope.view.type === 'File') {
//            $scope.$watch('view.model.path', function(n, o) {
//                if (n !== o) {
//                    if (typeof $scope.model !== 'undefined'){
//                        $scope.model.path = n;
//                    } else {
//                        $scope.model = $scope.view.model;
//                    }
//                }
//            });
//        }

        /**
         * Open modal to enter more parameters for the input file
         */
        $scope.more = function() {

            var modalInstance = $modal.open({
                template: $templateCache.get('views/cliche/partials/input-file-more.html'),
                controller: 'InputFileMoreCtrl',
                windowClass: 'modal-prop',
                resolve: {data: function () {return {schema: $scope.view.model, key: $scope.view.name};}}
            });

            modalInstance.result.then(function (schema) {
                $scope.view.model = angular.copy(schema);
            });

        };

        /**
         * Expose current parameter
         */
        $scope.exposeParams = function () {

            if ($scope.view.expose) {
                $scope.exposed[keyName] = $scope.prop;
                $scope.isDisabled = true;
                $scope.handleExpose({appName: $scope.appName, key: $scope.view.name});
            } else {
                delete $scope.exposed[keyName];

                if (typeof $scope.onUnExpose === 'function') {
                    $scope.onUnExpose({appName: $scope.appName, key: $scope.view.name, value: $scope.view.model});
                }

                $scope.isDisabled = false;
            }

        };

        $scope.$on('$destroy', function () {
            if (_.isFunction(deepWatcher)) {
                deepWatcher.call();
                deepWatcher = null;
            }
        })

    }])
    .directive('inputField', ['RecursionHelper', function (RecursionHelper) {
        return {
            restrict: 'E',
            template: '<ng-form name="inputForm" class="input-property" ng-if="!view.ignore"><ng-include class="include" src="view.tpl"></ng-include></ng-form>',
            scope: {
                model: '=ngModel',
                prop: '=',
                key: '@',
                ignoreFiles: '@',
                form: '=',
                appName: '@',
                exposed: '=?',
                isDisabled: '=?',
                handleExpose: '&',
                onUnExpose: '&'
            },
            controller: 'InputFieldCtrl',
            compile: function(element) {
                return RecursionHelper.compile(element, function() {});
            }
        };
    }]);<|endoftext|>