<commit_before>    angular.module('container', [])
    .controller('ContainerController', ['$scope', '$routeParams', '$location', 'Container', 'ContainerCommit', 'Image', 'Messages', 'ViewSpinner', '$timeout',
        function ($scope, $routeParams, $location, Container, ContainerCommit, Image, Messages, ViewSpinner, $timeout) {
            $scope.changes = [];
            $scope.editEnv = false;
            $scope.editPorts = false;
            $scope.editBinds = false;
            $scope.newCfg = {
                Env: [],
                Ports: {}
            };

            var update = function () {
                ViewSpinner.spin();
                Container.get({id: $routeParams.id}, function (d) {
                    $scope.container = d;
                    $scope.container.edit = false;
                    $scope.container.newContainerName = d.Name;

                    // fill up env
                    if (d.Config.Env) {
                        $scope.newCfg.Env = d.Config.Env.map(function (entry) {
                            return {name: entry.split('=')[0], value: entry.split('=')[1]};
                        });
                    }

                    // fill up ports
                    $scope.newCfg.Ports = {};
                    angular.forEach(d.Config.ExposedPorts, function(i, port) {
                        if (d.HostConfig.PortBindings && port in d.HostConfig.PortBindings) {
                            $scope.newCfg.Ports[port] = d.HostConfig.PortBindings[port];
                        }
                        else {
                            $scope.newCfg.Ports[port] = [];
                        }
                    });

                    // fill up bindings
                    $scope.newCfg.Binds = [];
                    var defaultBinds = {};
                    angular.forEach(d.Config.Volumes, function(value, vol) {
                        defaultBinds[vol] = { ContPath: vol, HostPath: '', ReadOnly: false, DefaultBind: true };
                    });
                    angular.forEach(d.HostConfig.Binds, function(binding, i) {
                        var mountpoint = binding.split(':')[0];
                        var vol = binding.split(':')[1] || '';
                        var ro = binding.split(':').length > 2 && binding.split(':')[2] === 'ro';
                        var defaultBind = false;
                        if (vol === '') {
                            vol = mountpoint;
                            mountpoint = '';
                        }

                        if (vol in defaultBinds) {
                            delete defaultBinds[vol];
                            defaultBind = true;
                        }
                        $scope.newCfg.Binds.push({ ContPath: vol, HostPath: mountpoint, ReadOnly: ro, DefaultBind: defaultBind });
                    });
                    angular.forEach(defaultBinds, function(bind) {
                        $scope.newCfg.Binds.push(bind);
                    });

                    ViewSpinner.stop();
                }, function (e) {
                    if (e.status === 404) {
                        $('.detail').hide();
                        Messages.error("Not found", "Container not found.");
                    } else {
                        Messages.error("Failure", e.data);
                    }
                    ViewSpinner.stop();
                });

            };

            $scope.start = function () {
                ViewSpinner.spin();
                Container.start({
                    id: $scope.container.Id,
                    HostConfig: $scope.container.HostConfig
                }, function (d) {
                    update();
                    Messages.send("Container started", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to start." + e.data);
                });
            };

            $scope.stop = function () {
                ViewSpinner.spin();
                Container.stop({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container stopped", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to stop." + e.data);
                });
            };

            $scope.kill = function () {
                ViewSpinner.spin();
                Container.kill({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container killed", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to die." + e.data);
                });
            };

            $scope.restartEnv = function () {
                var config = angular.copy($scope.container.Config);

                config.Env = $scope.newCfg.Env.map(function(entry) {
                    return entry.name+"="+entry.value;
                });

                var portBindings = angular.copy($scope.newCfg.Ports);
                angular.forEach(portBindings, function(item, key) {
                    if (item.length === 0) {
                        delete portBindings[key];
                    }
                });

                var binds = [];
                angular.forEach($scope.newCfg.Binds, function(b) {
                    if (b.ContPath !== '') {
                        var bindLine = '';
                        if (b.HostPath !== '') {
                            bindLine = b.HostPath + ':';
                        }
                        bindLine += b.ContPath;
                        if (b.ReadOnly) {
                            bindLine += ':ro';
                        }
                        if (b.HostPath !== '' || !b.DefaultBind) {
                            binds.push(bindLine);
                        }
                    }
                });

                ViewSpinner.spin();
                ContainerCommit.commit({id: $routeParams.id, tag: $scope.container.Config.Image, config: config }, function (d) {
                    if ('Id' in d) {
                        var imageId = d.Id;
                        Image.inspect({id: imageId}, function(imageData) {
                            // Append current host config to image with new port bindings
                            imageData.Config.HostConfig = angular.copy($scope.container.HostConfig);
                            imageData.Config.HostConfig.PortBindings = portBindings;
                            imageData.Config.HostConfig.Binds = binds;
                            if (imageData.Config.HostConfig.NetworkMode === 'host') {
                                imageData.Config.Hostname = '';
                            }

                            Container.create(imageData.Config, function(containerData) {
                                if (!('Id' in containerData)) {
                                    Messages.error("Failure", "Container failed to create.");
                                    return;
                                }
                                // Stop current if running
                                if ($scope.container.State.Running) {
                                    Container.stop({id: $routeParams.id}, function (d) {
                                        Messages.send("Container stopped", $routeParams.id);
                                        // start new
                                        Container.start({
                                            id: containerData.Id
                                        }, function (d) {
                                            $location.url('/containers/' + containerData.Id + '/');
                                            Messages.send("Container started", $routeParams.id);
                                        }, function (e) {
                                            update();
                                            Messages.error("Failure", "Container failed to start." + e.data);
                                        });
                                    }, function (e) {
                                        update();
                                        Messages.error("Failure", "Container failed to stop." + e.data);
                                    });
                                } else {
                                    // start new
                                    Container.start({
                                        id: containerData.Id
                                    }, function (d) {
                                        $location.url('/containers/'+containerData.Id+'/');
                                        Messages.send("Container started", $routeParams.id);
                                    }, function (e) {
                                        update();
                                        Messages.error("Failure", "Container failed to start." + e.data);
                                    });
                                }

                            }, function(e) {
                                update();
                                Messages.error("Failure", "Image failed to get." + e.data);
                            });
                        }, function (e) {
                            update();
                            Messages.error("Failure", "Image failed to get." + e.data);
                        });

                    } else {
                        update();
                        Messages.error("Failure", "Container commit failed.");
                    }

                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to commit." + e.data);
                });
            };

            $scope.commit = function () {
                ViewSpinner.spin();
                ContainerCommit.commit({id: $routeParams.id, repo: $scope.container.Config.Image}, function (d) {
                    update();
                    Messages.send("Container commited", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to commit." + e.data);
                });
            };
            $scope.pause = function () {
                ViewSpinner.spin();
                Container.pause({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container paused", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to pause." + e.data);
                });
            };

            $scope.unpause = function () {
                ViewSpinner.spin();
                Container.unpause({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container unpaused", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to unpause." + e.data);
                });
            };

            $scope.remove = function () {
                ViewSpinner.spin();
                Container.remove({id: $routeParams.id}, function (d) {
                    update();
                    $location.path('/containers');
                    Messages.send("Container removed", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to remove." + e.data);
                });
            };

            $scope.restart = function () {
                ViewSpinner.spin();
                Container.restart({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container restarted", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to restart." + e.data);
                });
            };

            $scope.hasContent = function (data) {
                return data !== null && data !== undefined;
            };

            $scope.getChanges = function () {
                ViewSpinner.spin();
                Container.changes({id: $routeParams.id}, function (d) {
                    $scope.changes = d;
                    ViewSpinner.stop();
                });
            };

            $scope.renameContainer = function () {
                // #FIXME fix me later to handle http status to show the correct error message
                Container.rename({id: $routeParams.id, 'name': $scope.container.newContainerName}, function (data) {
                    if (data.name) {
                        $scope.container.Name = data.name;
                        Messages.send("Container renamed", $routeParams.id);
                    } else {
                        $scope.container.newContainerName = $scope.container.Name;
                        Messages.error("Failure", "Container failed to rename.");
                    }
                });
                $scope.container.edit = false;
            };

            $scope.addEntry = function (array, entry) {
                array.push(entry);
            };
            $scope.rmEntry = function (array, entry) {
                var idx = array.indexOf(entry);
                array.splice(idx, 1);
            };

            $scope.toggleEdit = function() {
                $scope.edit = !$scope.edit;
            };

            update();
            $scope.getChanges();
        }]);

<commit_msg>Fix the ability to start a container from the container details (#245)<commit_after>    angular.module('container', [])
    .controller('ContainerController', ['$scope', '$routeParams', '$location', 'Container', 'ContainerCommit', 'Image', 'Messages', 'ViewSpinner', '$timeout',
        function ($scope, $routeParams, $location, Container, ContainerCommit, Image, Messages, ViewSpinner, $timeout) {
            $scope.changes = [];
            $scope.editEnv = false;
            $scope.editPorts = false;
            $scope.editBinds = false;
            $scope.newCfg = {
                Env: [],
                Ports: {}
            };

            var update = function () {
                ViewSpinner.spin();
                Container.get({id: $routeParams.id}, function (d) {
                    $scope.container = d;
                    $scope.container.edit = false;
                    $scope.container.newContainerName = d.Name;

                    // fill up env
                    if (d.Config.Env) {
                        $scope.newCfg.Env = d.Config.Env.map(function (entry) {
                            return {name: entry.split('=')[0], value: entry.split('=')[1]};
                        });
                    }

                    // fill up ports
                    $scope.newCfg.Ports = {};
                    angular.forEach(d.Config.ExposedPorts, function(i, port) {
                        if (d.HostConfig.PortBindings && port in d.HostConfig.PortBindings) {
                            $scope.newCfg.Ports[port] = d.HostConfig.PortBindings[port];
                        }
                        else {
                            $scope.newCfg.Ports[port] = [];
                        }
                    });

                    // fill up bindings
                    $scope.newCfg.Binds = [];
                    var defaultBinds = {};
                    angular.forEach(d.Config.Volumes, function(value, vol) {
                        defaultBinds[vol] = { ContPath: vol, HostPath: '', ReadOnly: false, DefaultBind: true };
                    });
                    angular.forEach(d.HostConfig.Binds, function(binding, i) {
                        var mountpoint = binding.split(':')[0];
                        var vol = binding.split(':')[1] || '';
                        var ro = binding.split(':').length > 2 && binding.split(':')[2] === 'ro';
                        var defaultBind = false;
                        if (vol === '') {
                            vol = mountpoint;
                            mountpoint = '';
                        }

                        if (vol in defaultBinds) {
                            delete defaultBinds[vol];
                            defaultBind = true;
                        }
                        $scope.newCfg.Binds.push({ ContPath: vol, HostPath: mountpoint, ReadOnly: ro, DefaultBind: defaultBind });
                    });
                    angular.forEach(defaultBinds, function(bind) {
                        $scope.newCfg.Binds.push(bind);
                    });

                    ViewSpinner.stop();
                }, function (e) {
                    if (e.status === 404) {
                        $('.detail').hide();
                        Messages.error("Not found", "Container not found.");
                    } else {
                        Messages.error("Failure", e.data);
                    }
                    ViewSpinner.stop();
                });

            };

            $scope.start = function () {
                ViewSpinner.spin();
                Container.start({
                    id: $scope.container.Id,
                }, {}, function (d) {
                    update();
                    Messages.send("Container started", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to start." + e.data);
                });
            };

            $scope.stop = function () {
                ViewSpinner.spin();
                Container.stop({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container stopped", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to stop." + e.data);
                });
            };

            $scope.kill = function () {
                ViewSpinner.spin();
                Container.kill({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container killed", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to die." + e.data);
                });
            };

            $scope.restartEnv = function () {
                var config = angular.copy($scope.container.Config);

                config.Env = $scope.newCfg.Env.map(function(entry) {
                    return entry.name+"="+entry.value;
                });

                var portBindings = angular.copy($scope.newCfg.Ports);
                angular.forEach(portBindings, function(item, key) {
                    if (item.length === 0) {
                        delete portBindings[key];
                    }
                });

                var binds = [];
                angular.forEach($scope.newCfg.Binds, function(b) {
                    if (b.ContPath !== '') {
                        var bindLine = '';
                        if (b.HostPath !== '') {
                            bindLine = b.HostPath + ':';
                        }
                        bindLine += b.ContPath;
                        if (b.ReadOnly) {
                            bindLine += ':ro';
                        }
                        if (b.HostPath !== '' || !b.DefaultBind) {
                            binds.push(bindLine);
                        }
                    }
                });

                ViewSpinner.spin();
                ContainerCommit.commit({id: $routeParams.id, tag: $scope.container.Config.Image, config: config }, function (d) {
                    if ('Id' in d) {
                        var imageId = d.Id;
                        Image.inspect({id: imageId}, function(imageData) {
                            // Append current host config to image with new port bindings
                            imageData.Config.HostConfig = angular.copy($scope.container.HostConfig);
                            imageData.Config.HostConfig.PortBindings = portBindings;
                            imageData.Config.HostConfig.Binds = binds;
                            if (imageData.Config.HostConfig.NetworkMode === 'host') {
                                imageData.Config.Hostname = '';
                            }

                            Container.create(imageData.Config, function(containerData) {
                                if (!('Id' in containerData)) {
                                    Messages.error("Failure", "Container failed to create.");
                                    return;
                                }
                                // Stop current if running
                                if ($scope.container.State.Running) {
                                    Container.stop({id: $routeParams.id}, function (d) {
                                        Messages.send("Container stopped", $routeParams.id);
                                        // start new
                                        Container.start({
                                            id: containerData.Id
                                        }, function (d) {
                                            $location.url('/containers/' + containerData.Id + '/');
                                            Messages.send("Container started", $routeParams.id);
                                        }, function (e) {
                                            update();
                                            Messages.error("Failure", "Container failed to start." + e.data);
                                        });
                                    }, function (e) {
                                        update();
                                        Messages.error("Failure", "Container failed to stop." + e.data);
                                    });
                                } else {
                                    // start new
                                    Container.start({
                                        id: containerData.Id
                                    }, function (d) {
                                        $location.url('/containers/'+containerData.Id+'/');
                                        Messages.send("Container started", $routeParams.id);
                                    }, function (e) {
                                        update();
                                        Messages.error("Failure", "Container failed to start." + e.data);
                                    });
                                }

                            }, function(e) {
                                update();
                                Messages.error("Failure", "Image failed to get." + e.data);
                            });
                        }, function (e) {
                            update();
                            Messages.error("Failure", "Image failed to get." + e.data);
                        });

                    } else {
                        update();
                        Messages.error("Failure", "Container commit failed.");
                    }

                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to commit." + e.data);
                });
            };

            $scope.commit = function () {
                ViewSpinner.spin();
                ContainerCommit.commit({id: $routeParams.id, repo: $scope.container.Config.Image}, function (d) {
                    update();
                    Messages.send("Container commited", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to commit." + e.data);
                });
            };
            $scope.pause = function () {
                ViewSpinner.spin();
                Container.pause({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container paused", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to pause." + e.data);
                });
            };

            $scope.unpause = function () {
                ViewSpinner.spin();
                Container.unpause({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container unpaused", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to unpause." + e.data);
                });
            };

            $scope.remove = function () {
                ViewSpinner.spin();
                Container.remove({id: $routeParams.id}, function (d) {
                    update();
                    $location.path('/containers');
                    Messages.send("Container removed", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to remove." + e.data);
                });
            };

            $scope.restart = function () {
                ViewSpinner.spin();
                Container.restart({id: $routeParams.id}, function (d) {
                    update();
                    Messages.send("Container restarted", $routeParams.id);
                }, function (e) {
                    update();
                    Messages.error("Failure", "Container failed to restart." + e.data);
                });
            };

            $scope.hasContent = function (data) {
                return data !== null && data !== undefined;
            };

            $scope.getChanges = function () {
                ViewSpinner.spin();
                Container.changes({id: $routeParams.id}, function (d) {
                    $scope.changes = d;
                    ViewSpinner.stop();
                });
            };

            $scope.renameContainer = function () {
                // #FIXME fix me later to handle http status to show the correct error message
                Container.rename({id: $routeParams.id, 'name': $scope.container.newContainerName}, function (data) {
                    if (data.name) {
                        $scope.container.Name = data.name;
                        Messages.send("Container renamed", $routeParams.id);
                    } else {
                        $scope.container.newContainerName = $scope.container.Name;
                        Messages.error("Failure", "Container failed to rename.");
                    }
                });
                $scope.container.edit = false;
            };

            $scope.addEntry = function (array, entry) {
                array.push(entry);
            };
            $scope.rmEntry = function (array, entry) {
                var idx = array.indexOf(entry);
                array.splice(idx, 1);
            };

            $scope.toggleEdit = function() {
                $scope.edit = !$scope.edit;
            };

            update();
            $scope.getChanges();
        }]);
<|endoftext|>


<commit_before>module.exports = {

    mixins: [
        require('../lib/package')
    ],

    data: function () {
        return _.extend({
            package: {},
            view: false,
            updates: null,
            search: '',
            status: ''
        }, window.$data);
    },

    ready: function () {
        this.load();
    },

    methods: {

        load: function () {
            this.$set('status', 'loading');

            this.queryUpdates(this.packages, function (res) {
                var data = res.data;
                this.$set('updates', data.packages.length ? _.indexBy(data.packages, 'name') : null);
                this.$set('status', '');
            }).error(function () {
                this.$set('status', 'error');
            });
        },

        icon: function (pkg) {

            if (pkg.extra && pkg.extra.icon) {
                return pkg.url + '/' + pkg.extra.icon;
            } else {
                return this.$url('app/system/assets/images/placeholder-icon.svg');
            }

        },

        image: function (pkg) {

            if (pkg.extra && pkg.extra.image) {
                return pkg.url + '/' + pkg.extra.image;
            } else {
                return this.$url('app/system/assets/images/placeholder-800x600.svg');
            }

        },

        details: function (pkg) {
            this.$set('package', pkg);
            this.$refs.details.open();
        },

        settings: function (pkg) {

            if (!pkg.settings) {
                return;
            }

            var view, options;

            _.forIn(this.$options.components, function (component, name) {

                options = component.options || {};

                if (options.settings && pkg.settings === name) {
                    view = name;
                }

            });

            if (view) {

                this.$set('package', pkg);
                this.$set('view', view);
                this.$refs.settings.open();

            } else {
                window.location = pkg.settings;
            }

        },

        update: function (pkg) {
            var vm = this;

            this.install(pkg, this.packages, function (output) {
                if (output.status === 'success') {
                    vm.updates.$delete(pkg.name);
                }

                setTimeout(function () {
                    location.reload();
                }, 300);
            });
        }

    },

    filters: {

        empty: function (packages) {
            return Vue.filter('filterBy')(packages, this.search, 'title').length === 0;
        }

    },

    components: {

        'package-upload': require('./package-upload.vue')

    }

};
<commit_msg>remove deprecated Vue resource method<commit_after>module.exports = {

    mixins: [
        require('../lib/package')
    ],

    data: function () {
        return _.extend({
            package: {},
            view: false,
            updates: null,
            search: '',
            status: ''
        }, window.$data);
    },

    ready: function () {
        this.load();
    },

    methods: {

        load: function () {
            this.$set('status', 'loading');

            this.queryUpdates(this.packages).then(function (res) {
                var data = res.data;
                this.$set('updates', data.packages.length ? _.indexBy(data.packages, 'name') : null);
                this.$set('status', '');
            }, function () {
                this.$set('status', 'error');
            });
        },

        icon: function (pkg) {

            if (pkg.extra && pkg.extra.icon) {
                return pkg.url + '/' + pkg.extra.icon;
            } else {
                return this.$url('app/system/assets/images/placeholder-icon.svg');
            }

        },

        image: function (pkg) {

            if (pkg.extra && pkg.extra.image) {
                return pkg.url + '/' + pkg.extra.image;
            } else {
                return this.$url('app/system/assets/images/placeholder-800x600.svg');
            }

        },

        details: function (pkg) {
            this.$set('package', pkg);
            this.$refs.details.open();
        },

        settings: function (pkg) {

            if (!pkg.settings) {
                return;
            }

            var view, options;

            _.forIn(this.$options.components, function (component, name) {

                options = component.options || {};

                if (options.settings && pkg.settings === name) {
                    view = name;
                }

            });

            if (view) {

                this.$set('package', pkg);
                this.$set('view', view);
                this.$refs.settings.open();

            } else {
                window.location = pkg.settings;
            }

        },

        update: function (pkg) {
            var vm = this;

            this.install(pkg, this.packages, function (output) {
                if (output.status === 'success') {
                    vm.updates.$delete(pkg.name);
                }

                setTimeout(function () {
                    location.reload();
                }, 300);
            });
        }

    },

    filters: {

        empty: function (packages) {
            return Vue.filter('filterBy')(packages, this.search, 'title').length === 0;
        }

    },

    components: {

        'package-upload': require('./package-upload.vue')

    }

};
<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
var SearchResults = require('./SearchResults');
var AddOpenMicForm = require('./AddOpenMicForm');
var {
    StyleSheet,
    Text,
    TextInput,
    View,
    ScrollView,
    TouchableHighlight,
    ActivityIndicatorIOS,
    Image,
    Component
} = React;

function urlForQueryAndPage(key, value) {
    var data = {
        city: value
    };

    var querystring = Object.keys(data)
        .map(key => key + '=' + encodeURIComponent(data[key]))
        .join('&');

    return 'http://localhost:3000/api/openmic/listForCity?' + querystring;
};

class SearchPage extends Component {

    constructor(props) {
        super(props);
        this.state = {
            searchString: 'New York',
            isLoading: false,
            message: ''
        };
    }

    _handleResponse(openmics) {
        this.setState({isLoading: false});
        if (openmics.length) {
            this.props.navigator.push({
                title:  ' Open Mics in ' + this.capitalize(this.state.searchString),
                component: SearchResults,
                passProps: {openmics: openmics}
            });
        } else {
            this.setState({message: 'Location not recognized or does not have any open mics. Please try again.'});
        }
    }

    _executeQuery(query) {
        this.setState({isLoading: true, message: ''});
        fetch(query)
            .then(response => response.json())
            .then(data => this._handleResponse(data))
            .catch(error => {
                this.setState({
                    isLoading: false,
                    message: 'Something bad happened ' + error
                });
            });
    }

    onSearchPressed() {
        var query = urlForQueryAndPage('place_name', this.state.searchString);
        this._executeQuery(query);
    }

    onAddOpenMicButtonPressed() {
        this.props.navigator.push({
            title: 'Add an Open Mic',
            component: AddOpenMicForm,
            passProps: {}
        });
    }

    onSearchTextChanged(event) {
        this.setState({searchString: event.nativeEvent.text});
    }

    render() {
        var spinner = this.state.isLoading ?
            ( <ActivityIndicatorIOS
                hidden='true'
                size='large'/> ) :
            ( <View/>);

        return (
            <ScrollView>
                <View style={styles.container}>
                <Text style={styles.description}>
                    Find Open Mics in your area!
                </Text>

                <Image source={require('./img/microphone.png')} style={styles.image}/>

                <Text style={styles.description}>
                    Search by city name.
                </Text>
                <View style={styles.flowRight}>
                    <TextInput
                        style={styles.searchInput}
                        placeholder='Search via city name'
                        value={this.state.searchString}
                        onChange={this.onSearchTextChanged.bind(this)}/>
                    <TouchableHighlight style={styles.button}
                                        underlayColor='#99d9f4'
                                        onPress={this.onSearchPressed.bind(this)}>
                        <Text style={styles.buttonText}>Go</Text>
                    </TouchableHighlight>
                </View>
                <TouchableHighlight style={styles.button}
                                    onPress={this.onAddOpenMicButtonPressed.bind(this)}
                                    underlayColor='#99d9f4'>
                    <Text style={styles.buttonText}>Add an Open Mic</Text>
                </TouchableHighlight>
                {spinner}
                <Text style={styles.description}>{this.state.message}</Text>
                </View>
            </ScrollView>
        );
    }

    capitalize(string)
    {
        return string[0].toUpperCase() + string.slice(1);
    }
}

var styles = StyleSheet.create({
    description: {
        marginBottom: 20,
        fontSize: 18,
        textAlign: 'center',
        color: '#656565'
    },
    container: {
        padding: 30,
        //marginTop: 65,
        alignItems: 'center'
    },
    flowRight: {
        flexDirection: 'row',
        alignItems: 'center',
        alignSelf: 'stretch'
    },
    buttonText: {
        fontSize: 18,
        color: 'white',
        alignSelf: 'center'
    },
    button: {
        height: 36,
        flex: 1,
        flexDirection: 'row',
        backgroundColor: '#2196f3',
        borderColor: '#2196f3',
        borderWidth: 1,
        borderRadius: 8,
        marginBottom: 10,
        alignSelf: 'stretch',
        justifyContent: 'center'
    },
    searchInput: {
        height: 36,
        padding: 4,
        marginRight: 5,
        flex: 4,
        fontSize: 18,
        borderWidth: 1,
        borderColor: '#2196f3',
        borderRadius: 8,
        color: '#2196f3'
    },
    image: {
        width: 100,
        height: 200
    }
});

module.exports = SearchPage;<commit_msg>Changine default city for ease of testing<commit_after>'use strict';

var React = require('react-native');
var SearchResults = require('./SearchResults');
var AddOpenMicForm = require('./AddOpenMicForm');
var {
    StyleSheet,
    Text,
    TextInput,
    View,
    ScrollView,
    TouchableHighlight,
    ActivityIndicatorIOS,
    Image,
    Component
} = React;

function urlForQueryAndPage(key, value) {
    var data = {
        city: value
    };

    var querystring = Object.keys(data)
        .map(key => key + '=' + encodeURIComponent(data[key]))
        .join('&');

    return 'http://localhost:3000/api/openmic/listForCity?' + querystring;
};

class SearchPage extends Component {

    constructor(props) {
        super(props);
        this.state = {
            searchString: 'Denver',
            isLoading: false,
            message: ''
        };
    }

    _handleResponse(openmics) {
        this.setState({isLoading: false});
        if (openmics.length) {
            this.props.navigator.push({
                title: this.capitalize(this.state.searchString),
                component: SearchResults,
                passProps: {openmics: openmics}
            });
        } else {
            this.setState({message: 'Location not recognized or does not have any open mics. Please try again.'});
        }
    }

    _executeQuery(query) {
        this.setState({isLoading: true, message: ''});
        fetch(query)
            .then(response => response.json())
            .then(data => this._handleResponse(data))
            .catch(error => {
                this.setState({
                    isLoading: false,
                    message: 'Something bad happened ' + error
                });
            });
    }

    onSearchPressed() {
        var query = urlForQueryAndPage('place_name', this.state.searchString);
        this._executeQuery(query);
    }

    onAddOpenMicButtonPressed() {
        this.props.navigator.push({
            title: 'Add an Open Mic',
            component: AddOpenMicForm,
            passProps: {}
        });
    }

    onSearchTextChanged(event) {
        this.setState({searchString: event.nativeEvent.text});
    }

    render() {
        var spinner = this.state.isLoading ?
            ( <ActivityIndicatorIOS
                hidden='true'
                size='large'/> ) :
            ( <View/>);

        return (
            <ScrollView>
                <View style={styles.container}>
                <Text style={styles.description}>
                    Find Open Mics in your area!
                </Text>

                <Image source={require('./img/microphone.png')} style={styles.image}/>

                <Text style={styles.description}>
                    Search by city name.
                </Text>
                <View style={styles.flowRight}>
                    <TextInput
                        style={styles.searchInput}
                        placeholder='Search via city name'
                        value={this.state.searchString}
                        onChange={this.onSearchTextChanged.bind(this)}/>
                    <TouchableHighlight style={styles.button}
                                        underlayColor='#99d9f4'
                                        onPress={this.onSearchPressed.bind(this)}>
                        <Text style={styles.buttonText}>Go</Text>
                    </TouchableHighlight>
                </View>
                <TouchableHighlight style={styles.button}
                                    onPress={this.onAddOpenMicButtonPressed.bind(this)}
                                    underlayColor='#99d9f4'>
                    <Text style={styles.buttonText}>Add an Open Mic</Text>
                </TouchableHighlight>
                {spinner}
                <Text style={styles.description}>{this.state.message}</Text>
                </View>
            </ScrollView>
        );
    }

    capitalize(string)
    {
        return string[0].toUpperCase() + string.slice(1);
    }
}

var styles = StyleSheet.create({
    description: {
        marginBottom: 20,
        fontSize: 18,
        textAlign: 'center',
        color: '#656565'
    },
    container: {
        padding: 30,
        //marginTop: 65,
        alignItems: 'center'
    },
    flowRight: {
        flexDirection: 'row',
        alignItems: 'center',
        alignSelf: 'stretch'
    },
    buttonText: {
        fontSize: 18,
        color: 'white',
        alignSelf: 'center'
    },
    button: {
        height: 36,
        flex: 1,
        flexDirection: 'row',
        backgroundColor: '#2196f3',
        borderColor: '#2196f3',
        borderWidth: 1,
        borderRadius: 8,
        marginBottom: 10,
        alignSelf: 'stretch',
        justifyContent: 'center'
    },
    searchInput: {
        height: 36,
        padding: 4,
        marginRight: 5,
        flex: 4,
        fontSize: 18,
        borderWidth: 1,
        borderColor: '#2196f3',
        borderRadius: 8,
        color: '#2196f3'
    },
    image: {
        width: 100,
        height: 200
    }
});

module.exports = SearchPage;<|endoftext|>


<commit_before>import Ember from 'ember';
import ENV from 'aeonvera/config/environment';

export default Ember.Controller.extend({
  columns: [
    { property: 'userName', title: 'Name' },
    { property: 'total', title: 'Total' },
    { property: 'paid', title: 'Paid' },
    { property: 'createdAt', title: 'Created At' },
    { property: '', title: 'Registration', sort: false }
  ],

  eventId: Ember.computed.alias('model.eventId'),
  orders: Ember.computed.alias('model.orders'),
  paramsForDownload: Ember.computed('model.eventId', {
    get(key) {
      return {
        event_id: this.get('model.eventId')
      };
    }
  }),

  path: Ember.computed('model.eventId', {
    get(key) {
      return `${ENV.host}/api/orders.csv?`;
    }
  })
});
<commit_msg>change orders screen to have currentPaidAmount<commit_after>import Ember from 'ember';
import ENV from 'aeonvera/config/environment';

export default Ember.Controller.extend({
  columns: [
    { property: 'userName', title: 'Name' },
    { property: 'currentPaidAmount', title: 'Paid Amount' },
    { property: 'paid', title: 'Paid' },
    { property: 'createdAt', title: 'Created At' },
    { property: '', title: 'Registration', sort: false }
  ],

  eventId: Ember.computed.alias('model.eventId'),
  orders: Ember.computed.alias('model.orders'),
  paramsForDownload: Ember.computed('model.eventId', {
    get(key) {
      return {
        event_id: this.get('model.eventId')
      };
    }
  }),

  path: Ember.computed('model.eventId', {
    get(key) {
      return `${ENV.host}/api/orders.csv?`;
    }
  })
});
<|endoftext|>


<commit_before>module.exports = ServerNode;

/////////// Load dependencies ///////////

var util = require('util'),
    fs = require('fs'),
    path = require('path'),
    express = require('express'),
    socket_io = require('socket.io');

var EventEmitter = require('events').EventEmitter;
var nodemailer = require('nodemailer');

var ServerChannel = require('./ServerChannel');

var JSUS = require('nodegame-client').JSUS;

////////// Configure Application ///////////

var app = express.createServer();

app.configure(function(){
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

function ServerNode (options) {

    if (!options) {
        throw new Error('No configuration found to create a server. Aborting');
    }
    this.options = options;
    this.options.mail = ('undefined' !== typeof options.mail) ? options.mail : false;
    this.options.dumpmsg = ('undefined' !== typeof options.dumpmsg) ? options.dumpmsg : false;
    this.options.dumpsys = ('undefined' !== typeof options.dumpsys) ? options.dumpsys : true;
    this.options.verbosity = ('undefined' !== typeof options.verbosity) ? options.verbosity : 1;

    if(process.env.PORT){
        this.port = process.env.PORT; // if app is running on heroku then the assigned port has to be used.
    } else {
        this.port = options.port || '80'; // port of the express server and sio
    }

    this.maxChannels = options.maxChannels;
    this.channels = [];

    this.listen();
}

ServerNode.prototype.createHTTPServer = function (options) {

    return app.listen(options.port);

};

ServerNode.prototype.listen = function (http, io) {

    // this.io = io || require('socket.io');
    app.listen(this.port);

    // this.server = this.io.listen(this.http);
    this.server = socket_io.listen(app);

    this.configureHTTP(this.options.http);
    this.configureIO(this.options.io);
};

ServerNode.prototype._configure = function (obj, options) {
    if (!options) return;
    //var keywords = ['set', 'enable', 'disable'];
    for (var i in options) {
        if (options.hasOwnProperty(i)) {
            if (i === 'set') {
                for (var j in options[i]) {
                    if (options[i].hasOwnProperty(j)) {
                        obj.set(j, options[i][j]);
                    }
                }
            }
            else if (i === 'enable') {
                obj.enable(options[i]);
            }
            else if (i === 'disable') {
                obj.disable(options[i]);
            }
        }
    }
};

ServerNode.prototype.configureIO = function (options) {
    this.server.enable('browser client etag');
    this.server.set('log level', -1);
    this._configure(this.server, options);
};

// Define Routes

ServerNode.prototype.configureHTTP = function (options) {

    var that = this;

    app.get('/', function(req, res){
        res.render('index', {
            title: 'Yay! Your nodeGame server is running.'
        });
    });

    app.get('/:game/:file', function(req, res){

        // check if file exists the folder the scientist has created. EXTERNAL
        // check if file exists in the nodegame-server folder. INTERNAL

        // fetchFile(req.params.game + '/' + req.params.file, function(file_contents){

        // });

        var externalFilePath = __dirname.replace(/node\_modules/i, '') + '/games/' + req.params.game + '/' + req.params.file;

        console.log(externalFilePath);

        // doesFileExists()

        // check if external file exists

        // for games included in nodegame-server
        var includedFilePath = __dirname + '/games/' + req.params.game + '/' + req.params.file;
        res.sendfile(includedFilePath);

    });

};

ServerNode.prototype.addChannel = function (options) {

    if (!options) {
        console.log('Options are not correctly defined for the channel. Aborting');
        return;
    }

    var cname = options.name;
    // Some options must not be overwritten
    var options = JSUS.extend(this.options, options);
    if (cname){
        options.name = cname;
    }

    // TODO merge global options with local options
    var channel = new ServerChannel(options, this.server, this.io);
    // TODO return false in case of error in creating the channel
    var ok = channel.listen();

    if (ok) {
        this.channels.push(channel);
        console.log('Channel added correctly: ' + options.name);
    }
    else {
        console.log('Channel could not be added: ' + options.name);
    }

    return channel;
};

////////// Helpers ///////////

var fetchFile = function(path_and_file, callback){
    fetchExternalFile(path_and_file, function(result){
        if(result !== null){
            callback(result);
        } else {
            fetchIncludedFile(path_and_file, function(result){
                if(result !== null){
                    callback(result);
                } else {
                    callback(null);
                }
            });
        }
    });
};

var fetchExternalFile = function(path_and_file, callback){
    // checks if file exists, reads it and returns the content as a string
    // if file doensn't exist -> return null

    callback(null);
};

var fetchIncludedFile = function(path_and_file, callback){

    var fullPath = __dirname + '/games/' + path_and_file;
    doesFileExists(fullPath, function(exists){
        if(exists){
            fs.readFile(fullPath, 'UTF-8', function(err, result){
                if(err){
                    throw err;
                } else {
                    callback(result);
                }
            });
        } else {
            callback(null);
        }
    });
};

var doesFileExists = function(path, callback){
    fs.stat(path, function(err, stats){
        console.log(err);
        console.log(stats);

        if(err){
            callback(false);
        } else {
            callback(true);
        }

    });
};
<commit_msg>fixed implementation of serving external and internal files<commit_after>module.exports = ServerNode;

/////////// Load dependencies ///////////

var util = require('util'),
    fs = require('fs'),
    path = require('path'),
    express = require('express'),
    socket_io = require('socket.io');

var EventEmitter = require('events').EventEmitter;
var nodemailer = require('nodemailer');

var ServerChannel = require('./ServerChannel');

var JSUS = require('nodegame-client').JSUS;

////////// Configure Application ///////////

var app = express.createServer();

app.configure(function(){
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade');
    app.use(express.static(__dirname + '/public'));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

function ServerNode (options) {

    if (!options) {
        throw new Error('No configuration found to create a server. Aborting');
    }
    this.options = options;
    this.options.mail = ('undefined' !== typeof options.mail) ? options.mail : false;
    this.options.dumpmsg = ('undefined' !== typeof options.dumpmsg) ? options.dumpmsg : false;
    this.options.dumpsys = ('undefined' !== typeof options.dumpsys) ? options.dumpsys : true;
    this.options.verbosity = ('undefined' !== typeof options.verbosity) ? options.verbosity : 1;

    if(process.env.PORT){
        this.port = process.env.PORT; // if app is running on heroku then the assigned port has to be used.
    } else {
        this.port = options.port || '80'; // port of the express server and sio
    }

    this.maxChannels = options.maxChannels;
    this.channels = [];

    this.listen();
}

ServerNode.prototype.createHTTPServer = function (options) {

    return app.listen(options.port);

};

ServerNode.prototype.listen = function (http, io) {

    // this.io = io || require('socket.io');
    app.listen(this.port);

    // this.server = this.io.listen(this.http);
    this.server = socket_io.listen(app);

    this.configureHTTP(this.options.http);
    this.configureIO(this.options.io);
};

ServerNode.prototype._configure = function (obj, options) {
    if (!options) return;
    //var keywords = ['set', 'enable', 'disable'];
    for (var i in options) {
        if (options.hasOwnProperty(i)) {
            if (i === 'set') {
                for (var j in options[i]) {
                    if (options[i].hasOwnProperty(j)) {
                        obj.set(j, options[i][j]);
                    }
                }
            }
            else if (i === 'enable') {
                obj.enable(options[i]);
            }
            else if (i === 'disable') {
                obj.disable(options[i]);
            }
        }
    }
};

ServerNode.prototype.configureIO = function (options) {
    this.server.enable('browser client etag');
    this.server.set('log level', -1);
    this._configure(this.server, options);
};

// Define Routes

ServerNode.prototype.configureHTTP = function (options) {

    var that = this;

    app.get('/', function(req, res){
        res.render('index', {
            title: 'Yay! Your nodeGame server is running.'
        });
    });

    app.get('/:game/:file', function(req, res){

        // check if file exists the folder the scientist has created. EXTERNAL
        // check if file exists in the nodegame-server folder. INTERNAL

        var externalFilePath = __dirname.replace(/node\_modules.+/i, '') + 'games/' + req.params.game + '/' + req.params.file;

        doesFileExists(externalFilePath, function(exists){
            if(exists){
                res.sendfile(externalFilePath);
            } else {
                var includedFilePath = __dirname + '/games/' + req.params.game + '/' + req.params.file;
                res.sendfile(includedFilePath);
            }
        });
    });

};

ServerNode.prototype.addChannel = function (options) {

    if (!options) {
        console.log('Options are not correctly defined for the channel. Aborting');
        return;
    }

    var cname = options.name;
    // Some options must not be overwritten
    var options = JSUS.extend(this.options, options);
    if (cname){
        options.name = cname;
    }

    // TODO merge global options with local options
    var channel = new ServerChannel(options, this.server, this.io);
    // TODO return false in case of error in creating the channel
    var ok = channel.listen();

    if (ok) {
        this.channels.push(channel);
        console.log('Channel added correctly: ' + options.name);
    }
    else {
        console.log('Channel could not be added: ' + options.name);
    }

    return channel;
};

////////// Helpers ///////////

var doesFileExists = function(path, callback){
    fs.stat(path, function(err, stats){

        if(err){
            callback(false);
        } else {
            callback(true);
        }

    });
};
<|endoftext|>


<commit_before>var clubhouseManagement = function()
{
	// load data locally for edit window
	var clubhousesInfo = [];
	var allClubhousesObjects;
	const ADDPAGE = 1;
	const EDITPAGE = 2;
	const FAIL = -1;
	var page;

	// edit page vars
	var clubToEdit;
	var edit_clubname;
	var edit_clubIndex;

	///////////////////////////////////////

     //-------------------------------------------------------------------------------------------------
     // INJECTION FOR ADDING NEW CLUBHOUSE PAGE
	var addClubhousePage={
        inputSection:
		'
'+
			'
'+
						'
'+
							'
'+
								'
הוספת מועדונית
'+
								'
'+
							'
'+
						'
 '+

						'
'+
							'<form class="form-horizontal" method="post" action="#">'+

								'
'+
									':שם מועדונית'+
									'
'+
										'
'+
											''+
											'<input type="text" class="form-control" name="clubhouseName" id="clubhouseNameID"  placeholder="הכנס שם מועדונית"/>'+
										'
'+
									'
'+
								'
'+

								'
'+
									':כתובת המועדונית'+
									'
'+
										'
'+
											''+
											'<input type="text" class="form-control" name="clubhouseAddress" id="clubhouseAddrID"  placeholder="הכנס כתובת מועדונית"/>'+
										'
'+
									'
'+
								'
'+

								'
'+

								'
'+
							'</form>'+
						'
'+

				'
'
			}

			var addClubhouseBtn={
       		 inputSection:'<button type="button" id="addClubhouseBtn" class="btn btn-primary btn-lg btn-block register-button" data-toggle="modal" data-target="#myModal" >הוספה</button>'+
									'
'
			}

			var editClubhouseBtn={
       		 inputSection:'<button type="button" id="editClubhouseBtn" class="btn btn-primary btn-lg btn-block register-button" data-toggle="modal" data-target="#myModal" >עריכה</button>'+
									'
'
			}
       //-------------------------------------------------------------------------------------------------
       //       INJECTION FOR EDIT OPTION - clubhouse and user choosing
        var EditClubhousePage={
        inputSection:
                '
'+
					'
'+
						'בחר מועדונית'+
					'
'+
					'
'+
						'
'+

						'
'+
					'
'+
					'
'+
						'<button id ="editCHbtn" type="button" class="btn btn-primary btn-block btn-lg edit-button"  >ערוך פרטי מועדונית</button>'+
						'<button id ="deleteCHbtn" type="button" class="btn-danger btn-danger btn-block btn-lg  delete-button"  >הסר מועדונית</button>'+
					'
'+
				'
'
        }

    //-------------------------------------------------------------------------------------------------
    // Initial page for add clubHouse
	 var addClubhouse = function ()
	 {
		page = ADDPAGE;
		$('.Nav').collapse('hide');
		$("#body").html(addClubhousePage.inputSection); // opens page
		$('#buttonSection').html(addClubhouseBtn.inputSection);
		$("#addClubhouseBtn").click(addClubhouseListener);
	 }
	 //-------------------------------------------------------------------------------------------------
    // Initial page for edit clubHouse
	 var editClubhouse = function()
	 {
		page = EDITPAGE;
		loadClubhousesData();
		$('.Nav').collapse('hide');
		$("#body").html(EditClubhousePage.inputSection);
        $("#editCHbtn").click(EditCluhouseListener);
		$('#deleteCHbtn').click(removeCHlistener);
	 }

	//////////////////////////////////////////////////////////////////////////
	// 					ADD CLUBHOUSE										//
	//					-------------										//
	// check if club is exist, if not - create and push to DB new clubhouse.//
	/////////////////////////////////////////////////////////////////////////
	var validateAndPush = function(nameArg,addressAarg)
	{
		var ref = firebase.database().ref("clubhouse");
		ref.once("value")
		.then(function(data)		// 		when value recieved
		{
			// in case the root is empty  ->  name is not exist
			if (data.val() == null)
				return false;

			var allClubhouses = data.val();   // get the whole tree of clubhouses
			var keys = Object.keys(allClubhouses);	// get all keys

			// loop on the answere array to find clubhouse name.
			for(var i =0; i<keys.length;i++)
			{
				var k = keys[i];
				var tempName = allClubhouses[k].name;

				if( tempName == nameArg )
					return true;
			}
			return false;

		}).then(function(res)
		{
			if(res)		// name is already exist in DB
			{
				alert("המועדונית שהוזנה כבר קיימת במערכת");
				return false;
			}
			// else - push clubhouse to DB
			var newclubhouse = clubHouse.create(nameArg,addressAarg);
			var key = firebase.database().ref('clubhouse').push(newclubhouse);
			firebase.database().ref('clubhouse/'+key.key+'/ClubhouseDBkey').set(key.key); // set key property
			return true;
		}).then(function(result){
			if(result)
				alert("מועדונית התווספה בהצלחה");
			addClubhouse();
		});
	}

	//---------------------------------------------------------------------

	var addClubhouseListener = function()
	{
		var name = 	document.getElementById("clubhouseNameID").value;
		var address = document.getElementById("clubhouseAddrID").value;
		if (name == "" || address == "" )
		{
			alert("אנא הכנס שם מועדונית וכתובת");
			return;
		}
		// check if clubhouse already exists on DB and push if not.
		validateAndPush(name,address);
	}

	//////////////////////////////////////////////////////////////
	// 		EDIT CLUBHOUSE										//
	//		-------------										//
	//////////////////////////////////////////////////////////////
	// edit button from clubhosue edit menu
	var EditCluhouseListener = function(e)
	{
		var clubRef = firebase.database().ref('clubhouse/'+clubhousesInfo[edit_clubIndex].key);
		clubRef.once("value").then(function(data)
		{
			clubToEdit = data.val();	// keep ch info
			// inject html and set listener for edit page
			$('.Nav').collapse('hide');
			$("#body").html(addClubhousePage.inputSection);
			document.getElementById('titleCH').innerHTML ="עריכת מועדונית"; // change top title
			// set inputs
			$('#clubhouseAddrID').val(data.val().address);
			$('#clubhouseNameID').val(data.val().name);
			$('#buttonSection').html(editClubhouseBtn.inputSection);
			$('#editClubhouseBtn').click(changeCHListener);
		});
	}

	var changeCHListener = function()
	{
		var obj={};
		var name = $('#clubhouseNameID').val();  //current value
		var address = $('#clubhouseAddrID').val();

		if(clubToEdit.name != name)
			obj.name = name;

		if(clubToEdit.address != address)
			obj.address = address;

		var cref = firebase.database().ref('clubhouse/');
		cref.child(clubhousesInfo[edit_clubIndex].key).update(obj);
	}

	var CHsellection = function(e)
	{
		edit_clubname = e.target.innerText;
		edit_clubIndex = getClubKeyIndex(e.target.innerText.trim());
	}

	var removeCHlistener = function()
	{
		if(!edit_clubname)
			alert('לא נבחרה מועדונית');
		else
			alert('האם אתה בטוח ? פעולה זו תמחק את כל המשתמשים המשויכים למועדונית זו');
		removeAllUsersFromCh(clubhousesInfo[edit_clubIndex].key);

		// var genRef=firebase.database().ref('clubhouse/'+clubhousesInfo[edit_clubIndex].key+'/generalMessages');
		// genRef.once("value").then(function(data)
		// {
		// 	if(data.val() == null)
		// 		return;
		// 	var msgs = data.val();
		// 	var mKeys = Object.keys(msgs);

		// 	for(var i=0;i<mKeys.length;i++)
		// 	{
		// 		removeAllMsgs(clubhousesInfo[edit_clubIndex].key,i);
		// 	}

		//});

	}
	var removeCH = function(clubKey)
	{
		firebase.database().ref('clubhouse/'+clubKey).remove()
		.then(function(res)
		{
			clubhousesInfo = [];
			editClubhouse();
		});

	}

	var removeAllMsgs = function(clubKey,i)
	{
		var club = clubKey;
        var delMsg = firebase.database().ref("clubhouse/" + club + "/generalMessages").once("value")
        .then(function(data)
        {
            var messages = data.val();
            var keys = Object.keys(messages);

            firebase.database().ref("clubhouse/" + club + "/generalMessages/" + keys[i]).once("value")
			.then(function(data)
			{
            	var curMessage = data.val();        //  take the message object

            	if(curMessage.imageURL != -1)      // delete an image from storage
            	{
                	var storage = firebase.storage();
                	var storageRef = storage.ref();
                	var desertRef;

					if(curMessage.imageKey == -1)  // delete image to specific club
					{
					desertRef  = storageRef.child('/generalMessagesImages/' + club + '/' + curMessage.imageName);
					desertRef.delete().then(function(){}).catch(function(error){});
					}
					else
					{
						firebase.database().ref("Images/" + curMessage.imageKey).once("value")
						.then(function(data)
						{
							var details = data.val();
							if(details.capacity == 1)
							{
								desertRef  = storageRef.child('/generalMessagesImages/allClubs/' + curMessage.imageName);
								desertRef.delete().then(function(){}).catch(function(error){});
								firebase.database().ref("Images/" + curMessage.imageKey).remove();
							}
							else
							{
								var obj = {capacity:details.capacity-1};
								var imageRef = firebase.database().ref('Images/');
								imageRef.child(curMessage.imageKey).update(obj);
							}
						});

                	}
            	}
            	var deleteMsg = firebase.database().ref("clubhouse/" + club + "/generalMessages/" +keys[i]);
            	deleteMsg.remove();

           });
        });

	}

	var removeAllUsersFromCh = function(clubKey)
	{

		firebase.database().ref('clubhouse/'+clubKey+"/usersList").once("value")
		.then(function(data)
		{
			if(data.val() == null)
				return;
			var allUsers = data.val();   // get the whole tree of clubhouses
			var keys=Object.keys(allUsers);

			for (var i = 0; i < keys.length; i++)
			{
				var uRefKey= keys[i];
				console.log(allUsers[uRefKey].userkey);
				firebase.database().ref("users/"+allUsers[uRefKey].userkey).remove();
			}
			removeCH(clubhousesInfo[edit_clubIndex].key);
		});

	}

	// loads only strings of names for now.
	var loadClubhousesData = function()
	{
		var ref = firebase.database().ref("clubhouse");
		ref.once("value")
		.then(function(data)		// 		when value recieved
		{
			if (data.val() == null)
			{
				alert("לא נמצאו מועדוניות להציג");
				return;
			}
			allClubhousesObjects = data.val();
			var allClubhouses = data.val();   // get the whole tree of clubhouses
			var keys = Object.keys(allClubhouses);	// get all keys

			for(var i =0; i<keys.length;i++)
			{
				if(page == EDITPAGE)
				{
					clubhousesInfo[i] = {key:keys[i],name:allClubhouses[keys[i]].name};
					var tempBtnID = 'btn'+i;
					var btnInput =
					''+
					'
 '
					+clubhousesInfo[i].name+
					'';
					if ( i%3 == 2 && i>1 )
						btnInput += '
';
					$('#clubBottunGroup_edcm').append(btnInput);
					$('#'+tempBtnID).click(CHsellection);
				}
				if(page == ADDPAGE)
				{
					clubhousesInfo[i] = {key:keys[i],name:allClubhouses[keys[i]].name};
					$('#clubhouse_select').append('<option value="'+i+'">'+clubhousesInfo[i].name+'</option>');
				}
			}
		});
	}

	var getClubKeyIndex = function (clubName)
	{
		for (var i = 0; i < clubhousesInfo.length; i++)
		{
			if(clubName.trim() == clubhousesInfo[i].name)
				return i;
		}
		return FAIL;
	}

	var getClubhousesInfo = function()
	{
		return{ clubhousesInfo:clubhousesInfo} ;
	}

    return{getClubhousesInfo:getClubhousesInfo  , addClubhouse:addClubhouse , editClubhouse:editClubhouse};
}();<commit_msg>update remove-clubhouse<commit_after>var clubhouseManagement = function()
{
	// load data locally for edit window
	var clubhousesInfo = [];
	var allClubhousesObjects;
	const ADDPAGE = 1;
	const EDITPAGE = 2;
	const FAIL = -1;
	var page;

	// edit page vars
	var clubToEdit;
	var edit_clubname;
	var edit_clubIndex;

	///////////////////////////////////////

     //-------------------------------------------------------------------------------------------------
     // INJECTION FOR ADDING NEW CLUBHOUSE PAGE
	var addClubhousePage={
        inputSection:
		'
'+
			'
'+
						'
'+
							'
'+
								'
הוספת מועדונית
'+
								'
'+
							'
'+
						'
 '+

						'
'+
							'<form class="form-horizontal" method="post" action="#">'+

								'
'+
									':שם מועדונית'+
									'
'+
										'
'+
											''+
											'<input type="text" class="form-control" name="clubhouseName" id="clubhouseNameID"  placeholder="הכנס שם מועדונית"/>'+
										'
'+
									'
'+
								'
'+

								'
'+
									':כתובת המועדונית'+
									'
'+
										'
'+
											''+
											'<input type="text" class="form-control" name="clubhouseAddress" id="clubhouseAddrID"  placeholder="הכנס כתובת מועדונית"/>'+
										'
'+
									'
'+
								'
'+

								'
'+

								'
'+
							'</form>'+
						'
'+

				'
'
			}

			var addClubhouseBtn={
       		 inputSection:'<button type="button" id="addClubhouseBtn" class="btn btn-primary btn-lg btn-block register-button" data-toggle="modal" data-target="#myModal" >הוספה</button>'+
									'
'
			}

			var editClubhouseBtn={
       		 inputSection:'<button type="button" id="editClubhouseBtn" class="btn btn-primary btn-lg btn-block register-button" data-toggle="modal" data-target="#myModal" >עריכה</button>'+
									'
'
			}
       //-------------------------------------------------------------------------------------------------
       //       INJECTION FOR EDIT OPTION - clubhouse and user choosing
        var EditClubhousePage={
        inputSection:
                '
'+
					'
'+
						'בחר מועדונית'+
					'
'+
					'
'+
						'
'+

						'
'+
					'
'+
					'
'+
						'<button id ="editCHbtn" type="button" class="btn btn-primary btn-block btn-lg edit-button"  >ערוך פרטי מועדונית</button>'+
						'<button id ="deleteCHbtn" type="button" class="btn-danger btn-danger btn-block btn-lg  delete-button"  >הסר מועדונית</button>'+
					'
'+
				'
'
        }

    //-------------------------------------------------------------------------------------------------
    // Initial page for add clubHouse
	 var addClubhouse = function ()
	 {
		page = ADDPAGE;
		$('.Nav').collapse('hide');
		$("#body").html(addClubhousePage.inputSection); // opens page
		$('#buttonSection').html(addClubhouseBtn.inputSection);
		$("#addClubhouseBtn").click(addClubhouseListener);
	 }
	 //-------------------------------------------------------------------------------------------------
    // Initial page for edit clubHouse
	 var editClubhouse = function()
	 {
		page = EDITPAGE;
		loadClubhousesData();
		$('.Nav').collapse('hide');
		$("#body").html(EditClubhousePage.inputSection);
        $("#editCHbtn").click(EditCluhouseListener);
		$('#deleteCHbtn').click(removeCHlistener);
	 }

	//////////////////////////////////////////////////////////////////////////
	// 					ADD CLUBHOUSE										//
	//					-------------										//
	// check if club is exist, if not - create and push to DB new clubhouse.//
	/////////////////////////////////////////////////////////////////////////
	var validateAndPush = function(nameArg,addressAarg)
	{
		var ref = firebase.database().ref("clubhouse");
		ref.once("value")
		.then(function(data)		// 		when value recieved
		{
			// in case the root is empty  ->  name is not exist
			if (data.val() == null)
				return false;

			var allClubhouses = data.val();   // get the whole tree of clubhouses
			var keys = Object.keys(allClubhouses);	// get all keys

			// loop on the answere array to find clubhouse name.
			for(var i =0; i<keys.length;i++)
			{
				var k = keys[i];
				var tempName = allClubhouses[k].name;

				if( tempName == nameArg )
					return true;
			}
			return false;

		}).then(function(res)
		{
			if(res)		// name is already exist in DB
			{
				alert("המועדונית שהוזנה כבר קיימת במערכת");
				return false;
			}
			// else - push clubhouse to DB
			var newclubhouse = clubHouse.create(nameArg,addressAarg);
			var key = firebase.database().ref('clubhouse').push(newclubhouse);
			firebase.database().ref('clubhouse/'+key.key+'/ClubhouseDBkey').set(key.key); // set key property
			return true;
		}).then(function(result){
			if(result)
				alert("מועדונית התווספה בהצלחה");
			addClubhouse();
		});
	}

	//---------------------------------------------------------------------

	var addClubhouseListener = function()
	{
		var name = 	document.getElementById("clubhouseNameID").value;
		var address = document.getElementById("clubhouseAddrID").value;
		if (name == "" || address == "" )
		{
			alert("אנא הכנס שם מועדונית וכתובת");
			return;
		}
		// check if clubhouse already exists on DB and push if not.
		validateAndPush(name,address);
	}

	//////////////////////////////////////////////////////////////
	// 		EDIT CLUBHOUSE										//
	//		-------------										//
	//////////////////////////////////////////////////////////////
	// edit button from clubhosue edit menu
	var EditCluhouseListener = function(e)
	{
		var clubRef = firebase.database().ref('clubhouse/'+clubhousesInfo[edit_clubIndex].key);
		clubRef.once("value").then(function(data)
		{
			clubToEdit = data.val();	// keep ch info
			// inject html and set listener for edit page
			$('.Nav').collapse('hide');
			$("#body").html(addClubhousePage.inputSection);
			document.getElementById('titleCH').innerHTML ="עריכת מועדונית"; // change top title
			// set inputs
			$('#clubhouseAddrID').val(data.val().address);
			$('#clubhouseNameID').val(data.val().name);
			$('#buttonSection').html(editClubhouseBtn.inputSection);
			$('#editClubhouseBtn').click(changeCHListener);
		});
	}

	var changeCHListener = function()
	{
		var obj={};
		var name = $('#clubhouseNameID').val();  //current value
		var address = $('#clubhouseAddrID').val();

		if(clubToEdit.name != name)
			obj.name = name;

		if(clubToEdit.address != address)
			obj.address = address;

		var cref = firebase.database().ref('clubhouse/');
		cref.child(clubhousesInfo[edit_clubIndex].key).update(obj);
	}

	var CHsellection = function(e)
	{
		edit_clubname = e.target.innerText;
		edit_clubIndex = getClubKeyIndex(e.target.innerText.trim());
	}

	var removeCHlistener = function()
	{
		if(!edit_clubname)
			alert('לא נבחרה מועדונית');
		else
			alert('האם אתה בטוח ? פעולה זו תמחק את כל המשתמשים המשויכים למועדונית זו');
		removeAllUsersFromCh(clubhousesInfo[edit_clubIndex].key);

		// var genRef=firebase.database().ref('clubhouse/'+clubhousesInfo[edit_clubIndex].key+'/generalMessages');
		// genRef.once("value").then(function(data)
		// {
		// 	if(data.val() == null)
		// 		return;
		// 	var msgs = data.val();
		// 	var mKeys = Object.keys(msgs);

		// 	for(var i=0;i<mKeys.length;i++)
		// 	{
		// 		removeAllMsgs(clubhousesInfo[edit_clubIndex].key,i);
		// 	}

		//});

	}
	var removeCH = function(clubKey)
	{
		firebase.database().ref('clubhouse/'+clubKey).remove()
		.then(function(res)
		{
			clubhousesInfo = [];
			editClubhouse();
		});

	}

	var removeAllMsgs = function(clubKey,i)
	{
		var club = clubKey;
        var delMsg = firebase.database().ref("clubhouse/" + club + "/generalMessages").once("value")
        .then(function(data)
        {
            var messages = data.val();
            var keys = Object.keys(messages);

            firebase.database().ref("clubhouse/" + club + "/generalMessages/" + keys[i]).once("value")
			.then(function(data)
			{
            	var curMessage = data.val();        //  take the message object

            	if(curMessage.imageURL != -1)      // delete an image from storage
            	{
                	var storage = firebase.storage();
                	var storageRef = storage.ref();
                	var desertRef;

					if(curMessage.imageKey == -1)  // delete image to specific club
					{
					desertRef  = storageRef.child('/generalMessagesImages/' + club + '/' + curMessage.imageName);
					desertRef.delete().then(function(){}).catch(function(error){});
					}
					else
					{
						firebase.database().ref("Images/" + curMessage.imageKey).once("value")
						.then(function(data)
						{
							var details = data.val();
							if(details.capacity == 1)
							{
								desertRef  = storageRef.child('/generalMessagesImages/allClubs/' + curMessage.imageName);
								desertRef.delete().then(function(){}).catch(function(error){});
								firebase.database().ref("Images/" + curMessage.imageKey).remove();
							}
							else
							{
								var obj = {capacity:details.capacity-1};
								var imageRef = firebase.database().ref('Images/');
								imageRef.child(curMessage.imageKey).update(obj);
							}
						});

                	}
            	}
            	var deleteMsg = firebase.database().ref("clubhouse/" + club + "/generalMessages/" +keys[i]);
            	deleteMsg.remove();

           });
        });

	}

	var removeAllUsersFromCh = function(clubKey)
	{

		firebase.database().ref('clubhouse/'+clubKey+"/usersList").once("value")
		.then(function(data)
		{
			if(data.val() == null)
				return;
			var allUsers = data.val();   // get the whole tree of clubhouses
			var keys=Object.keys(allUsers);

			for (var i = 0; i < keys.length; i++)
			{
				var uRefKey= keys[i];
				console.log(allUsers[uRefKey].userkey);
				firebase.database().ref("users/"+allUsers[uRefKey].userkey).remove();
			}
			removeCH(clubhousesInfo[edit_clubIndex].key);  //remove clubhouse
		});

	}

	// loads only strings of names for now.
	var loadClubhousesData = function()
	{
		var ref = firebase.database().ref("clubhouse");
		ref.once("value")
		.then(function(data)		// 		when value recieved
		{
			if (data.val() == null)
			{
				alert("לא נמצאו מועדוניות להציג");
				return;
			}
			allClubhousesObjects = data.val();
			var allClubhouses = data.val();   // get the whole tree of clubhouses
			var keys = Object.keys(allClubhouses);	// get all keys

			for(var i =0; i<keys.length;i++)
			{
				if(page == EDITPAGE)
				{
					clubhousesInfo[i] = {key:keys[i],name:allClubhouses[keys[i]].name};
					var tempBtnID = 'btn'+i;
					var btnInput =
					''+
					'
 '
					+clubhousesInfo[i].name+
					'';
					if ( i%3 == 2 && i>1 )
						btnInput += '
';
					$('#clubBottunGroup_edcm').append(btnInput);
					$('#'+tempBtnID).click(CHsellection);
				}
				if(page == ADDPAGE)
				{
					clubhousesInfo[i] = {key:keys[i],name:allClubhouses[keys[i]].name};
					$('#clubhouse_select').append('<option value="'+i+'">'+clubhousesInfo[i].name+'</option>');
				}
			}
		});
	}

	var getClubKeyIndex = function (clubName)
	{
		for (var i = 0; i < clubhousesInfo.length; i++)
		{
			if(clubName.trim() == clubhousesInfo[i].name)
				return i;
		}
		return FAIL;
	}

	var getClubhousesInfo = function()
	{
		return{ clubhousesInfo:clubhousesInfo} ;
	}

    return{getClubhousesInfo:getClubhousesInfo  , addClubhouse:addClubhouse , editClubhouse:editClubhouse};
}();<|endoftext|>


<commit_before>import React from 'react';

import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';

import TableRow from '@material-ui/core/TableRow';
import IconButton from '@material-ui/core/IconButton';
import FirstPageIcon from '@material-ui/icons/FirstPage';
import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
import LastPageIcon from '@material-ui/icons/LastPage';

import TableFooter from '@material-ui/core/TableFooter';
import TablePagination from '@material-ui/core/TablePagination';

const actionsStyles = theme => ({
  root: {
    flexShrink: 0,
    color: theme.palette.text.secondary,
    marginLeft: theme.spacing.unit * 2.5,
  },
});

class TablePaginationActions extends React.Component {

  handleFirstPageButtonClick = () => {
    this.props.onChangePage(0);
  };

  handleBackButtonClick = () => {
    this.props.onChangePage(this.props.page - 1);
  };

  handleNextButtonClick = () => {
    this.props.onChangePage(this.props.page + 1);
  };

  handleLastPageButtonClick = () => {
    this.props.onChangePage(
      Math.max(0, Math.ceil(this.props.count / this.props.rowsPerPage) - 1),
    );
  };

  render() {
    const { classes, theme } = this.props;
    let count = this.props.count;
    let page = this.props.page;
    let rowsPerPage = this.props.rowsPerPage;
    return (

        <IconButton
          onClick={this.handleFirstPageButtonClick}
          disabled={page === 0}
          aria-label="First Page"
        >
          {theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
        </IconButton>
        <IconButton
          onClick={this.handleBackButtonClick}
          disabled={page === 0}
          aria-label="Previous Page"
        >
          {theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
        </IconButton>
        <IconButton
          onClick={this.handleNextButtonClick}
          disabled={page >= Math.ceil(count / rowsPerPage) - 1}
          aria-label="Next Page"
        >
          {theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
        </IconButton>
        <IconButton
          onClick={this.handleLastPageButtonClick}
          disabled={page >= Math.ceil(count / rowsPerPage) - 1}
          aria-label="Last Page"
        >
          {theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
        </IconButton>

    );
  }
}

TablePaginationActions.propTypes = {
  classes: PropTypes.object.isRequired,
  onChangePage: PropTypes.func.isRequired,
  theme: PropTypes.object.isRequired,
};

const TablePaginationActionsWrapped = withStyles(actionsStyles, { withTheme: true })(
  TablePaginationActions,
);

class ListTableFooter extends React.Component {
  constructor() {
    super();
    this.handleChangePage = this.handleChangePage.bind(this);
    this.handleChangeRowsPerPage = this.handleChangeRowsPerPage.bind(this);
  }

  render() {
    return (<TableFooter>
      <TableRow>
        <TablePagination
          colSpan={3}
          count={this.props.params.rowTotal}
          rowsPerPage={this.props.params.rowsPerPage}
          page={this.props.params.page}
          onChangePage={this.handleChangePage}
          onChangeRowsPerPage={(event) => this.handleChangeRowsPerPage(event)}
          ActionsComponent={TablePaginationActionsWrapped}
        />
      </TableRow>
    </TableFooter>);
  }

  handleChangePage(page) {
    this.props.params.setPage(page);
  };

  handleChangeRowsPerPage(event) {
    this.props.params.setRowsPerPage(event.target.value);
  };

}

export default ListTableFooter;
<commit_msg>Increase colspan to align pagination footer to the right<commit_after>import React from 'react';

import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';

import TableRow from '@material-ui/core/TableRow';
import IconButton from '@material-ui/core/IconButton';
import FirstPageIcon from '@material-ui/icons/FirstPage';
import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight';
import LastPageIcon from '@material-ui/icons/LastPage';

import TableFooter from '@material-ui/core/TableFooter';
import TablePagination from '@material-ui/core/TablePagination';

const actionsStyles = theme => ({
  root: {
    flexShrink: 0,
    color: theme.palette.text.secondary,
    marginLeft: theme.spacing.unit * 2.5,
  },
});

class TablePaginationActions extends React.Component {

  handleFirstPageButtonClick = () => {
    this.props.onChangePage(0);
  };

  handleBackButtonClick = () => {
    this.props.onChangePage(this.props.page - 1);
  };

  handleNextButtonClick = () => {
    this.props.onChangePage(this.props.page + 1);
  };

  handleLastPageButtonClick = () => {
    this.props.onChangePage(
      Math.max(0, Math.ceil(this.props.count / this.props.rowsPerPage) - 1),
    );
  };

  render() {
    const { classes, theme } = this.props;
    let count = this.props.count;
    let page = this.props.page;
    let rowsPerPage = this.props.rowsPerPage;
    return (

        <IconButton
          onClick={this.handleFirstPageButtonClick}
          disabled={page === 0}
          aria-label="First Page"
        >
          {theme.direction === 'rtl' ? <LastPageIcon /> : <FirstPageIcon />}
        </IconButton>
        <IconButton
          onClick={this.handleBackButtonClick}
          disabled={page === 0}
          aria-label="Previous Page"
        >
          {theme.direction === 'rtl' ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
        </IconButton>
        <IconButton
          onClick={this.handleNextButtonClick}
          disabled={page >= Math.ceil(count / rowsPerPage) - 1}
          aria-label="Next Page"
        >
          {theme.direction === 'rtl' ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
        </IconButton>
        <IconButton
          onClick={this.handleLastPageButtonClick}
          disabled={page >= Math.ceil(count / rowsPerPage) - 1}
          aria-label="Last Page"
        >
          {theme.direction === 'rtl' ? <FirstPageIcon /> : <LastPageIcon />}
        </IconButton>

    );
  }
}

TablePaginationActions.propTypes = {
  classes: PropTypes.object.isRequired,
  onChangePage: PropTypes.func.isRequired,
  theme: PropTypes.object.isRequired,
};

const TablePaginationActionsWrapped = withStyles(actionsStyles, { withTheme: true })(
  TablePaginationActions,
);

class ListTableFooter extends React.Component {
  constructor() {
    super();
    this.handleChangePage = this.handleChangePage.bind(this);
    this.handleChangeRowsPerPage = this.handleChangeRowsPerPage.bind(this);
  }

  render() {
    return (<TableFooter>
      <TableRow>
        <TablePagination
          colSpan={10}
          count={this.props.params.rowTotal}
          rowsPerPage={this.props.params.rowsPerPage}
          page={this.props.params.page}
          onChangePage={this.handleChangePage}
          onChangeRowsPerPage={(event) => this.handleChangeRowsPerPage(event)}
          ActionsComponent={TablePaginationActionsWrapped}
        />
      </TableRow>
    </TableFooter>);
  }

  handleChangePage(page) {
    this.props.params.setPage(page);
  };

  handleChangeRowsPerPage(event) {
    this.props.params.setRowsPerPage(event.target.value);
  };

}

export default ListTableFooter;
<|endoftext|>


<commit_before>import Node from "./node"
import * as style from "./style"

export default function fromDOM(dom, options) {
  if (!options) options = {}
  let context = new Context(options.topNode || new Node("doc"))
  context.addContent(dom, options.from || 0, options.to != null ? options.to : dom.childNodes.length)
  return context.stack[0]
}

const blockElements = {
  address: true, article: true, aside: true, blockquote: true, canvas: true,
  dd: true, div: true, dl: true, fieldset: true, figcaption: true, figure: true,
  footer: true, form: true, h1: true, h2: true, h3: true, h4: true, h5: true,
  h6: true, header: true, hgroup: true, hr: true, li: true, noscript: true, ol: true,
  output: true, p: true, pre: true, section: true, table: true, tfoot: true, ul: true
}

class Context {
  constructor(topNode) {
    this.stack = [topNode]
    this.frames = []
    this.styles = []
    this.closing = false
  }

  get top() {
    return this.stack[this.stack.length - 1]
  }

  addDOM(dom) {
    if (dom.nodeType == 3) {
      this.insert(Node.text(dom.nodeValue, this.styles))
    } else if (dom.nodeType != 1) {
      // Ignore non-text non-element nodes
    } else if (dom.hasAttribute("pm-html")) {
      let type = dom.getAttribute("pm-html")
      if (type == "html_tag")
        this.insert(new Node.Inline("html_tag", this.styles, null, {html: dom.innerHTML}))
      else
        this.insert(new Node("html_block", null, {html: dom.innerHTML}))
    } else {
      let name = dom.nodeName.toLowerCase()
      if (name in tags) {
        tags[name](dom, this)
      } else {
        this.addContent(dom)
        if (blockElements.hasOwnProperty(name) && this.top.type == Node.types.paragraph)
          this.closing = true
      }
    }
  }

  addContent(dom, start = 0, end = dom.childNodes.length) {
    for (let i = start; i < end; i++)
      this.addDOM(dom.childNodes[i])
  }

  insert(node) {
    if (this.closing) {
      let left = this.stack.pop().copy()
      this.top.push(left)
      this.stack.push(left)
      this.closing = false
    }
    let top = this.stack[this.stack.length - 1]
    if (top.type.contains == node.type.type) {
      top.push(node)
    } else {
      let route = Node.findConnection(top.type, node.type)
      if (!route) return false
      for (let i = 0; i < route.length; i++)
        this.enter(new Node(route[i]), false)
      this.top.push(node)
    }
    return true
  }

  enter(node, isFrame) {
    // FIXME is it really okay to discard what we can't place?
    if (!this.insert(node)) return false
    if (this.styles.length) this.styles = []
    if (isFrame !== false)
      this.frames.push(this.stack.length)
    this.stack.push(node)
    return true
  }

  leave() {
    this.stack.length = this.frames.pop()
    this.closing = false
  }
}

const tags = Object.create(null)

function wrap(dom, context, node) {
  if (context.enter(node)) {
    context.addContent(dom)
    context.leave()
  }
}

function wrapAs(type) {
  return (dom, context) => wrap(dom, context, new Node(type))
}

function inline(dom, context, added) {
  var old = context.styles
  context.styles = style.add(old, added)
  context.addContent(dom)
  context.styles = old
}

tags.p = wrapAs("paragraph")

tags.blockquote = wrapAs("blockquote")

for (var i = 1; i <= 6; i++) (function(attrs) {
  tags["h" + i] = (dom, context) => wrap(dom, context, new Node("heading", null, attrs))
})({level: i})

tags.hr = (_, context) => context.insert(new Node("horizontal_rule"))

tags.pre = (dom, context) => {
  let params = dom.firstChild && /^code$/i.test(dom.firstChild.nodeName) && dom.firstChild.getAttribute("class")
  if (params && /fence/.test(params)) {
    let found = [], re = /(?:^|\s)lang-(\S+)/g, m
    while (m = re.test(params)) found.push(m[1])
    params = found.join(" ")
  } else {
    params = null
  }
  context.insert(new Node("code_block", [Node.text(dom.textContent)], {params: params}))
}

tags.ul = (dom, context) => {
  let cls = dom.getAttribute("class")
  let attrs = {bullet: /bullet_dash/.test(cls) ? "-" : /bullet_plus/.test(cls) ? "+" : "*",
               tight: /\btight\b/.test(dom.getAttribute("class"))}
  wrap(dom, context, new Node("bullet_list", null, attrs))
}

tags.ol = (dom, context) => {
  let attrs = {order: dom.getAttribute("start") || 1,
               tight: /\btight\b/.test(dom.getAttribute("class"))}
  wrap(dom, context, new Node("ordered_list", null, attrs))
}

tags.li = wrapAs("list_item")

tags.br = (_, context) => context.insert(new Node.Inline("hard_break", context.styles))

tags.a = (dom, context) => inline(dom, context, style.link(dom.getAttribute("href"), dom.getAttribute("title")))

tags.b = tags.strong = (dom, context) => inline(dom, context, style.strong)

tags.i = tags.em = (dom, context) => inline(dom, context, style.em)

tags.code = (dom, context) => inline(dom, context, style.code)

tags.img = (dom, context) => {
  let attrs = {src: dom.getAttribute("src"),
               title: dom.getAttribute("title") || null,
               alt: dom.getAttribute("alt") || null}
  context.insert(new Node.Inline("image", null, attrs))
}
<commit_msg>Improve DOM parsing<commit_after>import Node from "./node"
import * as style from "./style"

export default function fromDOM(dom, options) {
  if (!options) options = {}
  let context = new Context(options.topNode || new Node("doc"))
  let start = options.from ? dom.childNodes[options.from] : dom.firstChild
  let end = options.to != null && dom.childNodes[options.to] || null
  context.addAll(start, end, true)
  return context.stack[0]
}

const blockElements = {
  address: true, article: true, aside: true, blockquote: true, canvas: true,
  dd: true, div: true, dl: true, fieldset: true, figcaption: true, figure: true,
  footer: true, form: true, h1: true, h2: true, h3: true, h4: true, h5: true,
  h6: true, header: true, hgroup: true, hr: true, li: true, noscript: true, ol: true,
  output: true, p: true, pre: true, section: true, table: true, tfoot: true, ul: true
}

class Context {
  constructor(topNode) {
    this.stack = [topNode]
    this.styles = []
    this.closing = false
  }

  get top() {
    return this.stack[this.stack.length - 1]
  }

  addDOM(dom) {
    if (dom.nodeType == 3) {
      let value = dom.nodeValue
      let top = this.top, inline = top.type.contains == "inline"
      if (/\S/.test(value) || inline) {
        value = value.replace(/\s+/g, " ")
        if (/^\s/.test(value) && top.content.length && /\s$/.test(top.content[top.content.length - 1].text))
          value = value.slice(1)
        this.insert(Node.text(value, this.styles))
      }
    } else if (dom.nodeType != 1) {
      // Ignore non-text non-element nodes
    } else if (dom.hasAttribute("pm-html")) {
      let type = dom.getAttribute("pm-html")
      if (type == "html_tag")
        this.insert(new Node.Inline("html_tag", this.styles, null, {html: dom.innerHTML}))
      else
        this.insert(new Node("html_block", null, {html: dom.innerHTML}))
    } else {
      let name = dom.nodeName.toLowerCase()
      if (name in tags) {
        tags[name](dom, this)
      } else {
        this.addAll(dom.firstChild, null)
        if (blockElements.hasOwnProperty(name) && this.top.type == Node.types.paragraph)
          this.closing = true
      }
    }
  }

  addAll(from, to, sync) {
    let stack = sync && this.stack.slice()
    for (let dom = from; dom != to; dom = dom.nextSibling) {
      this.addDOM(dom)
      if (sync && blockElements.hasOwnProperty(dom.nodeName.toLowerCase()))
        this.sync(stack)
    }
  }

  doClose() {
    if (!this.closing) return
    let left = this.stack.pop().copy()
    this.top.push(left)
    this.stack.push(left)
    this.closing = false
  }

  insert(node) {
    if (this.top.type.contains == node.type.type) {
      this.doClose()
    } else {
      for (let i = this.stack.length - 1; i >= 0; i--) {
        let route = Node.findConnection(this.stack[i].type, node.type)
        if (!route) continue
        if (i == this.stack.length - 1)
          this.doClose()
        else
          this.stack.length = i + 1
        for (let j = 0; j < route.length; j++) {
          let wrap = new Node(route[j])
          this.top.push(wrap)
          this.stack.push(wrap)
        }
        if (this.styles.length) this.styles = []
        break
      }
    }
    this.top.push(node)
  }

  enter(node) {
    this.insert(node)
    if (this.styles.length) this.styles = []
    this.stack.push(node)
  }

  sync(stack) {
    while (this.stack.length > stack.length) this.stack.pop()
    while (!stack[this.stack.length - 1].sameMarkup(stack[this.stack.length - 1])) this.stack.pop()
    while (stack.length > this.stack.length) {
      let add = stack[this.stack.length].copy()
      this.top.push(add)
      this.stack.push(add)
    }
    if (this.styles.length) this.styles = []
    this.closing = false
  }
}

const tags = Object.create(null)

function wrap(dom, context, node) {
  context.enter(node)
  context.addAll(dom.firstChild, null, true)
  context.stack.pop()
}

function wrapAs(type) {
  return (dom, context) => wrap(dom, context, new Node(type))
}

function inline(dom, context, added) {
  var old = context.styles
  context.styles = style.add(old, added)
  context.addAll(dom.firstChild, null)
  context.styles = old
}

tags.p = wrapAs("paragraph")

tags.blockquote = wrapAs("blockquote")

for (var i = 1; i <= 6; i++) (function(attrs) {
  tags["h" + i] = (dom, context) => wrap(dom, context, new Node("heading", null, attrs))
})({level: i})

tags.hr = (_, context) => context.insert(new Node("horizontal_rule"))

tags.pre = (dom, context) => {
  let params = dom.firstChild && /^code$/i.test(dom.firstChild.nodeName) && dom.firstChild.getAttribute("class")
  if (params && /fence/.test(params)) {
    let found = [], re = /(?:^|\s)lang-(\S+)/g, m
    while (m = re.test(params)) found.push(m[1])
    params = found.join(" ")
  } else {
    params = null
  }
  context.insert(new Node("code_block", [Node.text(dom.textContent)], {params: params}))
}

tags.ul = (dom, context) => {
  let cls = dom.getAttribute("class")
  let attrs = {bullet: /bullet_dash/.test(cls) ? "-" : /bullet_plus/.test(cls) ? "+" : "*",
               tight: /\btight\b/.test(dom.getAttribute("class"))}
  wrap(dom, context, new Node("bullet_list", null, attrs))
}

tags.ol = (dom, context) => {
  let attrs = {order: dom.getAttribute("start") || 1,
               tight: /\btight\b/.test(dom.getAttribute("class"))}
  wrap(dom, context, new Node("ordered_list", null, attrs))
}

tags.li = wrapAs("list_item")

tags.br = (_, context) => context.insert(new Node.Inline("hard_break", context.styles))

tags.a = (dom, context) => inline(dom, context, style.link(dom.getAttribute("href"), dom.getAttribute("title")))

tags.b = tags.strong = (dom, context) => inline(dom, context, style.strong)

tags.i = tags.em = (dom, context) => inline(dom, context, style.em)

tags.code = (dom, context) => inline(dom, context, style.code)

tags.img = (dom, context) => {
  let attrs = {src: dom.getAttribute("src"),
               title: dom.getAttribute("title") || null,
               alt: dom.getAttribute("alt") || null}
  context.insert(new Node.Inline("image", null, null, attrs))
}
<|endoftext|>