<commit_before>module.exports = (function () {

    // Default

    function _beforeEach(transition) {
        var roles,
            auth = _toArray(transition.to.auth);

        if (auth && (auth === true || auth.constructor === Array)) {
            if ( ! this.check()) {
                this.$router.replace(this.getOption('authRedirect'));
            }
            else if (auth.constructor === Array && ! _compare(auth, _toArray(this.user()[this.getOption('rolesVar')]))) {
                this.$router.replace(this.getOption('forbiddenRedirect'));
            }
            else {
                return transition.next();
            }
        }
        else if (auth === false && this.check()) {
            this.$router.replace(this.getOption('notFoundRedirect'));
        }
        else {
            return transition.next();
        }
    }

    function _userData(resp) {
        return resp.data;
    }

    function _cookieDomain() {
        return window.location.hostname;
    }

    // Utils

    function _getUrl() {
        var port = window.location.port;

        return window.location.protocol + '//' + window.location.hostname + (port ? ':' + port : '');
    }

    function _compare(one, two) {
        var i, ii;

        one = _toArray(one);
        two = _toArray(two);

        if (one.constructor !== Array || two.constructor !== Array) {
            return false;
        }

        for (i = 0, ii = one.length; i < ii; i++) {
            if (two.indexOf(one[i]) >= 0) {
                return true;
            }
        }

        return false;
    }

    function _toArray(val) {
        return (typeof val) === 'string' ? [val] : val;
    }

    // Remember Me

    function _setCookie(name, value, timeOffset) {
        var domain  = this.getOption('cookieDomain').call(this),
            expires = (new Date((new Date).getTime() + timeOffset)).toUTCString();

        document.cookie = (name + '=' + value + '; domain=' + domain + '; path=/;' + (timeOffset ? ' expires=' + expires + ';' : '') );
    }

    function _setRememberMeCookie(rememberMe) {
        _setCookie.call(this,
            'rememberMe',
            rememberMe === true ? 'true' : 'false',
            rememberMe === true ? 12096e5 : undefined
        );
    }

    function _removeRememberMeCookie() {
        _setCookie.call(this, 'rememberMe', 'false', -12096e5);
    }

    // Token

    function _setToken(token) {
        if (token) {
            localStorage.setItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName'), token);
        }
    }

    function _getToken() {
        return localStorage.getItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName'));
    }

    function _removeToken() {
        localStorage.removeItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName'));
    }

    function _refreshToken() {
        if (_getToken.call(this)) {
            this.$http.get(this.getOption('tokenUrl'));
        }
    }

    // Router

    function _setRoute(route, router) {
        this.$route = route;
        this.$router = router;
    }

    // Auth

    function _login(path, data, rememberMe, redirectUrl, options) {
        options = options || {};

        this.$http.post(path, data, function(resp) {
            var _this = this;

            _setRememberMeCookie.call(this, rememberMe);

            _setToken.call(this, resp[this.getOption('tokenVar')]);

            this.authenticated = null;

            this.fetch(function () {
                if (options.success) {
                    options.success.call(_this, resp);
                }

                if (redirectUrl && _this.check()) {
                    _this.$router.go(redirectUrl);
                }
            });
        }, {
            error: function (resp) {
                if (options.error) {
                    options.error.call(this, resp);
                }
            }
        });
    }

    function _social(type, data, rememberMe, redirectUrl, options) {
        var state,
            params = '';

        data = data || {};

        if (data.code) {
            state = JSON.parse(this.$route.query.state);

            _login.call(this, this.getOption(type + 'Url'), data, state.rememberMe, state.redirect, options);
        }
        else {
            data.state = data.state || {};
            data.state.rememberMe = rememberMe === true ? true : false;
            data.state.redirect = redirectUrl || '';

            data.appId = data.appId || this.getOption(type + 'AppId');
            data.clientId = data.clientId || this.getOption(type + 'ClientId');
            data.scope = data.scope || this.getOption(type + 'Scope');
            data.redirect = data.redirect || this.getOption(type + 'Redirect');

            params = '?client_id=' + data.appId + '&redirect_uri=' + data.redirect + '&scope=' + data.scope + '&response_type=code&state=' + JSON.stringify(data.state);

            if (type === 'facebook') {
                window.location = 'https://www.facebook.com/v2.5/dialog/oauth' + params;
            }
            else if (type === 'google') {
                window.location = 'https://accounts.google.com/o/oauth2/auth' + params;
            }
            // else if (type === 'twitter') {
            //     window.location = 'https://oauth.twitter.com/2/authorize?oauth_callback_url=' + data.redirect + '&oauth_mode=flow_web_client&oauth_client_identifier=' + data.appId + '&redirect_uri=' + data.redirect + '&response_type=token&client_id=' + data.clientId;
            // }
        }
    }

    function _fetch(cb) {
        cb = cb || function () {};

        this.$http.get(this.getOption('fetchUrl'), function(resp) {
            this.authenticated = true;
            this.data = this.getOption('userData').call(this, resp);
            this.loaded = true;

            return cb();
        }, {
            error: function() {
                this.loaded = true;

                return cb();
            }
        });
    }

    // Plugin

    var Auth = {
        options: {
            authType          : 'bearer',

            fetchUrl          : '/auth/user',
            tokenUrl          : '/auth/token',
            loginUrl          : '/auth/login',
            loginAsUrl        : '/auth/login-as',

            logoutRedirect    : '/',
            notFoundRedirect  : '/404',
            forbiddenRedirect : '/403',

            rolesVar          : 'roles',
            tokenVar          : 'token',
            tokenName         : 'jwt-auth-token',

            cookieDomain      : _cookieDomain,
            userData          : _userData,
            beforeEach        : _beforeEach,

            facebookUrl       : '/auth/facebook',
            facebookAppId     : '',
            facebookScope     : 'email',
            facebookRedirect  : _getUrl() + '/login/facebook',

            googleUrl         : '/auth/google',
            googleAppId       : '',
            googleScope       : 'https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.profile.emails.read',
            googleRedirect    : _getUrl() + '/login/google',
        },

        data: function () {
            return {
                data: null,
                loaded: false,
                authenticated: null
            };
        },

        created: function () {
            var _this = this;

            Vue.http.interceptors.push({

                // Send auth token on each request.
                request: function (req) {
                    var token = _getToken.call(_this);

                    if (token) {
                        if (_this.getOption('authType') === 'bearer') {
                            req.headers.Authorization = 'Bearer: ' + token;
                        }
                    }

                    return req;
                },

                // Reset auth token if provided in response.
                response: function (res) {
                    var authorization = res.headers('authorization');

                    if (authorization) {
                        authorization = authorization.split(' ');

                        if (authorization[1]) {
                            _setToken.call(this, authorization[1]);
                        }
                    }

                    return res;
                }
            });
        },

        methods: {

            // Options

            getOption: function (key) {
                return this.$options.options[key];
            },

            setOptions: function (options) {
                for (var i in options) {
                    this.$options.options[i] = options[i];
                }
            },

            // Login / Logout

            login: function (data, rememberMe, redirectUrl, options) {
                _login.call(this, this.getOption('loginUrl'), data, rememberMe, redirectUrl, options);
            },

            facebook: function (data, rememberMe, redirectUrl, options) {
                _social.call(this, 'facebook', data, rememberMe, redirectUrl, options);
            },

            google: function (data, rememberMe, redirectUrl, options) {
                _social.call(this, 'google', data, rememberMe, redirectUrl, options);
            },

            logout: function(redirectUrl, force) {
                _removeRememberMeCookie.call(this);

                // Need to call twice to remove both tokens.
                _removeToken.call(this);
                _removeToken.call(this);

                this.authenticated = false;
                this.data = null;

                if (redirectUrl && (this.$route.auth || force)) {
                    this.$router.go(redirectUrl);
                }
            },

            // User

            check: function (role) {
                if (this.data !== null) {
                    if (role) {
                        return _compare(role, this.data[this.getOption('rolesVar')]);
                    }

                    return true;
                }

                return false;
            },

            fetch: function(cb) {
                cb = cb || function () {};

                if ( ! this.loaded) {
                    _refreshToken.call(this);
                }

                if (this.authenticated === null && _getToken.call(this)) {
                    if ( ! document.cookie.match(/rememberMe/)) {
                        _removeToken.call(this);

                        this.loaded = true;

                        return cb();
                    }

                    this.authenticated = false;

                    _fetch.call(this, cb);
                }
                else {
                    this.loaded = true;

                    return cb();
                }
            },

            user: function() {
                return this.data;
            },

            ready: function() {
                return this.loaded;
            },

            // Login As

            loginAs: function(data, redirectUrl, options) {
                options = options || {};

                this.$http.post(this.getOption('loginAsUrl'), data, function(resp) {
                    var _this = this;

                    localStorage.setItem('login-as-' + this.getOption('tokenName'), resp[this.getOption('tokenVar')]);

                    _fetch.call(this, function () {
                        if (options.success) {
                            options.success.call(this, resp);
                        }

                        if (redirectUrl && _this.check()) {
                            _this.$router.go(redirectUrl);
                        }
                    });
                }, {
                    error: function (resp) {
                        if (options.error) {
                            options.error.call(this, resp);
                        }
                    }
                });
            },

            logoutAs: function(redirectUrl) {
                var _this = this;

                localStorage.removeItem('login-as-' + this.getOption('tokenName'));

                _fetch.call(this, function () {
                    if (redirectUrl) {
                        _this.$router.go(redirectUrl);
                    }
                });
            },

            other: function() {
                this.data; // TODO: Strange thing, need this to make the check fire consistently ??

                return localStorage.getItem('login-as-' + this.getOption('tokenName'));
            }
        }
    };

    return function install(Vue, options, router) {
        var auth = new Vue(Auth);

        auth.setOptions(options || {});

        Object.defineProperties(Vue.prototype, {
            $auth: {
                get: function () {
                    _setRoute.call(auth, this.$route, this.$router);

                    return auth;
                }
            }
        });

        // // Setup before each route change check.
        (Vue.router || router).beforeEach(function (transition) {

            // Make sure to use $auth.fetch so context is loaded.
            transition.to.router.app.$auth.fetch(function () {
                auth.getOption('beforeEach').bind(auth)(transition);
            });
        });
    }
})();<commit_msg>Fix missing Vue instance for $http interceptors.<commit_after>module.exports = (function () {

    // Default

    function _beforeEach(transition) {
        var roles,
            auth = _toArray(transition.to.auth);

        if (auth && (auth === true || auth.constructor === Array)) {
            if ( ! this.check()) {
                this.$router.replace(this.getOption('authRedirect'));
            }
            else if (auth.constructor === Array && ! _compare(auth, _toArray(this.user()[this.getOption('rolesVar')]))) {
                this.$router.replace(this.getOption('forbiddenRedirect'));
            }
            else {
                return transition.next();
            }
        }
        else if (auth === false && this.check()) {
            this.$router.replace(this.getOption('notFoundRedirect'));
        }
        else {
            return transition.next();
        }
    }

    function _userData(resp) {
        return resp.data;
    }

    function _cookieDomain() {
        return window.location.hostname;
    }

    // Utils

    function _getUrl() {
        var port = window.location.port;

        return window.location.protocol + '//' + window.location.hostname + (port ? ':' + port : '');
    }

    function _compare(one, two) {
        var i, ii;

        one = _toArray(one);
        two = _toArray(two);

        if (one.constructor !== Array || two.constructor !== Array) {
            return false;
        }

        for (i = 0, ii = one.length; i < ii; i++) {
            if (two.indexOf(one[i]) >= 0) {
                return true;
            }
        }

        return false;
    }

    function _toArray(val) {
        return (typeof val) === 'string' ? [val] : val;
    }

    // Remember Me

    function _setCookie(name, value, timeOffset) {
        var domain  = this.getOption('cookieDomain').call(this),
            expires = (new Date((new Date).getTime() + timeOffset)).toUTCString();

        document.cookie = (name + '=' + value + '; domain=' + domain + '; path=/;' + (timeOffset ? ' expires=' + expires + ';' : '') );
    }

    function _setRememberMeCookie(rememberMe) {
        _setCookie.call(this,
            'rememberMe',
            rememberMe === true ? 'true' : 'false',
            rememberMe === true ? 12096e5 : undefined
        );
    }

    function _removeRememberMeCookie() {
        _setCookie.call(this, 'rememberMe', 'false', -12096e5);
    }

    // Token

    function _setToken(token) {
        if (token) {
            localStorage.setItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName'), token);
        }
    }

    function _getToken() {
        return localStorage.getItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName'));
    }

    function _removeToken() {
        localStorage.removeItem( (this.other() ? 'login-as-' : '') + this.getOption('tokenName'));
    }

    function _refreshToken() {
        if (_getToken.call(this)) {
            this.$http.get(this.getOption('tokenUrl'));
        }
    }

    // Router

    function _setRoute(route, router) {
        this.$route = route;
        this.$router = router;
    }

    // Auth

    function _login(path, data, rememberMe, redirectUrl, options) {
        options = options || {};

        this.$http.post(path, data, function(resp) {
            var _this = this;

            _setRememberMeCookie.call(this, rememberMe);

            _setToken.call(this, resp[this.getOption('tokenVar')]);

            this.authenticated = null;

            this.fetch(function () {
                if (options.success) {
                    options.success.call(_this, resp);
                }

                if (redirectUrl && _this.check()) {
                    _this.$router.go(redirectUrl);
                }
            });
        }, {
            error: function (resp) {
                if (options.error) {
                    options.error.call(this, resp);
                }
            }
        });
    }

    function _social(type, data, rememberMe, redirectUrl, options) {
        var state,
            params = '';

        data = data || {};

        if (data.code) {
            state = JSON.parse(this.$route.query.state);

            _login.call(this, this.getOption(type + 'Url'), data, state.rememberMe, state.redirect, options);
        }
        else {
            data.state = data.state || {};
            data.state.rememberMe = rememberMe === true ? true : false;
            data.state.redirect = redirectUrl || '';

            data.appId = data.appId || this.getOption(type + 'AppId');
            data.clientId = data.clientId || this.getOption(type + 'ClientId');
            data.scope = data.scope || this.getOption(type + 'Scope');
            data.redirect = data.redirect || this.getOption(type + 'Redirect');

            params = '?client_id=' + data.appId + '&redirect_uri=' + data.redirect + '&scope=' + data.scope + '&response_type=code&state=' + JSON.stringify(data.state);

            if (type === 'facebook') {
                window.location = 'https://www.facebook.com/v2.5/dialog/oauth' + params;
            }
            else if (type === 'google') {
                window.location = 'https://accounts.google.com/o/oauth2/auth' + params;
            }
            // else if (type === 'twitter') {
            //     window.location = 'https://oauth.twitter.com/2/authorize?oauth_callback_url=' + data.redirect + '&oauth_mode=flow_web_client&oauth_client_identifier=' + data.appId + '&redirect_uri=' + data.redirect + '&response_type=token&client_id=' + data.clientId;
            // }
        }
    }

    function _fetch(cb) {
        cb = cb || function () {};

        this.$http.get(this.getOption('fetchUrl'), function(resp) {
            this.authenticated = true;
            this.data = this.getOption('userData').call(this, resp);
            this.loaded = true;

            return cb();
        }, {
            error: function() {
                this.loaded = true;

                return cb();
            }
        });
    }

    // Plugin

    var Auth = {
        options: {
            authType          : 'bearer',

            fetchUrl          : '/auth/user',
            tokenUrl          : '/auth/token',
            loginUrl          : '/auth/login',
            loginAsUrl        : '/auth/login-as',

            logoutRedirect    : '/',
            notFoundRedirect  : '/404',
            forbiddenRedirect : '/403',

            rolesVar          : 'roles',
            tokenVar          : 'token',
            tokenName         : 'jwt-auth-token',

            cookieDomain      : _cookieDomain,
            userData          : _userData,
            beforeEach        : _beforeEach,

            facebookUrl       : '/auth/facebook',
            facebookAppId     : '',
            facebookScope     : 'email',
            facebookRedirect  : _getUrl() + '/login/facebook',

            googleUrl         : '/auth/google',
            googleAppId       : '',
            googleScope       : 'https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.profile.emails.read',
            googleRedirect    : _getUrl() + '/login/google',
        },

        data: function () {
            return {
                data: null,
                loaded: false,
                authenticated: null
            };
        },

        created: function () {
            var _this = this;

            this.$http.interceptors.push({

                // Send auth token on each request.
                request: function (req) {
                    var token = _getToken.call(_this);

                    if (token) {
                        if (_this.getOption('authType') === 'bearer') {
                            req.headers.Authorization = 'Bearer: ' + token;
                        }
                    }

                    return req;
                },

                // Reset auth token if provided in response.
                response: function (res) {
                    var authorization = res.headers('authorization');

                    if (authorization) {
                        authorization = authorization.split(' ');

                        if (authorization[1]) {
                            _setToken.call(this, authorization[1]);
                        }
                    }

                    return res;
                }
            });
        },

        methods: {

            // Options

            getOption: function (key) {
                return this.$options.options[key];
            },

            setOptions: function (options) {
                for (var i in options) {
                    this.$options.options[i] = options[i];
                }
            },

            // Login / Logout

            login: function (data, rememberMe, redirectUrl, options) {
                _login.call(this, this.getOption('loginUrl'), data, rememberMe, redirectUrl, options);
            },

            facebook: function (data, rememberMe, redirectUrl, options) {
                _social.call(this, 'facebook', data, rememberMe, redirectUrl, options);
            },

            google: function (data, rememberMe, redirectUrl, options) {
                _social.call(this, 'google', data, rememberMe, redirectUrl, options);
            },

            logout: function(redirectUrl, force) {
                _removeRememberMeCookie.call(this);

                // Need to call twice to remove both tokens.
                _removeToken.call(this);
                _removeToken.call(this);

                this.authenticated = false;
                this.data = null;

                if (redirectUrl && (this.$route.auth || force)) {
                    this.$router.go(redirectUrl);
                }
            },

            // User

            check: function (role) {
                if (this.data !== null) {
                    if (role) {
                        return _compare(role, this.data[this.getOption('rolesVar')]);
                    }

                    return true;
                }

                return false;
            },

            fetch: function(cb) {
                cb = cb || function () {};

                if ( ! this.loaded) {
                    _refreshToken.call(this);
                }

                if (this.authenticated === null && _getToken.call(this)) {
                    if ( ! document.cookie.match(/rememberMe/)) {
                        _removeToken.call(this);

                        this.loaded = true;

                        return cb();
                    }

                    this.authenticated = false;

                    _fetch.call(this, cb);
                }
                else {
                    this.loaded = true;

                    return cb();
                }
            },

            user: function() {
                return this.data;
            },

            ready: function() {
                return this.loaded;
            },

            // Login As

            loginAs: function(data, redirectUrl, options) {
                options = options || {};

                this.$http.post(this.getOption('loginAsUrl'), data, function(resp) {
                    var _this = this;

                    localStorage.setItem('login-as-' + this.getOption('tokenName'), resp[this.getOption('tokenVar')]);

                    _fetch.call(this, function () {
                        if (options.success) {
                            options.success.call(this, resp);
                        }

                        if (redirectUrl && _this.check()) {
                            _this.$router.go(redirectUrl);
                        }
                    });
                }, {
                    error: function (resp) {
                        if (options.error) {
                            options.error.call(this, resp);
                        }
                    }
                });
            },

            logoutAs: function(redirectUrl) {
                var _this = this;

                localStorage.removeItem('login-as-' + this.getOption('tokenName'));

                _fetch.call(this, function () {
                    if (redirectUrl) {
                        _this.$router.go(redirectUrl);
                    }
                });
            },

            other: function() {
                this.data; // TODO: Strange thing, need this to make the check fire consistently ??

                return localStorage.getItem('login-as-' + this.getOption('tokenName'));
            }
        }
    };

    return function install(Vue, options, router) {
        var auth = new Vue(Auth);

        auth.setOptions(options || {});

        Object.defineProperties(Vue.prototype, {
            $auth: {
                get: function () {
                    _setRoute.call(auth, this.$route, this.$router);

                    return auth;
                }
            }
        });

        // // Setup before each route change check.
        (Vue.router || router).beforeEach(function (transition) {

            // Make sure to use $auth.fetch so context is loaded.
            transition.to.router.app.$auth.fetch(function () {
                auth.getOption('beforeEach').bind(auth)(transition);
            });
        });
    }
})();<|endoftext|>


<commit_before>/*
 * to run tests (from pouchdb root dir)
 * $ qunit -t ./tests/test.attachments.js \
        -d ./src/pouch.js ./tests/test.utils.js \
        -c ./src/adapters/pouch.leveldb.js
 */
var adapters = ['idb-1', 'http-1']
  , repl_adapters = [['idb-1', 'http-1'],
         ['http-1', 'http-2'],
         ['http-1', 'idb-1'],
         ['idb-1', 'idb-2']]
  , qunit = module;

// if we are running under node.js, set things up
// a little differently, and only test the leveldb adapter
if (typeof module !== undefined && module.exports) {
  this.Pouch = require('../src/pouch.js');
  this.LevelPouch = require('../src/adapters/pouch.leveldb.js');
  this.utils = require('./test.utils.js');

  for (var k in this.utils) {
    global[k] = global[k] || this.utils[k];
  }
  qunit = QUnit.module;
  adapters = ['ldb-1', 'http-1'];
  repl_adapters = [['ldb-1', 'http-1'],
         ['http-1', 'http-2'],
         ['http-1', 'ldb-1'],
         ['ldb-1', 'ldb-2']];
}

adapters.map(function(adapter) {
  qunit('attachments: ' + adapter, {
    setup : function () {
      this.name = generateAdapterUrl(adapter);
    }
  });

  var binAttDoc = {
    _id: "bin_doc",
    _attachments:{
      "foo.txt": {
        content_type:"text/plain",
        data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
      }
    }
  };

  // empty attachment
  var binAttDoc2 = {
    _id: "bin_doc2",
    _attachments:{
      "foo.txt": {
        content_type:"text/plain",
        data: ""
      }
    }
  }

  // json string doc
  var jsonDoc = {
    _id: 'json_doc',
    _attachments: {
      "foo.json": {
        content_type: "text/plain",
        data: btoa('{"Hello":"world"}')
      }
    }
  }

  asyncTest("Test some attachments", function() {
    var db;
    initTestDB(this.name, function(err, _db) {
      db = _db;
      db.put(binAttDoc, function(err, write) {
        ok(!err, 'saved doc with attachment');
        db.get('bin_doc/foo.txt', function(err, res) {
          equal(res, 'This is a base64 encoded text', 'Correct data returned');
          db.put(binAttDoc2, function(err, rev) {
            db.get('bin_doc2/foo.txt', function(err, res, xhr) {
              equal(res, '', 'Correct data returned');
              moreTests(rev.rev);
            });
          });
        });
      });
    });

    function moreTests(rev) {
      var ndoc = 'This is no base64 encoded text';
      db.putAttachment('bin_doc2/foo2.txt', rev, ndoc, "text/plain", function() {
        db.get('bin_doc2/foo2.txt', function(err, res, xhr) {
          ok(res === 'This is no base64 encoded text', 'Correct data returned');
          db.get('bin_doc2', {attachments: true}, function(err, res, xhr) {
            ok(res._attachments, 'Result has attachments field');
            equal(res._attachments['foo2.txt'].data,
                  btoa('This is no base64 encoded text', 'binary'));
            equal(res._attachments['foo.txt'].data, '');
            start();
          });
        });
      });
    };

  });

  asyncTest("Test put attachment on a doc without attachments", function() {
    initTestDB(this.name, function(err, db) {
      db.put({ _id: 'mydoc' }, function(err, resp) {
        db.putAttachment('mydoc/mytext', resp.rev, 'Mytext', 'text/plain', function(err, res) {
          ok(res.ok);
          start();
        })
      });
    });
  });

  asyncTest("Test a document with a json string attachment", function() {
    initTestDB(this.name, function(err, db) {
      db.put(jsonDoc, function(err, results) {
        ok(!err, 'saved doc with attachment');
        db.get(results.id, function(err, doc) {
          ok(!err, 'fetched doc')
          ok(doc._attachments, 'doc has attachment')
          db.get(results.id + '/' + 'foo.json', function(err, attachment) {
            equal(attachment, atob(jsonDoc._attachments['foo.json'].data), 'correct data');
            start();
          });
        });
      });
    });
  });

  asyncTest("Test remove doc with attachment", function() {
    initTestDB(this.name, function(err, db) {
      db.put({ _id: 'mydoc' }, function(err, resp) {
        db.putAttachment('mydoc/mytext', resp.rev, 'Mytext', 'text/plain', function(err, res) {
          db.get('mydoc',{attachments:false},function(err,doc){
            db.remove(doc, function(err, resp){
              ok(res.ok);
              start();
            });
          });
        });
      });
    });
  });

  asyncTest("Insert a doc with a / in the _id", function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      var doc = {_id: 'doc/attachment', test: true};
      db.put(doc, function(err, info) {
        ok(!err, 'saved doc')
        equal(info.id, 'doc', '_id got truncated');
        db.get('doc', {attachments: true}, function(err, doc2) {
          ok(!err, 'retreived the doc');
          ok(doc2._attachments['attachment'], 'it has the attachment');
          equal(doc2._attachments['attachment'].data, btoa(JSON.stringify(doc)),
             'the attachment matches the original doc');

          db.get('doc/attachment', function(err, response) {
            ok(!err, 'got the attachment');
            equal(response, JSON.stringify(doc),
                  'the attachment is returned as a JSON string');
            var obj = JSON.parse(response);
            equal(obj._id, doc._id, 'id matches');
            equal(obj.test, doc.test, 'test matches');
            start();
          });
        });

      });
    });
  })
});

repl_adapters.map(function(adapters) {

  qunit('replication: ' + adapters[0] + ':' + adapters[1], {
    setup : function () {
      this.name = generateAdapterUrl(adapters[0]);
      this.remote = generateAdapterUrl(adapters[1]);
    }
  });

    asyncTest("Attachments replicate", function() {
        console.info('Starting Test: Attachments replicate');

        var binAttDoc = {
          _id: "bin_doc",
          _attachments:{
            "foo.txt": {
              content_type:"text/plain",
              data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
            }
          }
        };

        var docs1 = [
          binAttDoc,
          {_id: "0", integer: 0},
          {_id: "1", integer: 1},
          {_id: "2", integer: 2},
          {_id: "3", integer: 3}
        ];

        initDBPair(this.name, this.remote, function(db, remote) {
          remote.bulkDocs({docs: docs1}, function(err, info) {
            var replicate = db.replicate.from(remote, function() {
              db.get('bin_doc', {attachments: true}, function(err, doc) {
                equal(binAttDoc._attachments['foo.txt'].data,
                      doc._attachments['foo.txt'].data);
                start();
              });
            });
          });
        });
    });

});
<commit_msg>attachment deletion test<commit_after>/*
 * to run tests (from pouchdb root dir)
 * $ qunit -t ./tests/test.attachments.js \
        -d ./src/pouch.js ./tests/test.utils.js \
        -c ./src/adapters/pouch.leveldb.js
 */
var adapters = ['idb-1', 'http-1']
  , repl_adapters = [['idb-1', 'http-1'],
         ['http-1', 'http-2'],
         ['http-1', 'idb-1'],
         ['idb-1', 'idb-2']]
  , qunit = module;

// if we are running under node.js, set things up
// a little differently, and only test the leveldb adapter
if (typeof module !== undefined && module.exports) {
  this.Pouch = require('../src/pouch.js');
  this.LevelPouch = require('../src/adapters/pouch.leveldb.js');
  this.utils = require('./test.utils.js');

  for (var k in this.utils) {
    global[k] = global[k] || this.utils[k];
  }
  qunit = QUnit.module;
  adapters = ['ldb-1', 'http-1'];
  repl_adapters = [['ldb-1', 'http-1'],
         ['http-1', 'http-2'],
         ['http-1', 'ldb-1'],
         ['ldb-1', 'ldb-2']];
}

adapters.map(function(adapter) {
  qunit('attachments: ' + adapter, {
    setup : function () {
      this.name = generateAdapterUrl(adapter);
    }
  });

  var binAttDoc = {
    _id: "bin_doc",
    _attachments:{
      "foo.txt": {
        content_type:"text/plain",
        data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
      }
    }
  };

  // empty attachment
  var binAttDoc2 = {
    _id: "bin_doc2",
    _attachments:{
      "foo.txt": {
        content_type:"text/plain",
        data: ""
      }
    }
  }

  // json string doc
  var jsonDoc = {
    _id: 'json_doc',
    _attachments: {
      "foo.json": {
        content_type: "text/plain",
        data: btoa('{"Hello":"world"}')
      }
    }
  }

  asyncTest("Test some attachments", function() {
    var db;
    initTestDB(this.name, function(err, _db) {
      db = _db;
      db.put(binAttDoc, function(err, write) {
        ok(!err, 'saved doc with attachment');
        db.get('bin_doc/foo.txt', function(err, res) {
          equal(res, 'This is a base64 encoded text', 'Correct data returned');
          db.put(binAttDoc2, function(err, rev) {
            db.get('bin_doc2/foo.txt', function(err, res, xhr) {
              equal(res, '', 'Correct data returned');
              moreTests(rev.rev);
            });
          });
        });
      });
    });

    function moreTests(rev) {
      var ndoc = 'This is no base64 encoded text';
      db.putAttachment('bin_doc2/foo2.txt', rev, ndoc, "text/plain", function() {
        db.get('bin_doc2/foo2.txt', function(err, res, xhr) {
          ok(res === 'This is no base64 encoded text', 'Correct data returned');
          db.get('bin_doc2', {attachments: true}, function(err, res, xhr) {
            ok(res._attachments, 'Result has attachments field');
            equal(res._attachments['foo2.txt'].data,
                  btoa('This is no base64 encoded text', 'binary'));
            equal(res._attachments['foo.txt'].data, '');
            start();
          });
        });
      });
    };

  });

  asyncTest("Test put attachment on a doc without attachments", function() {
    initTestDB(this.name, function(err, db) {
      db.put({ _id: 'mydoc' }, function(err, resp) {
        db.putAttachment('mydoc/mytext', resp.rev, 'Mytext', 'text/plain', function(err, res) {
          ok(res.ok);
          start();
        })
      });
    });
  });

  asyncTest("Test delete attachment from a doc", function() {
    initTestDB(this.name, function(erro, db) {
      db.put({ _id: 'mydoc' }, function(err, resp) {
        db.putAttachment('mydoc/mytext', resp.rev, 'Mytext', 'text/plain', function(err, res) {
          ok(res.ok);
          var rev = res.rev;
          db.removeAttachment('mydoc/mytext', 0, function(err, res) {
            ok(err);
            db.removeAttachment('mydoc/mytext', rev, function(err, res) {
              ok(res.ok);
              start();
            });
          });
        });
      });
    });
  });

  asyncTest("Test a document with a json string attachment", function() {
    initTestDB(this.name, function(err, db) {
      db.put(jsonDoc, function(err, results) {
        ok(!err, 'saved doc with attachment');
        db.get(results.id, function(err, doc) {
          ok(!err, 'fetched doc')
          ok(doc._attachments, 'doc has attachment')
          db.get(results.id + '/' + 'foo.json', function(err, attachment) {
            equal(attachment, atob(jsonDoc._attachments['foo.json'].data), 'correct data');
            start();
          });
        });
      });
    });
  });

  asyncTest("Test remove doc with attachment", function() {
    initTestDB(this.name, function(err, db) {
      db.put({ _id: 'mydoc' }, function(err, resp) {
        db.putAttachment('mydoc/mytext', resp.rev, 'Mytext', 'text/plain', function(err, res) {
          db.get('mydoc',{attachments:false},function(err,doc){
            db.remove(doc, function(err, resp){
              ok(res.ok);
              start();
            });
          });
        });
      });
    });
  });

  asyncTest("Insert a doc with a / in the _id", function() {
    initTestDB(this.name, function(err, db) {
      ok(!err, 'opened the pouch');
      var doc = {_id: 'doc/attachment', test: true};
      db.put(doc, function(err, info) {
        ok(!err, 'saved doc')
        equal(info.id, 'doc', '_id got truncated');
        db.get('doc', {attachments: true}, function(err, doc2) {
          ok(!err, 'retreived the doc');
          ok(doc2._attachments['attachment'], 'it has the attachment');
          equal(doc2._attachments['attachment'].data, btoa(JSON.stringify(doc)),
             'the attachment matches the original doc');

          db.get('doc/attachment', function(err, response) {
            ok(!err, 'got the attachment');
            equal(response, JSON.stringify(doc),
                  'the attachment is returned as a JSON string');
            var obj = JSON.parse(response);
            equal(obj._id, doc._id, 'id matches');
            equal(obj.test, doc.test, 'test matches');
            start();
          });
        });

      });
    });
  })
});

repl_adapters.map(function(adapters) {

  qunit('replication: ' + adapters[0] + ':' + adapters[1], {
    setup : function () {
      this.name = generateAdapterUrl(adapters[0]);
      this.remote = generateAdapterUrl(adapters[1]);
    }
  });

    asyncTest("Attachments replicate", function() {
        console.info('Starting Test: Attachments replicate');

        var binAttDoc = {
          _id: "bin_doc",
          _attachments:{
            "foo.txt": {
              content_type:"text/plain",
              data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
            }
          }
        };

        var docs1 = [
          binAttDoc,
          {_id: "0", integer: 0},
          {_id: "1", integer: 1},
          {_id: "2", integer: 2},
          {_id: "3", integer: 3}
        ];

        initDBPair(this.name, this.remote, function(db, remote) {
          remote.bulkDocs({docs: docs1}, function(err, info) {
            var replicate = db.replicate.from(remote, function() {
              db.get('bin_doc', {attachments: true}, function(err, doc) {
                equal(binAttDoc._attachments['foo.txt'].data,
                      doc._attachments['foo.txt'].data);
                start();
              });
            });
          });
        });
    });

});
<|endoftext|>


<commit_before>var fs = require('fs');
var http = require('http');
var wait = require('./waitfor');

//------------------------------
// TEST APP - dummy blog server
//------------------------------

function formatPost(post){
  var lines=post.split('\n');
  var result = '
'+lines[0]+'
'
              + '
'+lines[1]+'
';
  for(var i=2;i<lines.length;i++)
      result +='
'+lines[i]+'
';

  return result;
}

function composeTemplate(css, template){
  var composed=template.replace('{{ css }}', css);
  return composed;
}

function applyTemplate(template, content){
  return template.replace('{{ content }}', content);
}

function longAsyncFn(inputData,callback){

  var data = 'here it is: '+inputData;
  var err = Math.random()>0.8? new Error('The ocassional error, Math.random()>0.8') : null;

  //simulate a long operation
  setTimeout( function() {
      callback(err,data)}
      ,2000);
}

//handle request in a fiber
function handler(req,res){
    try{
      res.writeHead(200, {'Content-Type': 'text/html'});
      var start = new Date().getTime();
      //console.log(start);

      //read css, wait.for syntax:
      var css = wait.for(fs.readFile,'style.css','utf8');

      //read post, fancy syntax:
      var content = wait.for(fs.readFile,'blogPost.txt','utf8');

      //compose  template, fancy syntax, as parameter:
      var template = composeTemplate ( css, wait.for(fs.readFile,'blogTemplate.html','utf8') );

      console.log('about to call hardToGetData...');

      //call async, wait.for syntax, in a expression
      var hardToGetData = "\n" + start.toString().substr(-5) +"
" + ( wait.for(longAsyncFn,'some data') );

      console.log('hardToGetData=',hardToGetData);

      var end = new Date().getTime();

      hardToGetData += ', after '+(end-start)+' ms
';
      hardToGetData += end.toString().substr(-5);

      res.end( applyTemplate(template, formatPost ( content + hardToGetData) ) );

    }
    catch(err){
      res.end('ERROR: '+err.message);
    }
  }

//----------------
// Main

var server = http.createServer(
  function(req, res){
    console.log('req!');
    wait.launchFiber(handler,req,res); //handle in a fiber
    // keep node spinning
  }).listen(8000);

console.log('server started on port', 8000);
<commit_msg>v0.6.6 added wait.parallel extensions<commit_after><|endoftext|>


<commit_before>/*eslint-disable */
var babel = require('babel');

module.exports = function(wallaby) {
  return {
    files: [
      'lib/**/*.js',
    ],
    tests: [
      'test/**/*-spec.js',
    ],
    compilers: {
      '**/*.js': wallaby.compilers.babel({babel: babel, stage: 1}),
    },
    env: {
      type: 'node',
    },
  };
};
<commit_msg>Set testFramework in wallaby<commit_after>/*eslint-disable */
var babel = require('babel');

module.exports = function(wallaby) {
  return {
    files: [
      'lib/**/*.js',
    ],
    tests: [
      'test/**/*-spec.js',
    ],
    compilers: {
      '**/*.js': wallaby.compilers.babel({babel: babel, stage: 1}),
    },
    env: {
      type: 'node',
    },
    testFramework: 'mocha',
  };
};
<|endoftext|>


<commit_before>/*-----Function definition-------*/
var activePage = document.URL.split("/").pop(); /*get page name*/
var activePageHighlight=function(){  // add top and bottom border on the active page name
	$("#navbar-"+activePage).addClass("navbar-item");
};
var deactivePageHighlight=function(){  // add top and bottom border on the active page name
	$("#navbar-"+activePage).removeClass("navbar-item");
};
var addScrollOnChart=function(){
	$("#balance-slimscroll").niceScroll();
};

$('#group-dropdown-span').hover(function() {
	$('.navbar .dropdown').find('.dropdown-menu').first().stop(true, true).delay(0).show();
}, function() {
	$('.navbar .dropdown').find('.dropdown-menu').first().stop(true, true).delay(0).hide()
});

/*--------CHARTS--------*/

var getChart=function(){
	var max=Math.max.apply( Math, balances );
	for (var i=0;i<members.length;i++){

            var newRow = document.createElement("tr");
		    newRow.setAttribute("id", i);
            if (balances[i]<0){
            $('#'+i).html('

	');
            	$('#'+i+' #balance-owner').html(members[i] +'
'+ currency +' '+ balances[i]);
            	$('#'+i+' #balance-owner').addClass('neg');
            	$('#'+i+' .pos-bar').width(0+'px');
		        $('#'+i+' .neg-bar').animate(
		            { width: balances[i]/max*(-90)+'%' }, {
		             duration: 800,
		         });
            }else{
            	$('#'+i).html('

	');
            	$('#'+i+' #balance-owner').html(members[i] +'
'+ currency +' '+  balances[i]);
            	$('#'+i+' #balance-owner').addClass('pos');
            	$('#'+i+' .neg-bar').width(0+'px');
		        $('#'+i+' .pos-bar').animate(
		            { width: balances[i]/max*90+'%' }, {
		             duration: 800,
		         });
            };

            if((i % 2 ==0)){
            	$('#'+i+' .positive-balance').css({"background-color":"rgb(250,250,250)"});
		        $('#'+i+' .negative-balance').css({"background-color":"rgb(250,250,250)"});
            }

		$('#balance-table').append(newRow);
	};
	$('#blce-tbl').height($('#balance-table').height()+10);
}

/* HEADER ACTIONS */

$(document).ready(function() {

	/* --- Group members picture toggle --- */
	$("#toggle-button").click(function(){
		$("#second-row-big").slideToggle();
		if($(this).text() === 'hide members'){
			$(this).text('show members');
		}else{
			$(this).text('hide members');
		}
	});

	/* --- Group members show profile in modal --- */
	$("a[data-target=memberProfileModal]").on("click", function(e){
		e.preventDefault();
		$.get('modal/profile/'+$(this).data('id'), function(response){
			$("#memberProfileModal").html(response).modal('show');
		});
	});
});

/* settingsStart, expenseStart, listsStart define the funciton that needs to be
/* called on page load and in response for ajax request

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EXPENSE START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

var expenseStart = function(){

	deactivePageHighlight();
	activePage = document.URL.split("/").pop(); /*get page name*/
	activePageHighlight();

	addScrollOnChart();
	getChart();

	/*--------CHARTS & TIMLINE SIZE--------*/
	if (activePage!=="lists"){
		var members_nb= balances.length;
	};
	var navbarHeight=$("#navbar-row").height();

    // ---> Expense filter
    $("#show-all-button").on("click", function(){
    	$(".expense-row").fadeIn();
    	$("#only-mine-button").removeClass("active");
    	$(this).addClass("active");
    });
    $("#only-mine-button").on("click", function(){
    	$(".expense-row").filter(".nottagged").fadeOut();
    	$("#show-all-button").removeClass("active");
    	$(this).addClass("active");
    });

    $('.edit-button').on('click', function(e){
    	e.preventDefault();
    	console.log('ok1');
    	var expenseId = $(this).data('id');
    	var editBox = $('#expense-edit-'+expenseId);

    	if($('#edit-expense-'+expenseId).css("display") == "none"){
    		console.log('ok3: '+expenseId);
    		console.log('ok3: '+editBox);
    		$('#edit-expense-'+expenseId).removeClass('hidden');
    		$.get('expenses/edit/'+expenseId, function(response){
    			$('#edit-expense-'+expenseId).html(response).hide().fadeIn();
    			editBox.addClass('shown');
    		});
    	} else {
    		console.log('ok2');
    		$('#edit-expense-'+expenseId).slideToggle();
    	}
    })

}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CHAT START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

var chatStart = function(){

	deactivePageHighlight();
	activePage = document.URL.split("/").pop(); /*get page name*/
	activePageHighlight();

	var input = $("#send-box").find('input');

	function refreshMessages() {
		rowCount=$('#chat-table tr').length
		if(activePage=="chat"){
			$.get('messages', function(response){
				$('#message-list').html(response);
			// rappeler les fonctions de mise en forme
			if(rowCount!=$('#chat-table tr').length){
				$("#message-list").animate({ scrollTop: 100000 }, "slow");
			}
		});
		}
	}
	window.setInterval(refreshMessages, 10000);

	$(document).keypress(function(e) {
		if(e.which == 13) {
			var message = $("#send-box").find('input').val();
			$.get('ajax/message/new?new_message='+message, function(response){
				$('#message-list').html(response);
				input.val('');
				input.focus();
				// rappeler les fonctions de mise en forme

				var rowCount=$('#chat-table tr').length

				if(rowCount < 7){
					$('#message-list').slimScroll({
						height: (rowCount+1)*($('#chat-table tr').height()+2),
					});
					$('#chat-container').height(40+(rowCount)*($('#chat-table tr').height()+2)+'px');
					$('#chat-container .slimScrollDiv').height((rowCount)*($('#chat-table tr').height()+2)+'px');
					$('#message-list').height((rowCount)*($('#chat-table tr').height()+2)+'px');

				}

				$("#message-list").animate({ scrollTop: 100000 }, "slow");
			});
		}
	});

	$("#more-expenses").on('click', 'a', function(e){
		e.preventDefault();
		$.get('ajax/expenses', function(response){
			$('#content-container').html(response);
			window.history.pushState("", "", 'expenses');
			// rappeler les fonctions de mise en forme
			addScrollOnChart();
			$('#expense-slimscroll').slimScroll({
				height: Math.min('450',$(window).height()-120)+'px'
			});
			expenseStart();
		});
	});

	$('#message-list').slimScroll({
		height: Math.min('280',$('#message-list').height())+'px',
		start: 'bottom'
	});
}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DASHBOARD START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

var dashboardStart = function(){

	deactivePageHighlight();
	activePage = document.URL.split("/").pop(); /*get page name*/
	activePageHighlight();
	getChart();

	$('#action-bar-first-child').hover(
		function()
		{
			$('.group-edit').addClass('group-edit-hover');
		},
		function(){
			$('.group-edit').removeClass('group-edit-hover');
		}
	);

	// --> hover and click on payback table

	$('#my-settlement .payback-table tr').hover(
		function(){
		$(this).css({"background-color":"rgb(250,250,250)"});
        $(this).find('#payback-cta').animate(
            { left: 0 }, {
             duration: 100,
         });
		},
		function(){
		$(this).css({"background-color":"#fff"});
        $(this).find('#payback-cta').animate(
            { left: -300 }, {
             duration: 100,
         });
		}
	);

	/* --- Prefilled payback form in modal --- */
	$(".payback-table tr").on("click", function(e){
		e.preventDefault();
		var id1 = $(this).data('payer');
		var amount = $(this).data('amount');
		var id2 = $(this).data('paid');
		$.get('payback/new/'+id1+'/'+amount+'/'+id2, function(response){
			$("#prefilledPaybackModal").html(response).modal('show');
		});
	});

	/* --- New payback form in modal --- */
	$("#new-payback").on("click", function(e){
		e.preventDefault();
		$.get('payback/new/0/0/0', function(response){
			$("#prefilledPaybackModal").html(response).modal('show');
		});
	});

    // Height set
    $('#page-body').height(Math.max($('#page-body').height(),$('#my-settlement').height()+$('#settlement').height()+$('header').height()+60));

    $('#remove-member').on('click', function(e){
    	$('#remove-member-box').slideToggle();
    	$('#edit-group-box').slideUp();
    	$('#close-group-box').slideUp();
    });
    $('#edit-group').on('click', function(e){
    	$('#remove-member-box').slideUp();
    	$('#edit-group-box').slideToggle();
    	$('#close-group-box').slideUp();
    });
    $('#close-group').on('click', function(e){
    	$('#remove-member-box').slideUp();
    	$('#edit-group-box').slideUp();
    	$('#close-group-box').slideToggle();
    });
    $('.cancel-action').on('click', function(e){
    	$('#remove-member-box').slideUp();
    	$('#edit-group-box').slideUp();
    	$('#close-group-box').slideUp();
    });

}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LOAD FUNCTION ON START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/* actually call the function when page is loaded for the first time */
$(document).ready(function() {

	jQuery(function($) {
		function fixDiv() {

			var oritop=55;
			if($("#toggle-button").text() === 'hide members'){
				oritop=55;
			}else{
				oritop=0;
			}

			var $cache = $('#navbar-row');
			var $cacheItem = $('#navbar-expenses');
			if ($(window).scrollTop() > oritop && ($(document).height()-100>$(window).height())) {
				$("#navbar-"+activePage).css({'border-top-left-radius':'0px','border-top-right-radius':'0px'});
				$cache.addClass("navbar-scroll");
				$cache.css({'position': 'fixed', 'top': '40px','z-index':'1'});
				$( "#toggle-button" ).hide();
			}
			else{
				$cache.css({'position': 'relative', 'top': 'auto','z-index':'0'});
				$cache.removeClass("navbar-scroll");
				$("#navbar-"+activePage).css({'border-top-left-radius':'4px','border-top-right-radius':'4px'});
				$( "#toggle-button" ).show();
			}
		}
		$(window).scroll(fixDiv);
		fixDiv();
	});

	if (activePage==="expenses"){
		expenseStart();
		getChart();
	}else if(activePage==="chat"){
		chatStart();
	}else if(activePage==="dashboard"){
		dashboardStart();
		getChart();
	}
});

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/* --- AJAX FOR SELECTION MENU --- */
$(document).ready(function() {

	// ---> ajax for going to expenses
	$("#navbar-expenses").on('click', function(e){
		e.preventDefault();
		$('#content-container').fadeOut()
		$.get('ajax/expenses', function(response){
			$('#content-container').html(response).fadeIn();
			window.history.pushState("", "", 'expenses');
			// rappeler les fonctions de mise en forme
			addScrollOnChart();
			$('#expense-slimscroll').slimScroll({
				height: Math.min('450',$(window).height()-120)+'px'
			});
			expenseStart();
			getChart();
		});
	});

	// ---> ajax for going to chat
	$("#navbar-chat").on('click', function(e){
		e.preventDefault();
		$('#content-container').fadeOut()
		$.get('ajax/chat', function(response){
			$('#content-container').html(response).fadeIn();
			window.history.pushState("", "", 'chat');
			// rappeler les fonctions de mise en forme
			// rappel de listapp.js

			deactivePageHighlight();
			activePage = document.URL.split("/").pop(); /*get page name*/
			activePageHighlight();

			chatStart();
		});
	});

	// ---> ajax for going to dashboard
	$("#navbar-dashboard").on('click', function(e){
		e.preventDefault();
		$('#content-container').fadeOut()
		$.get('ajax/dashboard', function(response){
			$('#content-container').html(response).fadeIn();
			window.history.pushState("", "", 'dashboard');
			// rappeler les fonctions de mise en forme
			// rappel de listapp.js

			deactivePageHighlight();
			activePage = document.URL.split("/").pop(); /*get page name*/
			activePageHighlight();

			dashboardStart();
			getChart();
		});
	});
});

<commit_msg>bug fixed on navbar - position fixed<commit_after>/*-----Function definition-------*/
var activePage = document.URL.split("/").pop(); /*get page name*/
var activePageHighlight=function(){  // add top and bottom border on the active page name
	$("#navbar-"+activePage).addClass("navbar-item");
};
var deactivePageHighlight=function(){  // add top and bottom border on the active page name
	$("#navbar-"+activePage).removeClass("navbar-item");
};
var addScrollOnChart=function(){
	$("#balance-slimscroll").niceScroll();
};

$('#group-dropdown-span').hover(function() {
	$('.navbar .dropdown').find('.dropdown-menu').first().stop(true, true).delay(0).show();
}, function() {
	$('.navbar .dropdown').find('.dropdown-menu').first().stop(true, true).delay(0).hide()
});

/*--------CHARTS--------*/

var getChart=function(){
	var max=Math.max.apply( Math, balances );
	for (var i=0;i<members.length;i++){

		var newRow = document.createElement("tr");
		newRow.setAttribute("id", i);
		if (balances[i]<0){
			$('#'+i).html('

	');
			$('#'+i+' #balance-owner').html(members[i] +'
'+ currency +' '+ balances[i]);
			$('#'+i+' #balance-owner').addClass('neg');
			$('#'+i+' .pos-bar').width(0+'px');
			$('#'+i+' .neg-bar').animate(
				{ width: balances[i]/max*(-90)+'%' }, {
					duration: 800,
				});
		}else{
			$('#'+i).html('

	');
			$('#'+i+' #balance-owner').html(members[i] +'
'+ currency +' '+  balances[i]);
			$('#'+i+' #balance-owner').addClass('pos');
			$('#'+i+' .neg-bar').width(0+'px');
			$('#'+i+' .pos-bar').animate(
				{ width: balances[i]/max*90+'%' }, {
					duration: 800,
				});
		};

		if((i % 2 ==0)){
			$('#'+i+' .positive-balance').css({"background-color":"rgb(250,250,250)"});
			$('#'+i+' .negative-balance').css({"background-color":"rgb(250,250,250)"});
		}

		$('#balance-table').append(newRow);
	};
	$('#blce-tbl').height($('#balance-table').height()+10);
}

/* HEADER ACTIONS */

$(document).ready(function() {

	/* --- Group members picture toggle --- */
	$("#toggle-button").click(function(){
		$("#second-row-big").slideToggle();
		if($(this).text() === 'hide members'){
			$(this).text('show members');
		}else{
			$(this).text('hide members');
		}
	});

	/* --- Group members show profile in modal --- */
	$("a[data-target=memberProfileModal]").on("click", function(e){
		e.preventDefault();
		$.get('modal/profile/'+$(this).data('id'), function(response){
			$("#memberProfileModal").html(response).modal('show');
		});
	});
});

/* settingsStart, expenseStart, listsStart define the funciton that needs to be
/* called on page load and in response for ajax request

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EXPENSE START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

var expenseStart = function(){

	deactivePageHighlight();
	activePage = document.URL.split("/").pop(); /*get page name*/
	activePageHighlight();

	addScrollOnChart();
	getChart();

	/*--------CHARTS & TIMLINE SIZE--------*/
	if (activePage!=="lists"){
		var members_nb= balances.length;
	};
	var navbarHeight=$("#navbar-row").height();

    // ---> Expense filter
    $("#show-all-button").on("click", function(){
    	$(".expense-row").fadeIn();
    	$("#only-mine-button").removeClass("active");
    	$(this).addClass("active");
    });
    $("#only-mine-button").on("click", function(){
    	$(".expense-row").filter(".nottagged").fadeOut();
    	$("#show-all-button").removeClass("active");
    	$(this).addClass("active");
    });

    $('.edit-button').on('click', function(e){
    	e.preventDefault();
    	console.log('ok1');
    	var expenseId = $(this).data('id');
    	var editBox = $('#expense-edit-'+expenseId);

    	if($('#edit-expense-'+expenseId).css("display") == "none"){
    		console.log('ok3: '+expenseId);
    		console.log('ok3: '+editBox);
    		$('#edit-expense-'+expenseId).removeClass('hidden');
    		$.get('expenses/edit/'+expenseId, function(response){
    			$('#edit-expense-'+expenseId).html(response).hide().fadeIn();
    			editBox.addClass('shown');
    		});
    	} else {
    		console.log('ok2');
    		$('#edit-expense-'+expenseId).slideToggle();
    	}
    })

}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CHAT START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

var chatStart = function(){

	deactivePageHighlight();
	activePage = document.URL.split("/").pop(); /*get page name*/
	activePageHighlight();

	var input = $("#send-box").find('input');

	function refreshMessages() {
		rowCount=$('#chat-table tr').length
		if(activePage=="chat"){
			$.get('messages', function(response){
				$('#message-list').html(response);
			// rappeler les fonctions de mise en forme
			if(rowCount!=$('#chat-table tr').length){
				$("#message-list").animate({ scrollTop: 100000 }, "slow");
			}
		});
		}
	}
	window.setInterval(refreshMessages, 10000);

	$(document).keypress(function(e) {
		if(e.which == 13) {
			var message = $("#send-box").find('input').val();
			$.get('ajax/message/new?new_message='+message, function(response){
				$('#message-list').html(response);
				input.val('');
				input.focus();
				// rappeler les fonctions de mise en forme

				var rowCount=$('#chat-table tr').length

				if(rowCount < 7){
					$('#message-list').slimScroll({
						height: (rowCount+1)*($('#chat-table tr').height()+2),
					});
					$('#chat-container').height(40+(rowCount)*($('#chat-table tr').height()+2)+'px');
					$('#chat-container .slimScrollDiv').height((rowCount)*($('#chat-table tr').height()+2)+'px');
					$('#message-list').height((rowCount)*($('#chat-table tr').height()+2)+'px');

				}

				$("#message-list").animate({ scrollTop: 100000 }, "slow");
			});
		}
	});

	$("#more-expenses").on('click', 'a', function(e){
		e.preventDefault();
		$.get('ajax/expenses', function(response){
			$('#content-container').html(response);
			window.history.pushState("", "", 'expenses');
			// rappeler les fonctions de mise en forme
			addScrollOnChart();
			$('#expense-slimscroll').slimScroll({
				height: Math.min('450',$(window).height()-120)+'px'
			});
			expenseStart();
		});
	});

	$('#message-list').slimScroll({
		height: Math.min('280',$('#message-list').height())+'px',
		start: 'bottom'
	});
}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DASHBOARD START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

var dashboardStart = function(){

	deactivePageHighlight();
	activePage = document.URL.split("/").pop(); /*get page name*/
	activePageHighlight();
	getChart();

	$('#action-bar-first-child').hover(
		function()
		{
			$('.group-edit').addClass('group-edit-hover');
		},
		function(){
			$('.group-edit').removeClass('group-edit-hover');
		}
		);

	// --> hover and click on payback table

	$('#my-settlement .payback-table tr').hover(
		function(){
			$(this).css({"background-color":"rgb(250,250,250)"});
			$(this).find('#payback-cta').animate(
				{ left: 0 }, {
					duration: 100,
				});
		},
		function(){
			$(this).css({"background-color":"#fff"});
			$(this).find('#payback-cta').animate(
				{ left: -300 }, {
					duration: 100,
				});
		}
		);

	/* --- Prefilled payback form in modal --- */
	$(".payback-table tr").on("click", function(e){
		e.preventDefault();
		var id1 = $(this).data('payer');
		var amount = $(this).data('amount');
		var id2 = $(this).data('paid');
		$.get('payback/new/'+id1+'/'+amount+'/'+id2, function(response){
			$("#prefilledPaybackModal").html(response).modal('show');
		});
	});

	/* --- New payback form in modal --- */
	$("#new-payback").on("click", function(e){
		e.preventDefault();
		$.get('payback/new/0/0/0', function(response){
			$("#prefilledPaybackModal").html(response).modal('show');
		});
	});

    // Height set
    $('#page-body').height(Math.max($('#page-body').height(),$('#my-settlement').height()+$('#settlement').height()+$('header').height()+60));

    $('#remove-member').on('click', function(e){
    	$('#remove-member-box').slideToggle();
    	$('#edit-group-box').slideUp();
    	$('#close-group-box').slideUp();
    });
    $('#edit-group').on('click', function(e){
    	$('#remove-member-box').slideUp();
    	$('#edit-group-box').slideToggle();
    	$('#close-group-box').slideUp();
    });
    $('#close-group').on('click', function(e){
    	$('#remove-member-box').slideUp();
    	$('#edit-group-box').slideUp();
    	$('#close-group-box').slideToggle();
    });
    $('.cancel-action').on('click', function(e){
    	$('#remove-member-box').slideUp();
    	$('#edit-group-box').slideUp();
    	$('#close-group-box').slideUp();
    });

}

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! LOAD FUNCTION ON START !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/* actually call the function when page is loaded for the first time */
$(document).ready(function() {

	jQuery(function($) {
		function fixDiv() {

			if($(window).width()>992){
				var oritop=55;
				if($("#toggle-button").text() === 'hide members'){
					oritop=55;
				}else{
					oritop=0;
				}

				var $cache = $('#navbar-row');
				var $cacheItem = $('#navbar-expenses');
				if ($(window).scrollTop() > oritop && ($(document).height()-100>$(window).height())) {
					$("#navbar-"+activePage).css({'border-top-left-radius':'0px','border-top-right-radius':'0px'});
					$cache.addClass("navbar-scroll");
					$cache.css({'position': 'fixed', 'top': '40px','z-index':'1'});
					$( "#toggle-button" ).hide();
				}
				else{
					$cache.css({'position': 'relative', 'top': 'auto','z-index':'0'});
					$cache.removeClass("navbar-scroll");
					$("#navbar-"+activePage).css({'border-top-left-radius':'4px','border-top-right-radius':'4px'});
					$( "#toggle-button" ).show();
				}
			};

		}
		$(window).scroll(fixDiv);
		fixDiv();
	});

	if (activePage==="expenses"){
		expenseStart();
		getChart();
	}else if(activePage==="chat"){
		chatStart();
	}else if(activePage==="dashboard"){
		dashboardStart();
		getChart();
	}
});

/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/* --- AJAX FOR SELECTION MENU --- */
$(document).ready(function() {

	// ---> ajax for going to expenses
	$("#navbar-expenses").on('click', function(e){
		e.preventDefault();
		$('#content-container').fadeOut()
		$.get('ajax/expenses', function(response){
			$('#content-container').html(response).fadeIn();
			window.history.pushState("", "", 'expenses');
			// rappeler les fonctions de mise en forme
			addScrollOnChart();
			$('#expense-slimscroll').slimScroll({
				height: Math.min('450',$(window).height()-120)+'px'
			});
			expenseStart();
			getChart();
		});
	});

	// ---> ajax for going to chat
	$("#navbar-chat").on('click', function(e){
		e.preventDefault();
		$('#content-container').fadeOut()
		$.get('ajax/chat', function(response){
			$('#content-container').html(response).fadeIn();
			window.history.pushState("", "", 'chat');
			// rappeler les fonctions de mise en forme
			// rappel de listapp.js

			deactivePageHighlight();
			activePage = document.URL.split("/").pop(); /*get page name*/
			activePageHighlight();

			chatStart();
		});
	});

	// ---> ajax for going to dashboard
	$("#navbar-dashboard").on('click', function(e){
		e.preventDefault();
		$('#content-container').fadeOut()
		$.get('ajax/dashboard', function(response){
			$('#content-container').html(response).fadeIn();
			window.history.pushState("", "", 'dashboard');
			// rappeler les fonctions de mise en forme
			// rappel de listapp.js

			deactivePageHighlight();
			activePage = document.URL.split("/").pop(); /*get page name*/
			activePageHighlight();

			dashboardStart();
			getChart();
		});
	});
});

<|endoftext|>


<commit_before>'use strict';

// Node.js fs API implementations, synchronous and static methods

// https://nodejs.org/api/fs.html

const fs = {};

const STATIC_FILE_DATA = {
  '/greeting': new Buffer('hello world'),

  // npm reads its own version from its package.json
  '/node_modules/npm/package.json': new Buffer(JSON.stringify({version: '3.6.0'})),

  // cat ./node_modules/browser-pack/_prelude.js
  // This should match ./prelude2.js (adds require.resolve addition), if the web-based browserify
  // is to match the node-based browserify bundle output. TODO: refactor to avoid duplication
  '/node_modules/browser-pack/_prelude.js': new Buffer(`//based on https://github.com/substack/browser-pack/blob/01d39894f7168983f66200e727cdaadf881cd39d/prelude.js
// modules are defined as an array
// [ module function, map of requireuires ]
//
// map of requireuires is short require name -> numeric require
//
// anything defined in a previous bundle is accessed via the
// orig method which is the requireuire for previous bundles

(function outer (modules, cache, entry) {
    // Save the require from previous bundle to this closure if any
    var previousRequire = typeof require == "function" && require;

    function newRequire(name, jumped){
        if(!cache[name]) {
            if(!modules[name]) {
                // if we cannot find the module within our internal map or
                // cache jump to the current global require ie. the last bundle
                // that was added to the page.
                var currentRequire = typeof require == "function" && require;
                if (!jumped && currentRequire) return currentRequire(name, true);

                // If there are other bundles on this page the require from the
                // previous one is saved to 'previousRequire'. Repeat this as
                // many times as there are bundles until the module is found or
                // we exhaust the require chain.
                if (previousRequire) return previousRequire(name, true);
                var err = new Error('Cannot find module \'' + name + '\'');
                err.code = 'MODULE_NOT_FOUND';
                throw err;
            }
            var m = cache[name] = {exports:{}};
            var R = (x) => {
                var id = modules[name][1][x];
                return newRequire(id ? id : x);
            };
            // https://github.com/deathcap/webnpm/issues/5 Implement require.resolve
            R.resolve = (module) => {
                console.log('require.resolve', module);
                return module;
            };
            modules[name][0].call(m.exports, R
            ,m,m.exports,outer,modules,cache,entry);
        }
        return cache[name].exports;
    }
    for(var i=0;i<entry.length;i++) newRequire(entry[i]);

    // Override the current require with this new one
    return newRequire;
})`),

};

fs.readFileSync = (file, options) => {
  console.log('readFileSync',file,options);

  const data = STATIC_FILE_DATA[file];
  if (data === undefined) {
    const e = new Error(`no such file or directory: ${file}`);
    e.code = 'ENOENT';
    e.errno = -2;
    throw e;
  }

  let encoding = null;
  if (typeof options === 'string') {
    encoding = options;
  } else if (typeof options === 'object') {
    encoding = options.encoding;
  }

  return data.toString(encoding);
};

module.exports = fs;
<commit_msg>Add fs.readdirSync, for npm-client-registry<commit_after>'use strict';

// Node.js fs API implementations, synchronous and static methods

// https://nodejs.org/api/fs.html

const fs = {};

// TODO: write this data to disk too, so it is consistent on the OS filesystem
const STATIC_FILE_DATA = {
  '/greeting': new Buffer('hello world'),

  // npm reads its own version from its package.json
  '/node_modules/npm/package.json': new Buffer(JSON.stringify({version: '3.6.0'})),

  // cat ./node_modules/browser-pack/_prelude.js
  // This should match ./prelude2.js (adds require.resolve addition), if the web-based browserify
  // is to match the node-based browserify bundle output. TODO: refactor to avoid duplication
  '/node_modules/browser-pack/_prelude.js': new Buffer(`//based on https://github.com/substack/browser-pack/blob/01d39894f7168983f66200e727cdaadf881cd39d/prelude.js
// modules are defined as an array
// [ module function, map of requireuires ]
//
// map of requireuires is short require name -> numeric require
//
// anything defined in a previous bundle is accessed via the
// orig method which is the requireuire for previous bundles

(function outer (modules, cache, entry) {
    // Save the require from previous bundle to this closure if any
    var previousRequire = typeof require == "function" && require;

    function newRequire(name, jumped){
        if(!cache[name]) {
            if(!modules[name]) {
                // if we cannot find the module within our internal map or
                // cache jump to the current global require ie. the last bundle
                // that was added to the page.
                var currentRequire = typeof require == "function" && require;
                if (!jumped && currentRequire) return currentRequire(name, true);

                // If there are other bundles on this page the require from the
                // previous one is saved to 'previousRequire'. Repeat this as
                // many times as there are bundles until the module is found or
                // we exhaust the require chain.
                if (previousRequire) return previousRequire(name, true);
                var err = new Error('Cannot find module \'' + name + '\'');
                err.code = 'MODULE_NOT_FOUND';
                throw err;
            }
            var m = cache[name] = {exports:{}};
            var R = (x) => {
                var id = modules[name][1][x];
                return newRequire(id ? id : x);
            };
            // https://github.com/deathcap/webnpm/issues/5 Implement require.resolve
            R.resolve = (module) => {
                console.log('require.resolve', module);
                return module;
            };
            modules[name][0].call(m.exports, R
            ,m,m.exports,outer,modules,cache,entry);
        }
        return cache[name].exports;
    }
    for(var i=0;i<entry.length;i++) newRequire(entry[i]);

    // Override the current require with this new one
    return newRequire;
})`),

};

const STATIC_DIR_DATA = {
  '/node_modules/npm/node_modules/npm-registry-client/lib': [
    // ls node_modules/npm/node_modules/npm-registry-client/lib|perl -pe'chomp;$_="    \"$_\",\n"'
    "access.js",
    "adduser.js",
    "attempt.js",
    "authify.js",
    "deprecate.js",
    "dist-tags",
    "fetch.js",
    "get.js",
    "initialize.js",
    "logout.js",
    "ping.js",
    "publish.js",
    "request.js",
    "star.js",
    "stars.js",
    "tag.js",
    "team.js",
    "unpublish.js",
    "whoami.js",
  ],
};

fs.readFileSync = (file, options) => {
  console.log('readFileSync',file,options);

  const data = STATIC_FILE_DATA[file];
  if (data === undefined) {
    const e = new Error(`no such file or directory: ${file}`);
    e.code = 'ENOENT';
    e.errno = -2;
    throw e;
  }

  let encoding = null;
  if (typeof options === 'string') {
    encoding = options;
  } else if (typeof options === 'object') {
    encoding = options.encoding;
  }

  return data.toString(encoding);
};

fs.readdirSync = (path) => {
  if (path in STATIC_DIR_DATA) {
    return STATIC_DIR_DATA[path];
  }
  const e = new Error(`no such file or directory, readdirSync '${path}'`);
  e.errno = -2;
  e.code = 'ENOENT';
  throw e;
};

module.exports = fs;
<|endoftext|>


<commit_before>/*
* Copyright (C) 2015-2016 by Arena of Titans Contributors.
*
* This file is part of Arena of Titans.
*
* Arena of Titans is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Arena of Titans is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Arena of Titans. If not, see <http://www.gnu.org/licenses/>.
*/

import { inject, NewInstance } from 'aurelia-framework';
import { I18N } from 'aurelia-i18n';
import { History } from './services/history';
import { EventAggregatorSubscriptions } from './services/utils';

@inject(History, I18N, NewInstance.of(EventAggregatorSubscriptions))
export class Game {
    static MAX_NUMBER_PLAYERS = 8;
    static heroes = [
        'daemon',
        'orc',
        'reaper',
        'thief',
    ];

    data = null;
    type = null;
    popupDefered = {
        promise: null,
        resolve: null,
        reject: null,
    };

    constructor(history, i18n, eas) {
        this._i18n = i18n;
        this._eas = eas;

        this._currentPlayerIndex = null;

        this._popupMessageId;
        this._popupMessage = {};
        this._eas.subscribe('i18n:locale:changed', () => this._translatePopupMessage());
        // Init history here: if the page is reloaded on the game page, the history may not be
        // setup until the player click on the player box. This may result in some actions not
        // being displayed. For instance, create a game, refresh, play a card. Without the line
        // below, it will not appear in the player box.
        history.init();
    }

    _translatePopupMessage(options = {}) {
        if (this._popupMessageId) {
            this._popupMessage.message = this._i18n.tr(this._popupMessageId, options);
        }
    }

    configureRouter(config, router) {
        router.baseUrl = 'game';
        config.options.pushState = true;
        config.map([
            {
                route: ['', 'play', ':version', ':version/play'],
                redirect: 'create',
            },
            {
                route: ['create', ':version/create', ':version/create/:id'],
                name: 'create',
                moduleId: './create/create',
                nav: false,
                title: 'Create game',
            },
            {
                route: ':version/play/:id',
                name: 'play',
                moduleId: './play/play',
                nav: false,
                title: 'Play',
            },
        ]);
        config.mapUnknownRoutes(instruction => {
            instruction.moduleId = 'not-found';

            return instruction;
        });
    }

    activate() {
        this._eas.subscribe('aot:api:error', data => {
            this._popupMessageId = data.message;
            this._translatePopupMessage();
            this.popup('error', this._popupMessage).then(() => {
                if (/\/game\/create\/.+/.test(location.pathname)) {
                    location.reload();
                }
            });
        });
        this._api.on(this._api.requestTypes.play, () => {
            if (this._api.game.next_player !== this._currentPlayerIndex) {
                this._currentPlayerIndex = this._api.game.next_player;
                if (this._currentPlayerIndex !== this._api.me.index) {
                    this._popupMessageId = 'game.play.whose_turn_message';
                    this._popupMessage.htmlMessage = true;
                } else {
                    this._popupMessageId = 'game.play.your_turn';
                }
                this._translatePopupMessage({
                    playerName: this._api.game.players.names[this._currentPlayerIndex],
                });

                this.popup('infos', this._popupMessage, {timeout: 5000}).then(() => {
                    this._popupMessageId = undefined;
                    this._popupMessage = {};
                    this._ea.publish('aot:game:counter_start');
                });
            }
        });
    }

    deactivate() {
        this._eas.dispose();
    }

    popup(type, data, {timeout = 0} = {}) {
        this.data = data;
        this.type = type;
        this.popupDefered.promise = new Promise((resolve, reject) => {
            this.popupDefered.resolve = resolve;
            this.popupDefered.reject = reject;
        });

        this.popupDefered.promise.then(() => {
            this.data = null;
            this.type = null;
        }, () => {
            this.data = null;
            this.type = null;
        });

        if (timeout) {
            let closeTimeout = setTimeout(() => {
                this.popupDefered.resolve();
            }, timeout);
            let cancelCloseTimout = () => {
                clearTimeout(closeTimeout);
            };
            this.popupDefered.promise.then(cancelCloseTimout, cancelCloseTimout);
        }

        return this.popupDefered.promise;
    }

    navigateWithRefresh(location) {
        window.location.replace(location);
    }
}
<commit_msg>feat(game): start the counter after all initial popup are closed<commit_after>/*
* Copyright (C) 2015-2016 by Arena of Titans Contributors.
*
* This file is part of Arena of Titans.
*
* Arena of Titans is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Arena of Titans is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Arena of Titans. If not, see <http://www.gnu.org/licenses/>.
*/

import { inject, NewInstance } from 'aurelia-framework';
import { I18N } from 'aurelia-i18n';
import { History } from './services/history';
import { EventAggregatorSubscriptions } from './services/utils';

@inject(History, I18N, NewInstance.of(EventAggregatorSubscriptions))
export class Game {
    static MAX_NUMBER_PLAYERS = 8;
    static heroes = [
        'daemon',
        'orc',
        'reaper',
        'thief',
    ];

    data = null;
    type = null;
    popupDefered = {
        promise: null,
        resolve: null,
        reject: null,
    };

    constructor(history, i18n, eas) {
        this._i18n = i18n;
        this._eas = eas;

        this._currentPlayerIndex = null;

        this._popupMessageId;
        this._popupMessage = {};
        this._eas.subscribe('i18n:locale:changed', () => this._translatePopupMessage());
        // Init history here: if the page is reloaded on the game page, the history may not be
        // setup until the player click on the player box. This may result in some actions not
        // being displayed. For instance, create a game, refresh, play a card. Without the line
        // below, it will not appear in the player box.
        history.init();
    }

    _translatePopupMessage(options = {}) {
        if (this._popupMessageId) {
            this._popupMessage.message = this._i18n.tr(this._popupMessageId, options);
        }
    }

    configureRouter(config, router) {
        router.baseUrl = 'game';
        config.options.pushState = true;
        config.map([
            {
                route: ['', 'play', ':version', ':version/play'],
                redirect: 'create',
            },
            {
                route: ['create', ':version/create', ':version/create/:id'],
                name: 'create',
                moduleId: './create/create',
                nav: false,
                title: 'Create game',
            },
            {
                route: ':version/play/:id',
                name: 'play',
                moduleId: './play/play',
                nav: false,
                title: 'Play',
            },
        ]);
        config.mapUnknownRoutes(instruction => {
            instruction.moduleId = 'not-found';

            return instruction;
        });
    }

    activate() {
        this._eas.subscribe('aot:api:error', data => {
            this._popupMessageId = data.message;
            this._translatePopupMessage();
            this.popup('error', this._popupMessage).then(() => {
                if (/\/game\/create\/.+/.test(location.pathname)) {
                    location.reload();
                }
            });
        });
        this._api.on(this._api.requestTypes.play, () => {
            if (this._api.game.next_player !== this._currentPlayerIndex) {
                this._currentPlayerIndex = this._api.game.next_player;
                if (this._currentPlayerIndex !== this._api.me.index) {
                    this._popupMessageId = 'game.play.whose_turn_message';
                    this._popupMessage.htmlMessage = true;
                } else {
                    this._popupMessageId = 'game.play.your_turn';
                }
                this._translatePopupMessage({
                    playerName: this._api.game.players.names[this._currentPlayerIndex],
                });

                this.popup('infos', this._popupMessage, {timeout: 5000}).then(() => {
                    this._popupMessageId = undefined;
                    this._popupMessage = {};
                });
            }
        });
    }

    deactivate() {
        this._eas.dispose();
    }

    popup(type, data, {timeout = 0} = {}) {
        this.data = data;
        this.type = type;
        this.popupDefered.promise = new Promise((resolve, reject) => {
            this.popupDefered.resolve = resolve;
            this.popupDefered.reject = reject;
        });

        this.popupDefered.promise.then(() => {
            this.data = null;
            this.type = null;
        }, () => {
            this.data = null;
            this.type = null;
        });

        if (timeout) {
            let closeTimeout = setTimeout(() => {
                this.popupDefered.resolve();
            }, timeout);
            let cancelCloseTimout = () => {
                clearTimeout(closeTimeout);
            };
            this.popupDefered.promise.then(cancelCloseTimout, cancelCloseTimout);
        }

        let startCounter = () => {
            this._ea.publish('aot:game:counter_start');
        };
        this.popupDefered.promise.then(startCounter, startCounter);

        return this.popupDefered.promise;
    }

    navigateWithRefresh(location) {
        window.location.replace(location);
    }
}
<|endoftext|>


<commit_before>define(['css!./home.css'/* TODO: add dependencies of this page */], function () {

  var Page = {
    /* TODO: preparation before the page's template is rendered, e.g. class instantiation, access control (return false in function),
     redirect to login page if not logged in, etc. (optional)
     try uncommenting the following line to see the effect of returning false.
     init: function () { return false; },

     // TODO: do things after the page's template has finished rendering (e.g. DOM manipulations)
     may need setTimeout(1) to yield wait for UI to be ready sometimes (optional)
     afterRender: function () {},

     /!* TODO: properly dispose this page to prevent memory leaks and UI leftovers (optional)
     e.g.: release event listeners, dispose knockout manual subscriptions, etc.
     NOTE: all primitives and ko observables defined on the page module object will have their values reset to initial
     values when leaving the page, unless false is returned in dispose function (try returning true/false to see the effect) *!/
     dispose: function () {},

     // TODO: controllers to handle url params/query strings (optional)
     controllers: {}
     */
  };

  /*
   If you don't need any JS logic at all (e.g. simple static text page), just return an empty object {} as the page module.
   If you want to separate the page's data from the behavior handlers (init, afterRender, dispose, controllers),
   feel free to make the data separate module(s) and merge them into the page module as needed.
   */

  return Page;

});
<commit_msg>Add more comment.<commit_after>define(['css!./home.css'/* TODO: add dependencies of this page */], function () {

  var Page = {
    /* TODO: preparation before the page's template is rendered, e.g. class instantiation, access control (return false in function),
     redirect to login page if not logged in, etc. (optional)
     root binging object is passed as the function param.
     try uncommenting the following line to see the effect of returning false.
     init: function (root) { console.log(root); return false; },

     // TODO: do things after the page's template has finished rendering (e.g. DOM manipulations)
     may need setTimeout(1) to yield wait for UI to be ready sometimes (optional)
     afterRender: function () {},

     /!* TODO: properly dispose this page to prevent memory leaks and UI leftovers (optional)
     e.g.: release event listeners, dispose knockout manual subscriptions, etc.
     NOTE: all primitives and ko observables defined on the page module object will have their values reset to initial
     values when leaving the page, unless false is returned in dispose function (try returning true/false to see the effect) *!/
     root binging object is passed as the function param.
     dispose: function (root) {},

     // TODO: controllers to handle url params/query strings (optional)
     controllers: {}
     */
  };

  /*
   If you don't need any JS logic at all (e.g. simple static text page), just return an empty object {} as the page module.
   If you want to separate the page's data from the behavior handlers (init, afterRender, dispose, controllers),
   feel free to make the data separate module(s) and merge them into the page module as needed.
   */

  return Page;

});
<|endoftext|>


<commit_before>const fs = require('fs')
const webpack = require('webpack')
const autoprefixer = require('autoprefixer-core')
const StatsPlugin = require('stats-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = function buildWebpackConfig (options) {
  options = options || {}

  // Environment
  const NODE_ENV = options.NODE_ENV || process.env.NODE_ENV || 'development'

  // Build type
  const SERVER = !!options.SERVER
  const BUILD = !!options.BUILD
  const TEST = !!options.TEST

  // shared values
  const publicPath = BUILD || (BUILD && SERVER)
    ? '/assets/'
    : 'http://localhost:8080/assets/'

  // Output filename
  // server.js, [name].[hash].js, [name].bundle.js
  const filename = SERVER
    ? 'server.js'
    : (BUILD
        ? '[name].[hash].js'
        : '[name].bundle.js'
      )

  // base
  const config = {

    context: __dirname,

    entry: TEST ? {} : {
      bshed: SERVER ? './client/renderer/server.js' : './client/index.js'
    },

    output: TEST ? {} : {
      filename: filename,
      publicPath: publicPath,
      pathinfo: !BUILD || SERVER,
      path: __dirname + (SERVER ? '/build' : '/public/assets'),
      libraryTarget: SERVER ? 'commonjs2' : 'var'
    },

    target: SERVER ? 'node' : 'web',

    devtool: BUILD || SERVER ? 'source-map' : (TEST ? 'inline-source-map' : 'eval'),

    externals: [{
      './stats.json': 'commonjs ./stats.json'
    }],

    module: {
      loaders: [{
        test: /\.(jsx|js)$/,

        loader: (function () {
          // Enable babel-plugin-typecheck in development
          // Enable babel-plugin-rewire in test
          if (TEST) {
            return [
              'babel?optional[]=runtime&plugins[]=rewire&cacheDirectory'
            ].join('!')
          } else if (BUILD || SERVER) {
            return [
              'babel?optional[]=runtime&cacheDirectory'
            ].join('!')
          } else {
            return [
              'react-hot',
              'babel?optional[]=runtime&plugins[]=typecheck&cacheDirectory'
            ].join('!')
          }
        })(),

        // loader: BUILD || SERVER || TEST ? 'babel?optional=runtime&cacheDirectory' : 'react-hot!babel!flowcheck!babel?{ "optional": "runtime", "blacklist": ["flow"], "cacheDirectory": true }',
        exclude: /node_modules/
      }, {
        test: /\.less$/,
        loader: SERVER || TEST ? 'null' : ExtractTextPlugin.extract(
          'style',
          'css?sourceMap!postcss!less?sourceMap'
        )
      }, {
        test: /\.(png|jpg|jpeg|gif|svg|woff|ttf|eot)$/,
        loader: 'file'
      }]
    },

    postcss: function postcss () {
      return [
        autoprefixer({
          browsers: ['last 2 version']
        })
      ]
    },

    resolve: {
      extensions: ['', '.js', '.jsx', '.less']
    },

    plugins: [
      new ExtractTextPlugin('[name].[hash].css', {
        disable: !BUILD || SERVER || TEST
      })
    ],

    devServer: {
      contentBase: './public',
      stats: {
        modules: false,
        cached: false,
        chunk: false
      }
    },

    node: !SERVER ? {} : {
      __filename: true,
      __dirname: true
    }
  }

  // Externals
  // http://jlongster.com/Backend-Apps-with-Webpack--Part-I
  if (SERVER) {
    config.externals.push(
      fs.readdirSync('node_modules')
        .filter(function (x) {
          return ['.bin'].indexOf(x) === -1
        })
        .reduce(function (nodeModules, mod) {
          nodeModules[mod] = 'commonjs ' + mod
          return nodeModules
        }, {
          './stats.json': 'commonjs ./stats.json'
        })
    )
  }

  /**
   * PLUGINS
   */

  // http://jlongster.com/Backend-Apps-with-Webpack--Part-I
  if (SERVER) {
    config.plugins.push(
      new webpack.BannerPlugin('require("source-map-support").install();', {
        entryOnly: true,
        raw: true
      })
    )
  }

  if (!SERVER) {
    if (!TEST) {
      config.plugins.push(
        new StatsPlugin(__dirname + '/build/stats.json')
      )
    }

    if (TEST) {
      config.plugins.push(
        new webpack.IgnorePlugin(/jsdom$/)
      )
    }

    config.plugins.push(
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(NODE_ENV)
      })
    )
  }

  // Minifify and dedupe
  if (BUILD && !SERVER) {
    config.plugins.push(
      new webpack.NoErrorsPlugin(),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin()
    )
  }

  return config
}
<commit_msg>Fix webpack entry scripts<commit_after>const fs = require('fs')
const webpack = require('webpack')
const autoprefixer = require('autoprefixer-core')
const StatsPlugin = require('stats-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = function buildWebpackConfig (options) {
  options = options || {}

  // Environment
  const NODE_ENV = options.NODE_ENV || process.env.NODE_ENV || 'development'

  // Build type
  const SERVER = !!options.SERVER
  const BUILD = !!options.BUILD
  const TEST = !!options.TEST

  // shared values
  const publicPath = BUILD || (BUILD && SERVER)
    ? '/assets/'
    : 'http://localhost:8080/assets/'

  // Output filename
  // server.js, [name].[hash].js, [name].bundle.js
  const filename = SERVER
    ? 'server.js'
    : (BUILD
        ? '[name].[hash].js'
        : '[name].bundle.js'
      )

  // base
  const config = {

    context: __dirname,

    entry: TEST ? {} : {
      bshed: SERVER ? './client/bootstrap/server.js' : './client/bootstrap/client.js'
    },

    output: TEST ? {} : {
      filename: filename,
      publicPath: publicPath,
      pathinfo: !BUILD || SERVER,
      path: __dirname + (SERVER ? '/build' : '/public/assets'),
      libraryTarget: SERVER ? 'commonjs2' : 'var'
    },

    target: SERVER ? 'node' : 'web',

    devtool: BUILD || SERVER ? 'source-map' : (TEST ? 'inline-source-map' : 'eval'),

    externals: [{
      './stats.json': 'commonjs ./stats.json'
    }],

    module: {
      loaders: [{
        test: /\.(jsx|js)$/,

        loader: (function () {
          // Enable babel-plugin-typecheck in development
          // Enable babel-plugin-rewire in test
          if (TEST) {
            return [
              'babel?optional[]=runtime&plugins[]=rewire&cacheDirectory'
            ].join('!')
          } else if (BUILD || SERVER) {
            return [
              'babel?optional[]=runtime&cacheDirectory'
            ].join('!')
          } else {
            return [
              'react-hot',
              'babel?optional[]=runtime&plugins[]=typecheck&cacheDirectory'
            ].join('!')
          }
        })(),

        // loader: BUILD || SERVER || TEST ? 'babel?optional=runtime&cacheDirectory' : 'react-hot!babel!flowcheck!babel?{ "optional": "runtime", "blacklist": ["flow"], "cacheDirectory": true }',
        exclude: /node_modules/
      }, {
        test: /\.less$/,
        loader: SERVER || TEST ? 'null' : ExtractTextPlugin.extract(
          'style',
          'css?sourceMap!postcss!less?sourceMap'
        )
      }, {
        test: /\.(png|jpg|jpeg|gif|svg|woff|ttf|eot)$/,
        loader: 'file'
      }]
    },

    postcss: function postcss () {
      return [
        autoprefixer({
          browsers: ['last 2 version']
        })
      ]
    },

    resolve: {
      extensions: ['', '.js', '.jsx', '.less']
    },

    plugins: [
      new ExtractTextPlugin('[name].[hash].css', {
        disable: !BUILD || SERVER || TEST
      })
    ],

    devServer: {
      contentBase: './public',
      stats: {
        modules: false,
        cached: false,
        chunk: false
      }
    },

    node: !SERVER ? {} : {
      __filename: true,
      __dirname: true
    }
  }

  // Externals
  // http://jlongster.com/Backend-Apps-with-Webpack--Part-I
  if (SERVER) {
    config.externals.push(
      fs.readdirSync('node_modules')
        .filter(function (x) {
          return ['.bin'].indexOf(x) === -1
        })
        .reduce(function (nodeModules, mod) {
          nodeModules[mod] = 'commonjs ' + mod
          return nodeModules
        }, {
          './stats.json': 'commonjs ./stats.json'
        })
    )
  }

  /**
   * PLUGINS
   */

  // http://jlongster.com/Backend-Apps-with-Webpack--Part-I
  if (SERVER) {
    config.plugins.push(
      new webpack.BannerPlugin('require("source-map-support").install();', {
        entryOnly: true,
        raw: true
      })
    )
  }

  if (!SERVER) {
    if (!TEST) {
      config.plugins.push(
        new StatsPlugin(__dirname + '/build/stats.json')
      )
    }

    if (TEST) {
      config.plugins.push(
        new webpack.IgnorePlugin(/jsdom$/)
      )
    }

    config.plugins.push(
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(NODE_ENV)
      })
    )
  }

  // Minifify and dedupe
  if (BUILD && !SERVER) {
    config.plugins.push(
      new webpack.NoErrorsPlugin(),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin()
    )
  }

  return config
}
<|endoftext|>