<commit_before>/**
 * (c) 2016 Tieto Finland Oy
 * Licensed under the MIT license.
 */
'use strict';

/**
 * @ngdoc directive
 * @name dashboard.proposalList:proposalListDirective
 * @description
 * # proposalListDirective
 */
angular.module('dashboard')
    .factory('PROPS', function (CONST) {
        return {
            'PUBLISHED': {
                NO: 0,
                YES: 1
            },
            'TYPE': [
                { value: 1, text: "Päätös", roles: [] },
                { value: 2, text: "Esityksen muutos", roles: [], cityCouncilRoles: [] },
                { value: 3, text: "Pöydällepanoehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 4, text: "Palautusehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 5, text: "Vastaehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 6, text: "Hylkäysehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 7, text: "Ponsi", roles: [], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 8, text: "Eriävä mielipide", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 9, text: "Esteellinen", roles: [], cityCouncilRoles: [] },
                { value: 10, text: "Esityksen poisto", roles: [], cityCouncilRoles: [] }
            ],
            'TOGGLE': 'PROPS.TOGGLE',
            'COUNT': 'PROPS.COUNT',
            'UPDATED': 'PROPS.UPDATED'
        };
    })
    .directive('dbProposalList', [function () {

        var controller = ['$log', '$scope', 'AhjoProposalsSrv', 'PROPS', '$rootScope', 'CONST', 'StorageSrv', function ($log, $scope, AhjoProposalsSrv, PROPS, $rootScope, CONST, StorageSrv) {
            $log.log("dbProposalList: CONTROLLER");
            var self = this;
            var role = CONST.MTGROLE.PARTICIPANT_FULL; // todo: pending support for other roles.
            var personGuid = null;
            var topicGuid = null;
            var isCityCouncil = null;
            self.proposals = null;
            self.tps = null;
            self.published = PROPS.PUBLISHED;
            self.isMobile = $rootScope.isMobile;
            self.isAllOpen = false;
            self.btnText = null;
            self.unsavedCount = 0;

            function setTypes() {
                $log.debug("dbProposalList: setTypes");
                self.tps = [];
                angular.forEach(PROPS.TYPE, function (type) {
                    if (angular.isObject(type)) {
                        var array = isCityCouncil ? type.cityCouncilRoles : type.roles;
                        if (angular.isArray(array) && array.indexOf(role) > CONST.NOTFOUND) {
                            this.push(type);
                        }
                    }
                }, self.tps);
            }

            function countProposals() {
                var drafts = 0;
                var published = 0;

                angular.forEach(self.proposals, function (prop) {
                    if (angular.isObject(prop)) {
                        if (prop.isPublished === PROPS.PUBLISHED.YES) {
                            published++;
                        }
                        else if (prop.isPublished === PROPS.PUBLISHED.NO) {
                            drafts++;
                        }
                    }
                });

                $rootScope.$emit(PROPS.COUNT, { 'drafts': drafts, 'published': published });
            }

            function checkProposals() {
                var unsaved = 0;
                angular.forEach(self.proposals, function (item) {
                    if (angular.isObject(item) && item.isPublished === null) {
                        unsaved++;
                    }
                });

                if (!self.unsavedCount && unsaved) {
                    $rootScope.$emit(CONST.PROPOSALISEDITING, true);
                }
                else if (self.unsavedCount && !unsaved) {
                    $rootScope.$emit(CONST.PROPOSALISEDITING, false);
                }
                self.unsavedCount = unsaved;
            }

            function createDraft(type) {
                if (type) {
                    if (!personGuid || !topicGuid) {
                        $log.error('dbProposalList: createDraft personGuid or topicGuid missing');
                    }
                    return {
                        "personGuid": personGuid,
                        "topicGuid": topicGuid,
                        "text": "",
                        "proposalType": type,
                        "isPublished": null,
                        "isOwnProposal": true
                    };
                }
                else {
                    return null;
                }
            }

            function removeProposal(data) {
                $log.debug("dbProposalList: removeProposal: " + JSON.stringify(data));

                var value;

                if (angular.isString(data)) {
                    value = data;
                }
                else if (angular.isObject(data)) {
                    if (angular.isString(data.proposalGuid)) {
                        value = data.proposalGuid;
                    }
                    else {
                        value = data;
                    }
                }

                if (value) {
                    var search = angular.isArray(self.proposals);
                    for (var index = self.proposals.length + CONST.NOTFOUND; search && index > CONST.NOTFOUND; index--) {
                        var prop = self.proposals[index];
                        if (angular.equals(value, prop.proposalGuid) || angular.equals(value, prop)) {
                            self.proposals.splice(index, 1);
                            search = false;
                        }
                    }

                    var events = angular.copy(StorageSrv.getKey(CONST.KEY.PROPOSAL_EVENT_ARRAY));
                    if (angular.isArray(events)) {
                        var found = false;
                        for (var i = events.length + CONST.NOTFOUND; !found && i > CONST.NOTFOUND; i--) {
                            var event = events[i];
                            if (angular.isObject(event.proposal) && angular.equals(event.proposal.proposalGuid, value)) {
                                events.splice(i, 1);
                                found = true;
                            }
                        }
                        if (found) {
                            StorageSrv.setKey(CONST.KEY.PROPOSAL_EVENT_ARRAY, events);
                        }
                    }

                    checkProposals();
                    countProposals();
                }
                else {
                    $log.error('dbProposalList: removeProposal parameter invalid');
                }
            }

            function updateProposal(proposal) {
                $log.debug("dbProposalList: updateProposal");
                if (angular.isObject(proposal)) {
                    if (!angular.isArray(self.proposals)) {
                        self.proposals = [];
                    }
                    var notFound = true;
                    for (var index = 0; notFound && index < self.proposals.length; index++) {
                        var prop = self.proposals[index];
                        if (angular.isObject(prop) && angular.equals(proposal.proposalGuid, prop.proposalGuid)) {
                            angular.merge(prop, proposal);
                            notFound = false;
                        }
                    }
                    if (notFound) {
                        self.proposals.splice(0, 0, proposal);
                    }
                    countProposals();
                }
                else {
                    $log.error('dbProposalList: updateProposal parameter invalid');
                }
            }

            function updateEvents(events) {
                $log.debug("dbProposalList: updateEvents");
                if (angular.isArray(events)) {
                    angular.forEach(events, function (event) {
                        if (angular.isObject(event)) {
                            switch (event.typeName) {
                                case CONST.MTGEVENT.REMARKPUBLISHED:
                                case CONST.MTGEVENT.REMARKUPDATED:
                                    if (angular.isObject(event.proposal) && angular.equals(event.proposal.topicGuid, topicGuid)) {
                                        updateProposal(event.proposal);
                                    }
                                    break;
                                default:
                                    $log.error('dbProposalList: updateEvents unsupported type');
                                    break;
                            }
                        }
                    });
                }
                else {
                    $log.error('dbProposalList: updateEvents parameter invalid');
                }
            }

            function getProposals(guid) {
                $log.debug("dbProposalList: getProposals: " + guid);
                if (angular.isString(guid)) {
                    self.proposals = [];
                    AhjoProposalsSrv.get({ 'guid': guid }).$promise.then(function (response) {
                        $log.debug("dbProposalList: get then");
                        if (angular.isObject(response) && angular.isArray(response.objects)) {
                            angular.forEach(response.objects, function (p) {
                                if (angular.isObject(p) && angular.isString(p.proposalGuid)) {
                                    this.push(angular.copy(p));
                                }
                            }, self.proposals);
                        }
                        else {
                            $log.error('dbProposalList: getProposals invalid response');
                        }
                    }, function (error) {
                        $log.error("dbProposalList: get error: " + JSON.stringify(error));
                    }, function (notify) {
                        $log.debug("dbProposalList: get notify: " + JSON.stringify(notify));
                    }).finally(function () {
                        $log.debug("dbProposalList: get finally: ");
                        var events = angular.copy(StorageSrv.getKey(CONST.KEY.PROPOSAL_EVENT_ARRAY));
                        updateEvents(events);
                        countProposals();
                    });
                }
                else {
                    $log.error('dbProposalList: getProposals parameter invalid');
                }
            }

            function addProposal(type) {
                $log.debug("dbProposalList: addProposal: " + type);
                if (angular.isObject(type)) {
                    if (!angular.isArray(self.proposals)) {
                        self.proposals = [];
                    }
                    var draft = createDraft(type.value);
                    self.proposals.splice(0, 0, draft);
                    countProposals();
                    checkProposals();
                }
                else {
                    $log.error('dbProposalList: addProposal parameter invalid');
                }
            }

            self.remove = function (data) {
                $log.debug("dbProposalList: remove: " + JSON.stringify(data));
                if (angular.isObject(data)) {
                    removeProposal(data.proposal);
                }
                else {
                    $log.error('dbProposalList: remove parameter invalid');
                }
            };

            self.add = function (data) {
                $log.debug("dbProposalList: add: " + JSON.stringify(data));
                if (angular.isObject(data) && angular.isObject(data.proposal)) {

                    var exists = false;
                    for (var index = 0; !exists && index < self.proposals.length; index++) {
                        var item = self.proposals[index];
                        if (angular.equals(item.proposalGuid, data.proposal.proposalGuid)) {
                            angular.merge(item, data.proposal);
                            exists = true;
                        }
                    }
                    if (!exists) {
                        self.proposals.splice(0, 0, data.proposal);
                    }

                }
                else {
                    $log.error('dbProposalList: add proposal missing');
                }
            };

            self.addProposalClicked = function (type) {
                addProposal(type);
            };

            self.toggleAll = function () {
                self.isAllOpen = !self.isAllOpen;
                self.btnText = self.isAllOpen ? 'STR_CLOSE_ALL' : 'STR_OPEN_ALL';
                $rootScope.$emit(PROPS.TOGGLE, self.isAllOpen);
            };

            $scope.$watch(function () {
                return {
                    topic: $scope.topic
                };
            }, function (data) {
                if (angular.isObject(data) && angular.isObject(data.topic) && !angular.equals(topicGuid, data.topic.topicGuid)) {
                    personGuid = data.topic.userPersonGuid;
                    topicGuid = data.topic.topicGuid;
                    isCityCouncil = data.topic.isCityCouncil;
                    getProposals(topicGuid);
                    setTypes();
                }

            }, true);

            $scope.$watch(function () {
                return StorageSrv.getKey(CONST.KEY.PROPOSAL_EVENT_ARRAY);
            }, function (events, oldEvents) {
                if (!angular.equals(events, oldEvents)) {
                    updateEvents(events);
                }
            });

            var proposalWatcher = $rootScope.$on(PROPS.UPDATED, function (event, data) {
                if (angular.isObject(data) && angular.isObject(data.sender)) {
                    if (self.proposals.indexOf(data.sender) >= 0) {
                        checkProposals();
                    }
                }
            });

            var deleteWatcher = $rootScope.$on(CONST.PROPOSALDELETED, function (event, data) {
                if (angular.isObject(data) && angular.isArray(data.deleted)) {
                    angular.forEach(data.deleted, function (e) {
                        if (angular.isObject(e) && angular.equals(e.topicGuid, topicGuid)) {
                            removeProposal(e.deletedProposal);
                        }
                    }, this);
                }
            });

            $scope.$on('$destroy', proposalWatcher);
            $scope.$on('$destroy', deleteWatcher);

            $scope.$on('$destroy', function () {
                $log.debug("dbProposalList: DESTROY");
            });

            self.btnText = self.isAllOpen ? 'STR_CLOSE_ALL' : 'STR_OPEN_ALL';
        }];

        return {
            scope: {
                topic: '='
            },
            templateUrl: 'directives/proposalList/proposalList.Directive.html',
            restrict: 'AE',
            controller: controller,
            controllerAs: 'c',
            replace: 'true'
        };
    }]);
<commit_msg>event search improved<commit_after>/**
 * (c) 2016 Tieto Finland Oy
 * Licensed under the MIT license.
 */
'use strict';

/**
 * @ngdoc directive
 * @name dashboard.proposalList:proposalListDirective
 * @description
 * # proposalListDirective
 */
angular.module('dashboard')
    .factory('PROPS', function (CONST) {
        return {
            'PUBLISHED': {
                NO: 0,
                YES: 1
            },
            'TYPE': [
                { value: 1, text: "Päätös", roles: [] },
                { value: 2, text: "Esityksen muutos", roles: [], cityCouncilRoles: [] },
                { value: 3, text: "Pöydällepanoehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 4, text: "Palautusehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 5, text: "Vastaehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 6, text: "Hylkäysehdotus", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 7, text: "Ponsi", roles: [], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 8, text: "Eriävä mielipide", roles: [CONST.MTGROLE.PARTICIPANT_FULL], cityCouncilRoles: [CONST.MTGROLE.PARTICIPANT_FULL] },
                { value: 9, text: "Esteellinen", roles: [], cityCouncilRoles: [] },
                { value: 10, text: "Esityksen poisto", roles: [], cityCouncilRoles: [] }
            ],
            'TOGGLE': 'PROPS.TOGGLE',
            'COUNT': 'PROPS.COUNT',
            'UPDATED': 'PROPS.UPDATED'
        };
    })
    .directive('dbProposalList', [function () {

        var controller = ['$log', '$scope', 'AhjoProposalsSrv', 'PROPS', '$rootScope', 'CONST', 'StorageSrv', function ($log, $scope, AhjoProposalsSrv, PROPS, $rootScope, CONST, StorageSrv) {
            $log.log("dbProposalList: CONTROLLER");
            var self = this;
            var role = CONST.MTGROLE.PARTICIPANT_FULL; // todo: pending support for other roles.
            var personGuid = null;
            var topicGuid = null;
            var isCityCouncil = null;
            self.proposals = null;
            self.tps = null;
            self.published = PROPS.PUBLISHED;
            self.isMobile = $rootScope.isMobile;
            self.isAllOpen = false;
            self.btnText = null;
            self.unsavedCount = 0;

            function setTypes() {
                $log.debug("dbProposalList: setTypes");
                self.tps = [];
                angular.forEach(PROPS.TYPE, function (type) {
                    if (angular.isObject(type)) {
                        var array = isCityCouncil ? type.cityCouncilRoles : type.roles;
                        if (angular.isArray(array) && array.indexOf(role) > CONST.NOTFOUND) {
                            this.push(type);
                        }
                    }
                }, self.tps);
            }

            function countProposals() {
                var drafts = 0;
                var published = 0;

                angular.forEach(self.proposals, function (prop) {
                    if (angular.isObject(prop)) {
                        if (prop.isPublished === PROPS.PUBLISHED.YES) {
                            published++;
                        }
                        else if (prop.isPublished === PROPS.PUBLISHED.NO) {
                            drafts++;
                        }
                    }
                });

                $rootScope.$emit(PROPS.COUNT, { 'drafts': drafts, 'published': published });
            }

            function checkProposals() {
                var unsaved = 0;
                angular.forEach(self.proposals, function (item) {
                    if (angular.isObject(item) && item.isPublished === null) {
                        unsaved++;
                    }
                });

                if (!self.unsavedCount && unsaved) {
                    $rootScope.$emit(CONST.PROPOSALISEDITING, true);
                }
                else if (self.unsavedCount && !unsaved) {
                    $rootScope.$emit(CONST.PROPOSALISEDITING, false);
                }
                self.unsavedCount = unsaved;
            }

            function createDraft(type) {
                if (type) {
                    if (!personGuid || !topicGuid) {
                        $log.error('dbProposalList: createDraft personGuid or topicGuid missing');
                    }
                    return {
                        "personGuid": personGuid,
                        "topicGuid": topicGuid,
                        "text": "",
                        "proposalType": type,
                        "isPublished": null,
                        "isOwnProposal": true
                    };
                }
                else {
                    return null;
                }
            }

            function removeProposal(data) {
                $log.debug("dbProposalList: removeProposal: " + JSON.stringify(data));
                var value;
                if (angular.isString(data)) {
                    value = data;
                }
                else if (angular.isObject(data)) {
                    if (angular.isString(data.proposalGuid)) {
                        value = data.proposalGuid;
                    }
                    else {
                        value = data;
                    }
                }

                if (value) {
                    var search = angular.isArray(self.proposals);
                    for (var index = self.proposals.length + CONST.NOTFOUND; search && index > CONST.NOTFOUND; index--) {
                        var prop = self.proposals[index];
                        if (angular.equals(value, prop.proposalGuid) || angular.equals(value, prop)) {
                            self.proposals.splice(index, 1);
                            search = false;
                        }
                    }

                    if (angular.isString(value)) {
                        var events = angular.copy(StorageSrv.getKey(CONST.KEY.PROPOSAL_EVENT_ARRAY));
                        if (angular.isArray(events)) {
                            var found = false;
                            for (var i = events.length + CONST.NOTFOUND; !found && i > CONST.NOTFOUND; i--) {
                                var event = events[i];
                                if (angular.isObject(event.proposal) && angular.equals(event.proposal.proposalGuid, value)) {
                                    events.splice(i, 1);
                                    found = true;
                                }
                            }
                            if (found) {
                                StorageSrv.setKey(CONST.KEY.PROPOSAL_EVENT_ARRAY, events);
                            }
                        }
                    }

                    checkProposals();
                    countProposals();
                }
                else {
                    $log.error('dbProposalList: removeProposal parameter invalid');
                }
            }

            function updateProposal(proposal) {
                $log.debug("dbProposalList: updateProposal");
                if (angular.isObject(proposal)) {
                    if (!angular.isArray(self.proposals)) {
                        self.proposals = [];
                    }
                    var notFound = true;
                    for (var index = 0; notFound && index < self.proposals.length; index++) {
                        var prop = self.proposals[index];
                        if (angular.isObject(prop) && angular.equals(proposal.proposalGuid, prop.proposalGuid)) {
                            angular.merge(prop, proposal);
                            notFound = false;
                        }
                    }
                    if (notFound) {
                        self.proposals.splice(0, 0, proposal);
                    }
                    countProposals();
                }
                else {
                    $log.error('dbProposalList: updateProposal parameter invalid');
                }
            }

            function updateEvents(events) {
                $log.debug("dbProposalList: updateEvents");
                if (angular.isArray(events)) {
                    angular.forEach(events, function (event) {
                        if (angular.isObject(event)) {
                            switch (event.typeName) {
                                case CONST.MTGEVENT.REMARKPUBLISHED:
                                case CONST.MTGEVENT.REMARKUPDATED:
                                    if (angular.isObject(event.proposal) && angular.equals(event.proposal.topicGuid, topicGuid)) {
                                        updateProposal(event.proposal);
                                    }
                                    break;
                                default:
                                    $log.error('dbProposalList: updateEvents unsupported type');
                                    break;
                            }
                        }
                    });
                }
                else {
                    $log.error('dbProposalList: updateEvents parameter invalid');
                }
            }

            function getProposals(guid) {
                $log.debug("dbProposalList: getProposals: " + guid);
                if (angular.isString(guid)) {
                    self.proposals = [];
                    AhjoProposalsSrv.get({ 'guid': guid }).$promise.then(function (response) {
                        $log.debug("dbProposalList: get then");
                        if (angular.isObject(response) && angular.isArray(response.objects)) {
                            angular.forEach(response.objects, function (p) {
                                if (angular.isObject(p) && angular.isString(p.proposalGuid)) {
                                    this.push(angular.copy(p));
                                }
                            }, self.proposals);
                        }
                        else {
                            $log.error('dbProposalList: getProposals invalid response');
                        }
                    }, function (error) {
                        $log.error("dbProposalList: get error: " + JSON.stringify(error));
                    }, function (notify) {
                        $log.debug("dbProposalList: get notify: " + JSON.stringify(notify));
                    }).finally(function () {
                        $log.debug("dbProposalList: get finally: ");
                        var events = angular.copy(StorageSrv.getKey(CONST.KEY.PROPOSAL_EVENT_ARRAY));
                        updateEvents(events);
                        countProposals();
                    });
                }
                else {
                    $log.error('dbProposalList: getProposals parameter invalid');
                }
            }

            function addProposal(type) {
                $log.debug("dbProposalList: addProposal: " + type);
                if (angular.isObject(type)) {
                    if (!angular.isArray(self.proposals)) {
                        self.proposals = [];
                    }
                    var draft = createDraft(type.value);
                    self.proposals.splice(0, 0, draft);
                    countProposals();
                    checkProposals();
                }
                else {
                    $log.error('dbProposalList: addProposal parameter invalid');
                }
            }

            self.remove = function (data) {
                $log.debug("dbProposalList: remove: " + JSON.stringify(data));
                if (angular.isObject(data)) {
                    removeProposal(data.proposal);
                }
                else {
                    $log.error('dbProposalList: remove parameter invalid');
                }
            };

            self.add = function (data) {
                $log.debug("dbProposalList: add: " + JSON.stringify(data));
                if (angular.isObject(data) && angular.isObject(data.proposal)) {

                    var exists = false;
                    for (var index = 0; !exists && index < self.proposals.length; index++) {
                        var item = self.proposals[index];
                        if (angular.equals(item.proposalGuid, data.proposal.proposalGuid)) {
                            angular.merge(item, data.proposal);
                            exists = true;
                        }
                    }
                    if (!exists) {
                        self.proposals.splice(0, 0, data.proposal);
                    }

                }
                else {
                    $log.error('dbProposalList: add proposal missing');
                }
            };

            self.addProposalClicked = function (type) {
                addProposal(type);
            };

            self.toggleAll = function () {
                self.isAllOpen = !self.isAllOpen;
                self.btnText = self.isAllOpen ? 'STR_CLOSE_ALL' : 'STR_OPEN_ALL';
                $rootScope.$emit(PROPS.TOGGLE, self.isAllOpen);
            };

            $scope.$watch(function () {
                return {
                    topic: $scope.topic
                };
            }, function (data) {
                if (angular.isObject(data) && angular.isObject(data.topic) && !angular.equals(topicGuid, data.topic.topicGuid)) {
                    personGuid = data.topic.userPersonGuid;
                    topicGuid = data.topic.topicGuid;
                    isCityCouncil = data.topic.isCityCouncil;
                    getProposals(topicGuid);
                    setTypes();
                }

            }, true);

            $scope.$watch(function () {
                return StorageSrv.getKey(CONST.KEY.PROPOSAL_EVENT_ARRAY);
            }, function (events, oldEvents) {
                if (!angular.equals(events, oldEvents)) {
                    updateEvents(events);
                }
            });

            var proposalWatcher = $rootScope.$on(PROPS.UPDATED, function (event, data) {
                if (angular.isObject(data) && angular.isObject(data.sender)) {
                    if (self.proposals.indexOf(data.sender) >= 0) {
                        checkProposals();
                    }
                }
            });

            var deleteWatcher = $rootScope.$on(CONST.PROPOSALDELETED, function (event, data) {
                if (angular.isObject(data) && angular.isArray(data.deleted)) {
                    angular.forEach(data.deleted, function (e) {
                        if (angular.isObject(e) && angular.equals(e.topicGuid, topicGuid)) {
                            removeProposal(e.deletedProposal);
                        }
                    }, this);
                }
            });

            $scope.$on('$destroy', proposalWatcher);
            $scope.$on('$destroy', deleteWatcher);

            $scope.$on('$destroy', function () {
                $log.debug("dbProposalList: DESTROY");
            });

            self.btnText = self.isAllOpen ? 'STR_CLOSE_ALL' : 'STR_OPEN_ALL';
        }];

        return {
            scope: {
                topic: '='
            },
            templateUrl: 'directives/proposalList/proposalList.Directive.html',
            restrict: 'AE',
            controller: controller,
            controllerAs: 'c',
            replace: 'true'
        };
    }]);
<|endoftext|>


<commit_before>/**
 * Copyright 2015 StreamSets Inc.
 *
 * Licensed under the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Service for launching Contextual Help.
 */

angular.module('dataCollectorApp.common')
  .service('contextHelpService', function($rootScope, $q, configuration, api, pipelineConstant, pipelineService) {

    // pre-populate with some static configurations
    var helpIds = {
        "pipeline-configuration": "index.html#Pipeline_Configuration/ConfiguringAPipeline.html",
        "pipeline-preview": "index.html#Data_Preview/PreviewingaSingleStage.html#task_cxd_p25_qq",
        "pipeline-snapshot": "index.html#Pipeline_Monitoring/ReviewingSnapshotData.html",
        "pipeline-monitoring": "index.html#Pipeline_Monitoring/PipelineMonitoring.html#concept_hsp_tnt_lq",
        "errors-tab": "index.html#Pipeline_Monitoring/MonitoringErrors.html#concept_pd3_crv_yr",
        "data-rules-tab": "index.html#Alerts/DataAlerts.html#concept_tpm_rsk_zq",
        "metric-rules-tab": "index.html#Alerts/MetricAlerts.html#concept_abj_nsk_zq",
        "data-drift-rules-tab": "index.html#Alerts/DataDriftAlerts.html#concept_wbz_mkk_p5"
      },
      buildInfo = {},
      helpWindow;

    this.configInitPromise = $q.all([
      api.admin.getBuildInfo(),
      pipelineService.init(),
      configuration.init()]
    ).then(function(results) {
      var stageConfigDefinitions = pipelineService.getStageDefinitions();
      angular.forEach(stageConfigDefinitions, function(stageConfigDefinition) {
        helpIds[stageConfigDefinition.name] = stageConfigDefinition.onlineHelpRefUrl;
      });
      buildInfo = results[0].data;
    });

    this.launchHelp = function(stagename) {
      this.configInitPromise.then(function() {
        var uiHelpBaseURL, helpURL,
          relativeURL = helpIds[stagename];

        uiHelpBaseURL = getHelpBaseUrl();

        helpURL = uiHelpBaseURL + '/' + (relativeURL || 'index.html');

        if(typeof(helpWindow) == 'undefined' || helpWindow.closed) {
          helpWindow = window.open(helpURL);
        } else {
          helpWindow.location.href = helpURL;
          helpWindow.focus();
        }

      });
    };

    this.launchHelpContents = function() {
      this.configInitPromise.then(function() {
        var uiHelpBaseURL, helpURL;
        uiHelpBaseURL = getHelpBaseUrl();
        helpURL = uiHelpBaseURL + '/index.html';

        if(typeof(helpWindow) == 'undefined' || helpWindow.closed) {
          helpWindow = window.open(helpURL);
        } else {
          helpWindow.location.href = helpURL;
          helpWindow.focus();
        }

      });
    };

    var getHelpBaseUrl = function() {
      var uiHelpBaseURL;
      if ($rootScope.$storage.helpLocation === pipelineConstant.HOSTED_HELP && navigator && navigator.onLine) {
        if (buildInfo.version.indexOf('-SNAPSHOT') === -1) {
          uiHelpBaseURL = 'https://www.streamsets.com/documentation/datacollector/' + buildInfo.version + '/help';
        } else {
          uiHelpBaseURL = 'https://streamsets.com/documentation/datacollector/latest/help/';
        }
      } else {
        uiHelpBaseURL = configuration.getUILocalHelpBaseURL();
      }
      return uiHelpBaseURL;
    };

  });
<commit_msg>SDC-4775. Fix help URLs for doc structure change<commit_after>/**
 * Copyright 2015 StreamSets Inc.
 *
 * Licensed under the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Service for launching Contextual Help.
 */

angular.module('dataCollectorApp.common')
  .service('contextHelpService', function($rootScope, $q, configuration, api, pipelineConstant, pipelineService) {

    // pre-populate with some static configurations
    var helpIds = {
        "pipeline-configuration": "index.html#Pipeline_Configuration/PipelineConfiguration_title.html#task_xlv_jdw_kq",
        "pipeline-preview": "index.html#Data_Preview/DataPreview_Title.html#concept_jtn_s3m_lq",
        "pipeline-snapshot": "index.html#Pipeline_Monitoring/PipelineMonitoring_title.html#task_wvz_rfp_tq",
        "pipeline-monitoring": "index.html#Pipeline_Monitoring/PipelineMonitoring_title.html#concept_hsp_tnt_lq",
        "errors-tab": "index.html#Pipeline_Monitoring/PipelineMonitoring_title.html#concept_pd3_crv_yr",
        "data-rules-tab": "index.html#Alerts/RulesAlerts_title.html#concept_tpm_rsk_zq",
        "metric-rules-tab": "index.html#Alerts/RulesAlerts_title.html#concept_abj_nsk_zq",
        "data-drift-rules-tab": "index.html#Alerts/RulesAlerts_title.html#concept_wbz_mkk_p5"
      },
      buildInfo = {},
      helpWindow;

    this.configInitPromise = $q.all([
      api.admin.getBuildInfo(),
      pipelineService.init(),
      configuration.init()]
    ).then(function(results) {
      var stageConfigDefinitions = pipelineService.getStageDefinitions();
      angular.forEach(stageConfigDefinitions, function(stageConfigDefinition) {
        helpIds[stageConfigDefinition.name] = stageConfigDefinition.onlineHelpRefUrl;
      });
      buildInfo = results[0].data;
    });

    this.launchHelp = function(stagename) {
      this.configInitPromise.then(function() {
        var uiHelpBaseURL, helpURL,
          relativeURL = helpIds[stagename];

        uiHelpBaseURL = getHelpBaseUrl();

        helpURL = uiHelpBaseURL + '/' + (relativeURL || 'index.html');

        if(typeof(helpWindow) == 'undefined' || helpWindow.closed) {
          helpWindow = window.open(helpURL);
        } else {
          helpWindow.location.href = helpURL;
          helpWindow.focus();
        }

      });
    };

    this.launchHelpContents = function() {
      this.configInitPromise.then(function() {
        var uiHelpBaseURL, helpURL;
        uiHelpBaseURL = getHelpBaseUrl();
        helpURL = uiHelpBaseURL + '/index.html';

        if(typeof(helpWindow) == 'undefined' || helpWindow.closed) {
          helpWindow = window.open(helpURL);
        } else {
          helpWindow.location.href = helpURL;
          helpWindow.focus();
        }

      });
    };

    var getHelpBaseUrl = function() {
      var uiHelpBaseURL;
      if ($rootScope.$storage.helpLocation === pipelineConstant.HOSTED_HELP && navigator && navigator.onLine) {
        if (buildInfo.version.indexOf('-SNAPSHOT') === -1) {
          uiHelpBaseURL = 'https://www.streamsets.com/documentation/datacollector/' + buildInfo.version + '/help';
        } else {
          uiHelpBaseURL = 'https://streamsets.com/documentation/datacollector/latest/help/';
        }
      } else {
        uiHelpBaseURL = configuration.getUILocalHelpBaseURL();
      }
      return uiHelpBaseURL;
    };

  });
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const blindfold = require('blindfold');
const editor = require('editor');
const {homedir} = require('os');
const fs = require('fs');
const storj = require('storj-lib');
const path = require('path');
const mkdirp = require('mkdirp');
const stripJsonComments = require('strip-json-comments');
const storjshare_create = require('commander');
const {execSync} = require('child_process');
const utils = require('../lib/utils');

const defaultConfig = JSON.parse(stripJsonComments(fs.readFileSync(
  path.join(__dirname, '../example/farmer.config.json')
).toString()));

function vimIsInstalled() {
  try {
    execSync('which vim');
  } catch (err) {
    return false;
  }

  return true;
}

storjshare_create
  .description('generates a new share configuration')
  .option('--storj <addr>', 'specify the STORJ address (required)')
  .option('--key <privkey>', 'specify the private key')
  .option('--storage <path>', 'specify the storage path')
  .option('--size <maxsize>', 'specify share size (ex: 10GB, 1TB)')
  .option('--rpcport <port>', 'specify the rpc port number')
  .option('--rpcaddress <addr>', 'specify the rpc address')
  .option('--maxtunnels <tunnels>', 'specify the max tunnels')
  .option('--tunnelportmin <port>', 'specify min gateway port')
  .option('--tunnelportmax <port>', 'specify max gateway port')
  .option('--manualforwarding', 'do not use nat traversal strategies')
  .option('--logdir <path>', 'specify the log directory')
  .option('--noedit', 'do not open generated config in editor')
  .option('-o, --outfile <writepath>', 'write config to path')
  .parse(process.argv);

if (!storjshare_create.storj) {
  console.error('\n  no payment address was given, try --help');
  process.exit(1);
}

if (!utils.isValidEthereumAddress(storjshare_create.storj)) {
  console.error('\n SJCX addresses are no longer supported. Please enter ERC20 compatible ETH wallet address');
  process.exit(1);
}

if (!storjshare_create.key) {
  storjshare_create.key = storj.KeyPair().getPrivateKey();
}

if (!storjshare_create.storage) {
  storjshare_create.storage = path.join(
    homedir(),
    '.config/storjshare/shares',
    storj.KeyPair(storjshare_create.key).getNodeID()
  );
  mkdirp.sync(storjshare_create.storage);
}

if (!storjshare_create.outfile) {
  storjshare_create.outfile = path.join(
    homedir(),
    '.config/storjshare/configs',
    storj.KeyPair(storjshare_create.key).getNodeID() + '.json'
  );
}

if (!storjshare_create.logdir) {
  storjshare_create.logdir = path.join(
    homedir(),
    '.config/storjshare/logs'
  );
}

let exampleConfigPath = path.join(__dirname, '../example/farmer.config.json');
let exampleConfigString = fs.readFileSync(exampleConfigPath).toString();

function getDefaultConfigValue(prop) {
  return {
    value: blindfold(defaultConfig, prop),
    type: typeof blindfold(defaultConfig, prop)
  };
}

function replaceDefaultConfigValue(prop, value) {
  let defaultValue = getDefaultConfigValue(prop);

  function toStringReplace(prop, value, type) {
    switch (type) {
      case 'string':
        value = value.split('\\').join('\\\\'); // NB: Hack windows paths
        return`"${prop}": "${value}"`;
      case 'boolean':
      case 'number':
        return `"${prop}": ${value}`;
      default:
        return '';
    }
  }

  prop = prop.split('.').pop();
  exampleConfigString = exampleConfigString.replace(
    toStringReplace(prop, defaultValue.value, defaultValue.type),
    toStringReplace(prop, value, defaultValue.type)
  );
}

replaceDefaultConfigValue('paymentAddress', storjshare_create.storj);
replaceDefaultConfigValue('networkPrivateKey', storjshare_create.key);
replaceDefaultConfigValue('storagePath',
                          path.normalize(storjshare_create.storage));
replaceDefaultConfigValue('loggerOutputFile',
                          path.normalize(storjshare_create.logdir));

const optionalReplacements = [
  { option: storjshare_create.size, name: 'storageAllocation' },
  { option: storjshare_create.rpcaddress, name: 'rpcAddress' },
  { option: storjshare_create.rpcport, name: 'rpcPort' },
  { option: storjshare_create.maxtunnels, name: 'maxTunnels' },
  { option: storjshare_create.tunnelportmin, name: 'tunnelGatewayRange.min' },
  { option: storjshare_create.tunnelportmax, name: 'tunnelGatewayRange.max' },
  { option: storjshare_create.manualforwarding, name: 'doNotTraverseNat' }
];

optionalReplacements.forEach((repl) => {
  if (repl.option) {
    replaceDefaultConfigValue(repl.name, repl.option);
  }
});

let outfile = path.isAbsolute(storjshare_create.outfile) ?
                path.normalize(storjshare_create.outfile) :
                path.join(process.cwd(), storjshare_create.outfile);

try {
  fs.writeFileSync(outfile, exampleConfigString);
} catch (err) {
  console.log (`\n  failed to write config, reason: ${err.message}`);
  process.exit(1);
}

console.log(`\n  * configuration written to ${outfile}`);

if (!storjshare_create.noedit) {
  console.log('  * opening in your favorite editor to tweak before running');
  editor(outfile, {
    // NB: Not all distros ship with vim, so let's use GNU Nano
    editor: process.platform === 'win32'
            ? null
            : (vimIsInstalled() ? 'vim' : 'nano')
  }, () => {
    console.log('  ...');
    console.log(`  * use new config: storjshare start --config ${outfile}`);
  });
}
<commit_msg>linter<commit_after>#!/usr/bin/env node

'use strict';

const blindfold = require('blindfold');
const editor = require('editor');
const {homedir} = require('os');
const fs = require('fs');
const storj = require('storj-lib');
const path = require('path');
const mkdirp = require('mkdirp');
const stripJsonComments = require('strip-json-comments');
const storjshare_create = require('commander');
const {execSync} = require('child_process');
const utils = require('../lib/utils');

const defaultConfig = JSON.parse(stripJsonComments(fs.readFileSync(
  path.join(__dirname, '../example/farmer.config.json')
).toString()));

function vimIsInstalled() {
  try {
    execSync('which vim');
  } catch (err) {
    return false;
  }

  return true;
}

storjshare_create
  .description('generates a new share configuration')
  .option('--storj <addr>', 'specify the STORJ address (required)')
  .option('--key <privkey>', 'specify the private key')
  .option('--storage <path>', 'specify the storage path')
  .option('--size <maxsize>', 'specify share size (ex: 10GB, 1TB)')
  .option('--rpcport <port>', 'specify the rpc port number')
  .option('--rpcaddress <addr>', 'specify the rpc address')
  .option('--maxtunnels <tunnels>', 'specify the max tunnels')
  .option('--tunnelportmin <port>', 'specify min gateway port')
  .option('--tunnelportmax <port>', 'specify max gateway port')
  .option('--manualforwarding', 'do not use nat traversal strategies')
  .option('--logdir <path>', 'specify the log directory')
  .option('--noedit', 'do not open generated config in editor')
  .option('-o, --outfile <writepath>', 'write config to path')
  .parse(process.argv);

if (!storjshare_create.storj) {
  console.error('\n  no payment address was given, try --help');
  process.exit(1);
}

if (!utils.isValidEthereumAddress(storjshare_create.storj)) {
  console.error('\n SJCX addresses are no longer supported. \
Please enter ERC20 compatible ETH wallet address');
  process.exit(1);
}

if (!storjshare_create.key) {
  storjshare_create.key = storj.KeyPair().getPrivateKey();
}

if (!storjshare_create.storage) {
  storjshare_create.storage = path.join(
    homedir(),
    '.config/storjshare/shares',
    storj.KeyPair(storjshare_create.key).getNodeID()
  );
  mkdirp.sync(storjshare_create.storage);
}

if (!storjshare_create.outfile) {
  storjshare_create.outfile = path.join(
    homedir(),
    '.config/storjshare/configs',
    storj.KeyPair(storjshare_create.key).getNodeID() + '.json'
  );
}

if (!storjshare_create.logdir) {
  storjshare_create.logdir = path.join(
    homedir(),
    '.config/storjshare/logs'
  );
}

let exampleConfigPath = path.join(__dirname, '../example/farmer.config.json');
let exampleConfigString = fs.readFileSync(exampleConfigPath).toString();

function getDefaultConfigValue(prop) {
  return {
    value: blindfold(defaultConfig, prop),
    type: typeof blindfold(defaultConfig, prop)
  };
}

function replaceDefaultConfigValue(prop, value) {
  let defaultValue = getDefaultConfigValue(prop);

  function toStringReplace(prop, value, type) {
    switch (type) {
      case 'string':
        value = value.split('\\').join('\\\\'); // NB: Hack windows paths
        return`"${prop}": "${value}"`;
      case 'boolean':
      case 'number':
        return `"${prop}": ${value}`;
      default:
        return '';
    }
  }

  prop = prop.split('.').pop();
  exampleConfigString = exampleConfigString.replace(
    toStringReplace(prop, defaultValue.value, defaultValue.type),
    toStringReplace(prop, value, defaultValue.type)
  );
}

replaceDefaultConfigValue('paymentAddress', storjshare_create.storj);
replaceDefaultConfigValue('networkPrivateKey', storjshare_create.key);
replaceDefaultConfigValue('storagePath',
                          path.normalize(storjshare_create.storage));
replaceDefaultConfigValue('loggerOutputFile',
                          path.normalize(storjshare_create.logdir));

const optionalReplacements = [
  { option: storjshare_create.size, name: 'storageAllocation' },
  { option: storjshare_create.rpcaddress, name: 'rpcAddress' },
  { option: storjshare_create.rpcport, name: 'rpcPort' },
  { option: storjshare_create.maxtunnels, name: 'maxTunnels' },
  { option: storjshare_create.tunnelportmin, name: 'tunnelGatewayRange.min' },
  { option: storjshare_create.tunnelportmax, name: 'tunnelGatewayRange.max' },
  { option: storjshare_create.manualforwarding, name: 'doNotTraverseNat' }
];

optionalReplacements.forEach((repl) => {
  if (repl.option) {
    replaceDefaultConfigValue(repl.name, repl.option);
  }
});

let outfile = path.isAbsolute(storjshare_create.outfile) ?
                path.normalize(storjshare_create.outfile) :
                path.join(process.cwd(), storjshare_create.outfile);

try {
  fs.writeFileSync(outfile, exampleConfigString);
} catch (err) {
  console.log (`\n  failed to write config, reason: ${err.message}`);
  process.exit(1);
}

console.log(`\n  * configuration written to ${outfile}`);

if (!storjshare_create.noedit) {
  console.log('  * opening in your favorite editor to tweak before running');
  editor(outfile, {
    // NB: Not all distros ship with vim, so let's use GNU Nano
    editor: process.platform === 'win32'
            ? null
            : (vimIsInstalled() ? 'vim' : 'nano')
  }, () => {
    console.log('  ...');
    console.log(`  * use new config: storjshare start --config ${outfile}`);
  });
}
<|endoftext|>


<commit_before>/*global describe,it,element,by,takeScreenshot,expect,browser*/
describe("sap.m.TextArea", function() {
	"use strict";

	// initial loading
	it("should load test page", function () {
		expect(takeScreenshot()).toLookAs("initial");
	});

	//TextArea with 50% width
	it("should vizualize a text area with 50% width", function(){
		var fiftyPercentTextArea = element(by.id("__area1"));
		expect(takeScreenshot(fiftyPercentTextArea)).toLookAs("fifty_percent_width");
	});

	//TextArea - Default
	it("should vizualize a simple text area", function(){
		var defaultTextArea = element(by.id("__area2"));
		expect(takeScreenshot(defaultTextArea)).toLookAs("default_textarea");
	});

	//TextArea - Disabled growing
	it("should vizualize a text area without growing", function(){
		var notGrowingTextArea = element(by.id("__area4"));
		expect(takeScreenshot(notGrowingTextArea)).toLookAs("not_growing_textarea");
	});

	//TextArea with 2 rows, 20 cols - Warning State
	it("should vizualize a text area with 2 rows and 20 cols in warning state", function(){
		var warningResizedTextArea = element(by.id("__area7"));
		browser.executeScript('document.getElementById("__area7").scrollIntoView()').then(function() {
			expect(takeScreenshot(warningResizedTextArea)).toLookAs("twoRows_twentyCols_warning_state");
		});
	});

	//Textarea with 90% width
	it("should vizualize a text area with 90% width", function(){
		var nintyPercentWidthTextArea = element(by.id("__area8"));
		browser.executeScript('document.getElementById("__area8").scrollIntoView()').then(function() {
			expect(takeScreenshot(nintyPercentWidthTextArea)).toLookAs("ninty_percent_width");
		});
	});

	//Textarea - Disabled
	it("should vizualize a disabled text area", function(){
		var disabledTextArea = element(by.id("__area9"));
		browser.executeScript('document.getElementById("__area9").scrollIntoView()').then(function() {
			disabledTextArea.click();
			expect(takeScreenshot(disabledTextArea)).toLookAs("disabled_state");
		});
	});

	//TextArea - Warning State
	it("should vizualize a text area with warning state", function(){
		var warningStateTextArea = element(by.id("__area10"));
		browser.executeScript('document.getElementById("__area10").scrollIntoView()').then(function() {
			expect(takeScreenshot(warningStateTextArea)).toLookAs("warning_state");
		});
	});

	//TextArea - Error State
	it("should vizualize a text area with error state", function(){
		var errorStateTextArea = element(by.id("__area11"));
		browser.executeScript('document.getElementById("__area11").scrollIntoView()').then(function() {
			expect(takeScreenshot(errorStateTextArea)).toLookAs("error_state");
		});
	});

	//TextArea - Wrapping Off
	it("should vizualize a text area without wrapping ", function(){
		var offWrappingTextArea = element(by.id("__area12"));
		browser.executeScript('document.getElementById("__area12").scrollIntoView()').then(function() {
			expect(takeScreenshot(offWrappingTextArea)).toLookAs("wrapping_off");
		});
	});

	//TextArea - Not Editable
	it("should vizualize a not editable text area ", function(){
		var notEditableTextArea = element(by.id("__area13"));
		browser.executeScript('document.getElementById("__area13").scrollIntoView()').then(function() {
			notEditableTextArea.click();
			expect(takeScreenshot(notEditableTextArea)).toLookAs("not_editable_textarea");
		});
	});

	//TextArea with placeholder
	it("should vizualize a text area with placeholder", function(){
		var textAreaWithPlaceholder = element(by.id("__area14"));
		browser.executeScript('document.getElementById("__area14").scrollIntoView()').then(function() {
			expect(takeScreenshot(textAreaWithPlaceholder)).toLookAs("textarea_with_placeholder");
		});
	});

	//TextArea - Growing
	it("should vizualize a growing text area", function(){
		var growingTextArea = element(by.id("__area15"));
		browser.executeScript('document.getElementById("__area15").scrollIntoView()').then(function() {
			expect(takeScreenshot(growingTextArea)).toLookAs("growing_textarea");
		});
	});

	//TextArea - Set height and showExceededText=true
	it("TextArea and Label total height should be the set height", function(){
		var textAreaWithHeight = element(by.id("showExceededTextWithHeight"));
		expect(takeScreenshot(textAreaWithHeight)).toLookAs("showExceededText_with_height");
	});
});<commit_msg>[INTERNAL][FIX] sap.m.TextArea: Visual tests adjusted<commit_after>/*global describe,it,element,by,takeScreenshot,expect,browser*/
describe("sap.m.TextArea", function() {
	"use strict";

	// initial loading
	it("should load test page", function () {
		expect(takeScreenshot()).toLookAs("initial");
	});

	//TextArea with 50% width
	it("should vizualize a text area with 50% width", function(){
		var fiftyPercentTextArea = element(by.id("__area1"));
		expect(takeScreenshot(fiftyPercentTextArea)).toLookAs("fifty_percent_width");
	});

	//TextArea - Default
	it("should vizualize a simple text area", function(){
		var defaultTextArea = element(by.id("__area2"));
		expect(takeScreenshot(defaultTextArea)).toLookAs("default_textarea");
	});

	//TextArea - Disabled growing
	it("should vizualize a text area without growing", function(){
		var notGrowingTextArea = element(by.id("__area4"));
		expect(takeScreenshot(notGrowingTextArea)).toLookAs("not_growing_textarea");
	});

	//TextArea with 2 rows, 20 cols - Warning State
	it("should vizualize a text area with 2 rows and 20 cols in warning state", function(){
		var warningResizedTextArea = element(by.id("__area7"));
		browser.executeScript('document.getElementById("__area7").scrollIntoView()').then(function() {
			expect(takeScreenshot(warningResizedTextArea)).toLookAs("twoRows_twentyCols_warning_state");
		});
	});

	//Textarea with 90% width
	it("should vizualize a text area with 90% width", function(){
		var nintyPercentWidthTextArea = element(by.id("__area8"));
		browser.executeScript('document.getElementById("__area8").scrollIntoView()').then(function() {
			expect(takeScreenshot(nintyPercentWidthTextArea)).toLookAs("ninty_percent_width");
		});
	});

	//Textarea - Disabled
	it("should vizualize a disabled text area", function(){
		var disabledTextArea = element(by.id("__area9"));
		browser.executeScript('document.getElementById("__area9").scrollIntoView()').then(function() {
			disabledTextArea.click();
			expect(takeScreenshot(disabledTextArea)).toLookAs("disabled_state");
		});
	});

	//TextArea - Warning State
	it("should vizualize a text area with warning state", function(){
		var warningStateTextArea = element(by.id("__area10"));
		browser.executeScript('document.getElementById("__area10").scrollIntoView()').then(function() {
			expect(takeScreenshot(warningStateTextArea)).toLookAs("warning_state");
		});
	});

	//TextArea - Error State
	it("should vizualize a text area with error state", function(){
		var errorStateTextArea = element(by.id("__area11"));
		browser.executeScript('document.getElementById("__area11").scrollIntoView()').then(function() {
			expect(takeScreenshot(errorStateTextArea)).toLookAs("error_state");
		});
	});

	//TextArea - Wrapping Off
	it("should vizualize a text area without wrapping ", function(){
		var offWrappingTextArea = element(by.id("__area12"));
		browser.executeScript('document.getElementById("__area12").scrollIntoView()').then(function() {
			expect(takeScreenshot(offWrappingTextArea)).toLookAs("wrapping_off");
		});
	});

	//TextArea - Not Editable
	it("should vizualize a not editable text area ", function(){
		var notEditableTextArea = element(by.id("__area13"));
		browser.executeScript('document.getElementById("__area13").scrollIntoView()').then(function() {
			notEditableTextArea.click();
			expect(takeScreenshot(notEditableTextArea)).toLookAs("not_editable_textarea");
		});
	});

	//TextArea with placeholder
	it("should vizualize a text area with placeholder", function(){
		var textAreaWithPlaceholder = element(by.id("__area14"));
		browser.executeScript('document.getElementById("__area14").scrollIntoView()').then(function() {
			expect(takeScreenshot(textAreaWithPlaceholder)).toLookAs("textarea_with_placeholder");
		});
	});

	//TextArea - Growing
	it("should vizualize a growing text area", function(){
		var growingTextArea = element(by.id("__area15"));
		browser.executeScript('document.getElementById("__area15").scrollIntoView()').then(function() {
			expect(takeScreenshot(growingTextArea)).toLookAs("growing_textarea");
		});
	});

	//TextArea - Set height and showExceededText=true
	it("TextArea and Label total height should be the set height", function(){
		browser.executeScript('document.getElementById("showExceededTextWithHeight").scrollIntoView()').then(function() {
			var textAreaWithHeight = element(by.id("showExceededTextWithHeight"));
			expect(takeScreenshot(textAreaWithHeight)).toLookAs("showExceededText_with_height");
		});
	});
});<|endoftext|>


<commit_before>define(function (require, exports, module) {
  'use strict';

  var L20n = require('../l20n');
  var io = require('./platform/io');

  var rtlLocales = ['ar', 'fa', 'he', 'ps', 'ur'];

  var ctx = L20n.getContext();

  bindPublicAPI();

  var bootstrapped = false;
  if (typeof(document) !== 'undefined') {
    bootstrap();
  }

  function bootstrap(lang) {
    bootstrapped = true;
    ctx.addEventListener('warning', console.error.bind(console));
    ctx.addEventListener('info', console.warn.bind(console));

    var availableLocales = [];
    var localePlaceable = /\{\{\s*locale\s*\}\}/;

    var head = document.head;
    var iniLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                         '[href$=".ini"]');
    var jsonLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                          '[href$=".json"]');

    for (var i = 0; i < jsonLinks.length; i++) {
      var parts = jsonLinks[i].getAttribute('href').split(localePlaceable);
      ctx.linkResource(function(locale) {
        return parts[0] + locale + parts[1];
      });
    }

    var scripts = head.querySelectorAll('script[type="application/l10n"]');
    for (var i = 0; i < scripts.length; i++) {
      // pass the node to save memory
      ctx.addDictionary(scripts[i], scripts[i].getAttribute('lang'));
    }

    if (document.readyState !== 'loading') {
      ctx.ready(translateDocument);
    } else {
      document.addEventListener('readystatechange', function() {
        ctx.ready(translateDocument);
      });
    }

    var iniToLoad = iniLinks.length;
    if (iniToLoad === 0) {
      return freeze(lang);
    }
    for (var i = 0; i < iniLinks.length; i++) {
      var url = iniLinks[i].getAttribute('href');
      io.load(url, iniLoaded.bind(null, url));
    }

    function iniLoaded(url, err, text) {
      if (err) {
        throw err;
      }
      var ini = parseINI(text, url);
      availableLocales.push.apply(availableLocales, ini.locales);
      for (var i = 0; i < ini.resources.length; i++) {
        var parts = ini.resources[i].split('en-US');
        ctx.linkResource(function(locale) {
          return parts[0] + locale + parts[1];
        });
      }
      iniToLoad--;
      if (iniToLoad == 0) {
        freeze(lang, availableLocales);
      }
    }

  }

  function freeze(lang, available) {
    if (!available) {
      var metaLocs = document.head.querySelector('meta[name="locales"]');
      if (metaLocs) {
        available = metaLocs.getAttribute('content').split(',')
                                                    .map(String.trim);
      } else {
        available = [];
      }
    }
    ctx.registerLocales('en-US', available);
    ctx.requestLocales(lang || navigator.language);

    // listen to language change events
    if ('mozSettings' in navigator && navigator.mozSettings) {
      navigator.mozSettings.addObserver('language.current', function(event) {
        ctx.requestLocales(event.settingValue);
      });
    }
  }

  var patterns = {
    ini: {
      section: /^\s*\[(.*)\]\s*$/,
      import: /^\s*@import\s+url\((.*)\)\s*$/i
    }
  };

  function parseINI(source, iniPath) {
    var entries = source.split(/[\r\n]+/);
    var locales = ['en-US'];
    var genericSection = true;
    var uris = [];

    for (var i = 0; i < entries.length; i++) {
      var line = entries[i];
      // we only care about en-US resources
      if (genericSection && patterns['ini']['import'].test(line)) {
        var match = patterns['ini']['import'].exec(line);
        var uri = relativePath(iniPath, match[1]);
        uris.push(uri);
        continue;
      }
      // but we need the list of all locales in the ini, too
      if (patterns['ini']['section'].test(line)) {
        genericSection = false;
        var match = patterns['ini']['section'].exec(line);
        locales.push(match[1]);
      }
    }
    return {
      locales: locales,
      resources: uris
    };
  }

  function relativePath(baseUrl, url) {
    if (url[0] == '/') {
      return url;
    }
    var dirs = baseUrl.split('/')
      .slice(0, -1)
      .concat(url.split('/'))
      .filter(function(elem) {
        return elem !== '.';
      });

    if (dirs[0] !== '' && dirs[0] !== '..') {
      // if the base path doesn't start with / or ..
      dirs.unshift('.');
    }

    return dirs.join('/');
  }

  function bindPublicAPI() {
    navigator.mozL10n = ctx;
    ctx.localize = function() {};
    ctx.language = {
      get code() {
        return ctx.supportedLocales[0];
      },
      set code(lang) {
        if (!bootstrapped) {
          bootstrap(lang);
        } else {
          ctx.requestLocales(lang);
        }
      },
      get direction() {
        if (rtlLocales.indexOf(ctx.supportedLocales[0]) >= 0) {
          return 'rtl';
        } else {
          return 'ltr';
        }
      }
    };
    ctx.getDictionary = getSubDictionary;
  }

  // return a sub-dictionary sufficient to translate a given fragment
  function getSubDictionary(fragment) {
    var ast = {
      type: 'WebL10n',
      body: []
    };

    if (!fragment) {
      ast.body = ctx.getSources();
      return ast;
    }

    var elements = getTranslatableChildren(fragment);

    for (var i = 0, l = elements.length; i < l; i++) {
      var id = elements[i].getAttribute('data-l10n-id');
      var source = ctx.getSource(id);
      ast.body.push(source);
      // check for any dependencies
      // XXX should this be recursive?
      if (source.value.type === 'ComplexString') {
        source.value.body.forEach(function (chunk) {
          if (chunk.type == 'Identifier') {
            ast.body.push(ctx.getSource(chunk.name));
          }
        });
      }
    }
    return ast;
  }

  function getTranslatableChildren(element) {
    return element ? element.querySelectorAll('*[data-l10n-id]') : [];
  }

  function getL10nAttributes(element) {
    if (!element) {
      return {};
    }

    var l10nId = element.getAttribute('data-l10n-id');
    var l10nArgs = element.getAttribute('data-l10n-args');
    var args = {};
    if (l10nArgs) {
      try {
        args = JSON.parse(l10nArgs);
      } catch (e) {
        consoleWarn('could not parse arguments for #' + l10nId);
      }
    }
    return { id: l10nId, args: args };
  }

  function translateDocument() {
    var nodes = document.querySelectorAll('[data-l10n-id]');
    for (var i = 0; i < nodes.length; i++) {
      translateNode(nodes[i]);
    }
    fireLocalizedEvent();
  }

  function translateNode(node) {
    var attrs = getL10nAttributes(node);
    node.textContent = navigator.mozL10n.get(attrs.id, attrs.args);
  }

  function fireLocalizedEvent() {
    var event = document.createEvent('Event');
    event.initEvent('localized', false, false);
    event.language = ctx.supportedLocales[0];
    window.dispatchEvent(event);
  }

  return L20n;
});
<commit_msg>don't use console.error<commit_after>define(function (require, exports, module) {
  'use strict';

  var L20n = require('../l20n');
  var io = require('./platform/io');

  var rtlLocales = ['ar', 'fa', 'he', 'ps', 'ur'];

  var ctx = L20n.getContext();

  bindPublicAPI();

  var bootstrapped = false;
  if (typeof(document) !== 'undefined') {
    bootstrap();
  }

  function bootstrap(lang) {
    bootstrapped = true;
    ctx.addEventListener('warning', console.warn.bind(console));
    ctx.addEventListener('info', console.warn.bind(console));

    var availableLocales = [];
    var localePlaceable = /\{\{\s*locale\s*\}\}/;

    var head = document.head;
    var iniLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                         '[href$=".ini"]');
    var jsonLinks = head.querySelectorAll('link[type="application/l10n"]' +
                                          '[href$=".json"]');

    for (var i = 0; i < jsonLinks.length; i++) {
      var parts = jsonLinks[i].getAttribute('href').split(localePlaceable);
      ctx.linkResource(function(locale) {
        return parts[0] + locale + parts[1];
      });
    }

    var scripts = head.querySelectorAll('script[type="application/l10n"]');
    for (var i = 0; i < scripts.length; i++) {
      // pass the node to save memory
      ctx.addDictionary(scripts[i], scripts[i].getAttribute('lang'));
    }

    if (document.readyState !== 'loading') {
      ctx.ready(translateDocument);
    } else {
      document.addEventListener('readystatechange', function() {
        ctx.ready(translateDocument);
      });
    }

    var iniToLoad = iniLinks.length;
    if (iniToLoad === 0) {
      return freeze(lang);
    }
    for (var i = 0; i < iniLinks.length; i++) {
      var url = iniLinks[i].getAttribute('href');
      io.load(url, iniLoaded.bind(null, url));
    }

    function iniLoaded(url, err, text) {
      if (err) {
        throw err;
      }
      var ini = parseINI(text, url);
      availableLocales.push.apply(availableLocales, ini.locales);
      for (var i = 0; i < ini.resources.length; i++) {
        var parts = ini.resources[i].split('en-US');
        ctx.linkResource(function(locale) {
          return parts[0] + locale + parts[1];
        });
      }
      iniToLoad--;
      if (iniToLoad == 0) {
        freeze(lang, availableLocales);
      }
    }

  }

  function freeze(lang, available) {
    if (!available) {
      var metaLocs = document.head.querySelector('meta[name="locales"]');
      if (metaLocs) {
        available = metaLocs.getAttribute('content').split(',')
                                                    .map(String.trim);
      } else {
        available = [];
      }
    }
    ctx.registerLocales('en-US', available);
    ctx.requestLocales(lang || navigator.language);

    // listen to language change events
    if ('mozSettings' in navigator && navigator.mozSettings) {
      navigator.mozSettings.addObserver('language.current', function(event) {
        ctx.requestLocales(event.settingValue);
      });
    }
  }

  var patterns = {
    ini: {
      section: /^\s*\[(.*)\]\s*$/,
      import: /^\s*@import\s+url\((.*)\)\s*$/i
    }
  };

  function parseINI(source, iniPath) {
    var entries = source.split(/[\r\n]+/);
    var locales = ['en-US'];
    var genericSection = true;
    var uris = [];

    for (var i = 0; i < entries.length; i++) {
      var line = entries[i];
      // we only care about en-US resources
      if (genericSection && patterns['ini']['import'].test(line)) {
        var match = patterns['ini']['import'].exec(line);
        var uri = relativePath(iniPath, match[1]);
        uris.push(uri);
        continue;
      }
      // but we need the list of all locales in the ini, too
      if (patterns['ini']['section'].test(line)) {
        genericSection = false;
        var match = patterns['ini']['section'].exec(line);
        locales.push(match[1]);
      }
    }
    return {
      locales: locales,
      resources: uris
    };
  }

  function relativePath(baseUrl, url) {
    if (url[0] == '/') {
      return url;
    }
    var dirs = baseUrl.split('/')
      .slice(0, -1)
      .concat(url.split('/'))
      .filter(function(elem) {
        return elem !== '.';
      });

    if (dirs[0] !== '' && dirs[0] !== '..') {
      // if the base path doesn't start with / or ..
      dirs.unshift('.');
    }

    return dirs.join('/');
  }

  function bindPublicAPI() {
    navigator.mozL10n = ctx;
    ctx.localize = function() {};
    ctx.language = {
      get code() {
        return ctx.supportedLocales[0];
      },
      set code(lang) {
        if (!bootstrapped) {
          bootstrap(lang);
        } else {
          ctx.requestLocales(lang);
        }
      },
      get direction() {
        if (rtlLocales.indexOf(ctx.supportedLocales[0]) >= 0) {
          return 'rtl';
        } else {
          return 'ltr';
        }
      }
    };
    ctx.getDictionary = getSubDictionary;
  }

  // return a sub-dictionary sufficient to translate a given fragment
  function getSubDictionary(fragment) {
    var ast = {
      type: 'WebL10n',
      body: []
    };

    if (!fragment) {
      ast.body = ctx.getSources();
      return ast;
    }

    var elements = getTranslatableChildren(fragment);

    for (var i = 0, l = elements.length; i < l; i++) {
      var id = elements[i].getAttribute('data-l10n-id');
      var source = ctx.getSource(id);
      ast.body.push(source);
      // check for any dependencies
      // XXX should this be recursive?
      if (source.value.type === 'ComplexString') {
        source.value.body.forEach(function (chunk) {
          if (chunk.type == 'Identifier') {
            ast.body.push(ctx.getSource(chunk.name));
          }
        });
      }
    }
    return ast;
  }

  function getTranslatableChildren(element) {
    return element ? element.querySelectorAll('*[data-l10n-id]') : [];
  }

  function getL10nAttributes(element) {
    if (!element) {
      return {};
    }

    var l10nId = element.getAttribute('data-l10n-id');
    var l10nArgs = element.getAttribute('data-l10n-args');
    var args = {};
    if (l10nArgs) {
      try {
        args = JSON.parse(l10nArgs);
      } catch (e) {
        consoleWarn('could not parse arguments for #' + l10nId);
      }
    }
    return { id: l10nId, args: args };
  }

  function translateDocument() {
    var nodes = document.querySelectorAll('[data-l10n-id]');
    for (var i = 0; i < nodes.length; i++) {
      translateNode(nodes[i]);
    }
    fireLocalizedEvent();
  }

  function translateNode(node) {
    var attrs = getL10nAttributes(node);
    node.textContent = navigator.mozL10n.get(attrs.id, attrs.args);
  }

  function fireLocalizedEvent() {
    var event = document.createEvent('Event');
    event.initEvent('localized', false, false);
    event.language = ctx.supportedLocales[0];
    window.dispatchEvent(event);
  }

  return L20n;
});
<|endoftext|>


<commit_before>function fitImgs(){
$("img").each(function(id){
  //alert($(window).height())
  //console.log('window.height ' + $(window).height())
  //var otherHeight = -$(this).parentsUntil('section').height(); //don't count self's container's size
  var otherHeight = -$(this).height(); //don't count self's container's size
  //console.log(otherHeight)
  //console.log('otherHeight ' + otherHeight)
  var slide = $(this).parentsUntil('section').parent();
  slide.children().each(function(id){
    otherHeight += $(this).height();
    //console.log($(this).height());
  });
  //console.log('otherHeight ' + otherHeight)

  //console.log(otherHeight)
  //May need to scale up a little
  var remainHeight = ($(window).height() - slide.offset()['top'] ) - otherHeight;//5: margin
  //console.log('remainHeight ' +remainHeight)
  $(this).css("max-height",  remainHeight * 0.95);
  //$(this).css("min-height",  remainHeight * 0.8);
})
}
window.onresize = fitImgs;
fitImgs();
<commit_msg>Resize image on every page turn<commit_after>function fitImgs(){
$("img").each(function(id){
  //alert($(window).height())
  //console.log('window.height ' + $(window).height())
  //var otherHeight = -$(this).parentsUntil('section').height(); //don't count self's container's size
  var otherHeight = -$(this).height(); //don't count self's container's size
  //console.log(otherHeight)
  //console.log('otherHeight ' + otherHeight)
  var slide = $(this).parentsUntil('section').parent();
  slide.children().each(function(id){
    otherHeight += $(this).height();
    //console.log($(this).height());
  });
  //console.log('otherHeight ' + otherHeight)

  //console.log(otherHeight)
  //May need to scale up a little
  var remainHeight = ($(window).height() - slide.offset()['top'] ) - otherHeight;//5: margin
  //console.log('remainHeight ' +remainHeight)
  $(this).css("max-height",  remainHeight * 0.95);
  //$(this).css("min-height",  remainHeight * 0.8);
})
}
window.onresize = fitImgs;
Reveal.addEventListener('slidechanged', function(event){
  // event.previousSlide, event.currentSlide, event.indexh, event.indexv
  fitImgs();
})
/*
Reveal.addEventListener('ready', function(event){
  // event.previousSlide, event.currentSlide, event.indexh, event.indexv
  fitImgs();
})
*/
fitImgs();
<|endoftext|>


<commit_before>import React, { Component } from "react";
import { View, StyleSheet, Dimensions } from "react-native";
import Timer from "./timer";
import Rx from "rx";

export default class ComponentEntitySystem extends Component {
  constructor(props) {
    super(props);

    this.state = props.initState || props.initialState || props.entities || {};
    this.systems = props.systems || [];
    this.timer = new Timer();
    this.timer.subscribe(this.update);
    this.touches = [];
    this.screen = Dimensions.get("window");
    this.previousTime = null;
    this.previousDelta = null;
    this.events = [];
    let push = this.events.push;
    this.events.push = e => {
      let res = push.call(this.events, e);
      if (this.props.onEvent) this.props.onEvent(e);
      return res;
    };

    this.touchStart = new Rx.Subject();
    this.touchMove = new Rx.Subject();
    this.touchEnd = new Rx.Subject();
    this.touchPress = this.touchStart.flatMap(e =>
      this.touchEnd
        .first(x => x.identifier === e.identifier)
        .timeout(200, Rx.Observable.empty())
    );
    this.longTouch = this.touchStart.flatMap(e =>
      Rx.Observable
        .return(e)
        .delay(700)
        .takeUntil(
          this.touchMove
            .merge(this.touchEnd)
            .first(x => x.identifier === e.identifier)
        )
    );

    this.onTouchStart = new Rx.CompositeDisposable();
    this.onTouchStart.add(
      this.touchStart
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "start", event: e });
          });
        })
        .subscribe(group => {
          this.onTouchStart.add(group.subscribe());
        })
    );

    this.onTouchMove = new Rx.CompositeDisposable();
    this.onTouchMove.add(
      Rx.Observable
        .merge(
          this.touchStart.map(x => Object.assign(x, { type: "start" })),
          this.touchMove.map(x => Object.assign(x, { type: "move" })),
          this.touchEnd.map(x => Object.assign(x, { type: "end" }))
        )
        .groupBy(e => e.identifier)
        .map(group => {
          return group.pairwise().map(([e1, e2]) => {
            if (e1.type !== "end") {
              this.touches.push({
                id: group.key,
                type: "move",
                event: e2,
                delta: {
                  locationX: e2.locationX - e1.locationX,
                  locationY: e2.locationY - e1.locationY,
                  pageX: e2.pageX - e1.pageX,
                  pageY: e2.pageY - e1.pageY,
                  timestamp: e2.timestamp - e1.timestamp
                }
              });
            }
          });
        })
        .subscribe(group => {
          this.onTouchMove.add(group.subscribe());
        })
    );

    this.onTouchEnd = new Rx.CompositeDisposable();
    this.onTouchEnd.add(
      this.touchEnd
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "end", event: e });
          });
        })
        .subscribe(group => {
          this.onTouchEnd.add(group.subscribe());
        })
    );

    this.onTouchPress = new Rx.CompositeDisposable();
    this.onTouchPress.add(
      this.touchPress
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "press", event: e });
          });
        })
        .subscribe(group => {
          this.onTouchPress.add(group.subscribe());
        })
    );

    this.onLongTouch = new Rx.CompositeDisposable();
    this.onLongTouch.add(
      this.longTouch
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "long-press", event: e });
          });
        })
        .subscribe(group => {
          this.onLongTouch.add(group.subscribe());
        })
    );
  }

  componentDidMount() {
    this.start();
  }

  componentWillUnmount() {
    this.timer.stop();
    this.timer.unsubscribe(this.update);

    this.touchStart.dispose();
    this.touchMove.dispose();
    this.touchEnd.dispose();

    this.onTouchStart.dispose();
    this.onTouchMove.dispose();
    this.onTouchEnd.dispose();
    this.onTouchPress.dispose();
    this.onLongTouch.dispose();
  }

  start = () => {
    this.timer.start();
    this.events.push({ type: "started" });
  };

  stop = () => {
    this.timer.stop();
    this.events.push({ type: "stopped" });
  };

  update = currentTime => {
    let args = {
      touches: this.touches,
      screen: this.screen,
      events: this.events,
      time: {
        current: currentTime,
        previous: this.previousTime,
        delta: currentTime - (this.previousTime || currentTime),
        previousDelta: this.previousDelta
      }
    };

    let newState = this.systems.reduce(
      (state, sys) => sys(state, args),
      this.state
    );

    this.touches.length = 0;
    this.events.length = 0;
    this.previousTime = currentTime;
    this.previousDelta = args.time.delta;
    this.setState(newState);
  };

  publishEvent = e => {
    this.events.push(e);
  }

  onPublishTouchStart = e => {
    this.touchStart.onNext(e.nativeEvent);
  };

  onPublishTouchMove = e => {
    this.touchMove.onNext(e.nativeEvent);
  };

  onPublishTouchEnd = e => {
    this.touchEnd.onNext(e.nativeEvent);
  };

  onLayout = () => {
    this.screen = Dimensions.get("window");
    this.forceUpdate();
  };

  render() {
    return (
      <View style={[css.container, this.props.style]} onLayout={this.onLayout}>

        <View
          style={css.entityContainer}
          onTouchStart={this.onPublishTouchStart}
          onTouchMove={this.onPublishTouchMove}
          onTouchEnd={this.onPublishTouchEnd}
        >
          {Object.keys(this.state)
            .filter(key => this.state[key].renderable)
            .map(key => {
              let entity = this.state[key];
              if (typeof entity.renderable === "object")
                return <entity.renderable.type key={key} {...entity} />;
              else if (typeof entity.renderable === "function")
                return <entity.renderable key={key} {...entity} />;
            })}
        </View>

        <View
          pointerEvents={"box-none"}
          style={[
            css.childrenContainer,
            { width: this.screen.width, height: this.screen.height }
          ]}
        >
          {this.props.children}
        </View>

      </View>
    );
  }
}

const css = StyleSheet.create({
  container: {
    flex: 1
  },
  entityContainer: {
    flex: 1,
    //-- Looks like Android requires bg color here
    //-- to register touches. If we didn't worry about
    //-- 'children' (foreground) components capturing events,
    //-- this whole shenanigan could be avoided..
    backgroundColor: "transparent"
  },
  childrenContainer: {
    top: 0,
    left: 0,
    position: "absolute"
  }
});
<commit_msg>Added some default props and a bit of refactoring<commit_after>import React, { Component } from "react";
import { View, StyleSheet, Dimensions } from "react-native";
import Timer from "./timer";
import Rx from "rx";

export default class ComponentEntitySystem extends Component {
  constructor(props) {
    super(props);
    this.state =
      props.initState ||
      props.initialState ||
      props.state ||
      props.initEntities ||
      props.initialEntities ||
      props.entities;
    this.timer = new Timer();
    this.timer.subscribe(this.update);
    this.touches = [];
    this.screen = Dimensions.get("window");
    this.previousTime = null;
    this.previousDelta = null;
    this.events = [];
    let push = this.events.push;
    this.events.push = e => {
      let res = push.call(this.events, e);
      if (this.props.onEvent) this.props.onEvent(e);
      return res;
    };

    this.touchStart = new Rx.Subject();
    this.touchMove = new Rx.Subject();
    this.touchEnd = new Rx.Subject();
    this.touchPress = this.touchStart.flatMap(e =>
      this.touchEnd
        .first(x => x.identifier === e.identifier)
        .timeout(200, Rx.Observable.empty())
    );
    this.longTouch = this.touchStart.flatMap(e =>
      Rx.Observable
        .return(e)
        .delay(700)
        .takeUntil(
          this.touchMove
            .merge(this.touchEnd)
            .first(x => x.identifier === e.identifier)
        )
    );

    this.onTouchStart = new Rx.CompositeDisposable();
    this.onTouchStart.add(
      this.touchStart
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "start", event: e });
          });
        })
        .subscribe(group => {
          this.onTouchStart.add(group.subscribe());
        })
    );

    this.onTouchMove = new Rx.CompositeDisposable();
    this.onTouchMove.add(
      Rx.Observable
        .merge(
          this.touchStart.map(x => Object.assign(x, { type: "start" })),
          this.touchMove.map(x => Object.assign(x, { type: "move" })),
          this.touchEnd.map(x => Object.assign(x, { type: "end" }))
        )
        .groupBy(e => e.identifier)
        .map(group => {
          return group.pairwise().map(([e1, e2]) => {
            if (e1.type !== "end") {
              this.touches.push({
                id: group.key,
                type: "move",
                event: e2,
                delta: {
                  locationX: e2.locationX - e1.locationX,
                  locationY: e2.locationY - e1.locationY,
                  pageX: e2.pageX - e1.pageX,
                  pageY: e2.pageY - e1.pageY,
                  timestamp: e2.timestamp - e1.timestamp
                }
              });
            }
          });
        })
        .subscribe(group => {
          this.onTouchMove.add(group.subscribe());
        })
    );

    this.onTouchEnd = new Rx.CompositeDisposable();
    this.onTouchEnd.add(
      this.touchEnd
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "end", event: e });
          });
        })
        .subscribe(group => {
          this.onTouchEnd.add(group.subscribe());
        })
    );

    this.onTouchPress = new Rx.CompositeDisposable();
    this.onTouchPress.add(
      this.touchPress
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "press", event: e });
          });
        })
        .subscribe(group => {
          this.onTouchPress.add(group.subscribe());
        })
    );

    this.onLongTouch = new Rx.CompositeDisposable();
    this.onLongTouch.add(
      this.longTouch
        .groupBy(e => e.identifier)
        .map(group => {
          return group.map(e => {
            this.touches.push({ id: group.key, type: "long-press", event: e });
          });
        })
        .subscribe(group => {
          this.onLongTouch.add(group.subscribe());
        })
    );
  }

  componentDidMount() {
    this.start();
  }

  componentWillUnmount() {
    this.timer.stop();
    this.timer.unsubscribe(this.update);

    this.touchStart.dispose();
    this.touchMove.dispose();
    this.touchEnd.dispose();

    this.onTouchStart.dispose();
    this.onTouchMove.dispose();
    this.onTouchEnd.dispose();
    this.onTouchPress.dispose();
    this.onLongTouch.dispose();
  }

  start = () => {
    this.timer.start();
    this.events.push({ type: "started" });
  };

  stop = () => {
    this.timer.stop();
    this.events.push({ type: "stopped" });
  };

  update = currentTime => {
    let args = {
      touches: this.touches,
      screen: this.screen,
      events: this.events,
      time: {
        current: currentTime,
        previous: this.previousTime,
        delta: currentTime - (this.previousTime || currentTime),
        previousDelta: this.previousDelta
      }
    };

    let newState = this.props.systems.reduce(
      (state, sys) => sys(state, args),
      this.state
    );

    this.touches.length = 0;
    this.events.length = 0;
    this.previousTime = currentTime;
    this.previousDelta = args.time.delta;
    this.setState(newState);
  };

  publishEvent = e => {
    this.events.push(e);
  };

  onPublishTouchStart = e => {
    this.touchStart.onNext(e.nativeEvent);
  };

  onPublishTouchMove = e => {
    this.touchMove.onNext(e.nativeEvent);
  };

  onPublishTouchEnd = e => {
    this.touchEnd.onNext(e.nativeEvent);
  };

  onLayout = () => {
    this.screen = Dimensions.get("window");
    this.forceUpdate();
  };

  render() {
    return (
      <View style={[css.container, this.props.style]} onLayout={this.onLayout}>

        <View
          style={css.entityContainer}
          onTouchStart={this.onPublishTouchStart}
          onTouchMove={this.onPublishTouchMove}
          onTouchEnd={this.onPublishTouchEnd}
        >
          {Object.keys(this.state)
            .filter(key => this.state[key].renderable)
            .map(key => {
              let entity = this.state[key];
              if (typeof entity.renderable === "object")
                return <entity.renderable.type key={key} {...entity} />;
              else if (typeof entity.renderable === "function")
                return <entity.renderable key={key} {...entity} />;
            })}
        </View>

        <View
          pointerEvents={"box-none"}
          style={[
            css.childrenContainer,
            { width: this.screen.width, height: this.screen.height }
          ]}
        >
          {this.props.children}
        </View>

      </View>
    );
  }
}

ComponentEntitySystem.defaultProps = { systems: [], entities: {} };

const css = StyleSheet.create({
  container: {
    flex: 1
  },
  entityContainer: {
    flex: 1,
    //-- Looks like Android requires bg color here
    //-- to register touches. If we didn't worry about
    //-- 'children' (foreground) components capturing events,
    //-- this whole shenanigan could be avoided..
    backgroundColor: "transparent"
  },
  childrenContainer: {
    top: 0,
    left: 0,
    position: "absolute"
  }
});
<|endoftext|>