<commit_before>/**
 * Created by Administrator on 2015/1/12.
 */
var fs = require('fs-extra');
var childprocess = require("child_process");
var pathLib = require("path");
var os = require('os');
var async = require('async');
var xml2js = require('xml2js');
var util = require('util');
var  AdmZip = require('adm-zip');
var urlLib = require('url');
var _ = require('underscore');
var sqlite3 = require('sqlite3').verbose();

var Logger = require('./lib/logger');
var Project = require('./lib/project');
var Channel = require('./lib/channel');

function ChameleonTool(){
    this.projectRoot = '../app/projects/';
    this.configRoot = '../app/chameleon/';
}

ChameleonTool.prototype.init = function(callback){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.serialize(function () {
        dbContext.run("create table if not exists 'project' ('id' integer PRIMARY KEY AUTOINCREMENT NOT NULL, 'name' varchar(50), 'landscape' boolean, 'version' varchar(50), 'path' text, 'signConfig' text, 'config' text)", function(err) {
            if(err) {
                Logger.log('Create table project failed.', err);
                return;
            }
            console.log('Table project created.')
        });
        dbContext.run("create table if not exists 'channel' ('id' integer PRIMARY KEY AUTOINCREMENT NOT NULL, 'projectID' int not null, 'channelName' varchar(50), 'config' text, 'desc' varchar(50), 'signConfig' text, 'sdks' text)", function(err) {
            if(err) {
                Logger.log('Create table channel failed.', err);
                return;
            }
            console.log('Table channel created.');
        });
        dbContext.run("create table if not exists 'history' ( 'version' varchar(50) PRIMARY KEY NOT NULL, 'config' text )", function(err) {
            if(err) {
                Logger.log('Create table history failed.', err);
                return;
            }
            console.log('Table history created.');
            callback(null, "success");
        });
    });
    dbContext.close();
}

ChameleonTool.prototype.getAllProjects = function(callback){
    var projects = [];
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.all("select * from project", function(err, rows){
        if(err) {
            Logger.log("getAllProject() failed.", err);
            callback(err);
            return;
        }
        for(var i=0; i<rows.length; i++){
            var project = new Project();
            var row = rows[i];
            project.id = row.id;
            project.name = row.name;
            project.landscape = row.landscape == 0 ? false : true;
            project.version = row.version;
            project.path = row.path;
            project.signConfig = JSON.parse(row.signConfig);
            project.config = JSON.parse(row.config);
            projects.push(project);
        }
        callback(null, projects);
    });
    dbContext.close();
}

ChameleonTool.prototype.initProject = function(project){
    var instance = new Project();
    return _.extend(instance, project);
}

ChameleonTool.prototype.createEmptyProject = function(){
    return new Project();
}

ChameleonTool.prototype.createProject = function(project, callback){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.run("insert into project (name, landscape, version, path, signConfig, config) values ($name, $landscape, $version, $path, $signConfig, $config)", {
        $name: project.name,
        $landscape: project.landscape,
        $version: project.version,
        $path: project.path,
        $signConfig: JSON.stringify(project.signConfig),
        $config: JSON.stringify(project.config)
    }, function(err){
        if(err){
            callback(err);
            return;
        }
        callback(null, this.lastID);
    });
    dbContext.close();
}

ChameleonTool.prototype.deleteProject = function(id){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.run("delete from project where id=$id", {$id: id});
    dbContext.close();
}

ChameleonTool.prototype.updateProject = function(project, callback){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.run("update project set name=$name, landscape=$landscape, version=$version, path=$path, signConfig=$signConfig, config=$config where id=$id", {
        $id: project.id,
        $name: project.name,
        $landscape: project.landscape,
        $version: project.version,
        $path: project.path,
        $signConfig: JSON.stringify(project.signConfig),
        $config: JSON.stringify(project.config)
    }, function(err){
        if(err){
            callback(err);
            return;
        }
        callback(null, this.changes);
    });
    dbContext.close();
}

ChameleonTool.prototype.getChannelList = function(){
    try {
        var channelList = [];
        var channelInfo = fs.readJsonFileSync(this.configRoot + 'channelinfo/channellist.json');
        for (var p in channelInfo) {
            var channel = new Channel();
            channel.channelName = p;
            channel.desc = channelInfo[p].name;
            channel.checked = false;
            channel.config.pkgsuffix = channelInfo[p].pkgsuffix;
            if(channelInfo[p].splashscreen == 1) channel.config.splash = '1';
            if(channelInfo[p].splashscreen == 2) channel.config.splash = true;
            channel.config.icon = channelInfo[p].icon == 1 ? {} : undefined;
            channel.config.iconFlag = channelInfo[p].icon;
            channel.config.SDKName = channelInfo[p].sdk;

            channelList.push(channel);
        }
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }

    return channelList;
}

ChameleonTool.prototype.getSDKList = function(){
    try {
        var SDKInfo = fs.readJsonFileSync(this.configRoot + 'info.json');
        var SDKList = SDKInfo.channels;
        for (var i = 0; i < SDKList.length; i++) {
            SDKList[i].checked = false;
        }
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }

    return SDKList;
}

ChameleonTool.prototype.dirName = function(){
    return __dirname;
}

ChameleonTool.prototype.createProjectDirectory = function(name){
    var root = this.projectRoot;
    try{
        var path = root + name;
        fs.mkdirpSync(path);
        path += '/cfg';
        fs.mkdirpSync(path);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.createChannelDirectory = function(project, channelName){
    var root = this.projectRoot + project.name + '/cfg/';
    try{
        var path = root + channelName;
        fs.mkdirpSync(path);
        path1 = path + '/res/splash';
        path2 = path + '/res/drawable';
        fs.mkdirpSync(path1);
        fs.mkdirpSync(path2);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.removeProjectDirectory = function(name){
    var root = this.projectRoot;
    try{
        var path = root + name;
        fs.removeSync(path);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.removeChannelDirectory = function(project, channelName){
    var root = this.projectRoot + project.name + '/cfg/';
    try{
        var path = root + channelName;
        fs.removeSync(path);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.generateServerConfig = function(project){
    var result = {};
    var url = urlLib.parse(project.config.payCallbackUrl);
    var host = url.protocol + '//' + url.host;
    var pathName = url.pathname;
    result['_product.json'] = {
        appcb: {
            host: host,
            payCbUrl: pathName
        }
    }
    for(var i=0; i<project.channels; i++){
        var channel = project.channels[i];
        var config = {};
        config.sdks = [];
        for(var j=0; j<channel.sdks.length; j++){
            config.push({
                name: channel.channelName,
                type: 'pay,user',
                cfg: channel.sdks[i].config
            });
        }
        result[channel.channelName + '.json'] = config;
    }
    return result;
}

ChameleonTool.prototype.checkJavaHome = function(){
    if(process.env.JAVA_HOME){
        return true;
    }else{
        return false;
    }
}

ChameleonTool.prototype.command = function(command, args, callback, process){
    var spawn = childprocess.spawn;
    var result = spawn(command, args);
    var message = '';
    console.log(command, args.join(" "));
    result.stdout.on('data', function(data){
        console.log(data.toString());
        message += data;
        if(process){
            process(data.toString());
        }
    });
    result.stderr.on('data', function(data){
        callback(data);
        return ;
    });
    result.on('close', function (code) {
        console.log('child process exited with code ' + code);
        if(code !== 0){
            callback({message : 'failed.'});
            return;
        }
        callback(null, message);
        return ;
    });
}

module.exports = ChameleonTool;
<commit_msg>Change: fix a bug.<commit_after>/**
 * Created by Administrator on 2015/1/12.
 */
var fs = require('fs-extra');
var childprocess = require("child_process");
var pathLib = require("path");
var os = require('os');
var async = require('async');
var xml2js = require('xml2js');
var util = require('util');
var  AdmZip = require('adm-zip');
var urlLib = require('url');
var _ = require('underscore');
var sqlite3 = require('sqlite3').verbose();

var Logger = require('./lib/logger');
var Project = require('./lib/project');
var Channel = require('./lib/channel');

function ChameleonTool(){
    this.projectRoot = '../app/projects/';
    this.configRoot = '../app/chameleon/';
}

ChameleonTool.prototype.init = function(callback){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.serialize(function () {
        dbContext.run("create table if not exists 'project' ('id' integer PRIMARY KEY AUTOINCREMENT NOT NULL, 'name' varchar(50), 'landscape' boolean, 'version' varchar(50), 'path' text, 'signConfig' text, 'config' text)", function(err) {
            if(err) {
                Logger.log('Create table project failed.', err);
                return;
            }
            console.log('Table project created.')
        });
        dbContext.run("create table if not exists 'channel' ('id' integer PRIMARY KEY AUTOINCREMENT NOT NULL, 'projectID' int not null, 'channelName' varchar(50), 'config' text, 'desc' varchar(50), 'signConfig' text, 'sdks' text)", function(err) {
            if(err) {
                Logger.log('Create table channel failed.', err);
                return;
            }
            console.log('Table channel created.');
        });
        dbContext.run("create table if not exists 'history' ( 'version' varchar(50) PRIMARY KEY NOT NULL, 'config' text )", function(err) {
            if(err) {
                Logger.log('Create table history failed.', err);
                return;
            }
            console.log('Table history created.');
            callback(null, "success");
        });
    });
    dbContext.close();
}

ChameleonTool.prototype.getAllProjects = function(callback){
    var projects = [];
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.all("select * from project", function(err, rows){
        if(err) {
            Logger.log("getAllProject() failed.", err);
            callback(err);
            return;
        }
        for(var i=0; i<rows.length; i++){
            var project = new Project();
            var row = rows[i];
            project.id = row.id;
            project.name = row.name;
            project.landscape = row.landscape == 0 ? false : true;
            project.version = row.version;
            project.path = row.path;
            project.signConfig = JSON.parse(row.signConfig);
            project.config = JSON.parse(row.config);
            projects.push(project);
        }
        callback(null, projects);
    });
    dbContext.close();
}

ChameleonTool.prototype.initProject = function(project){
    var instance = new Project();
    return _.extend(instance, project);
}

ChameleonTool.prototype.createEmptyProject = function(){
    return new Project();
}

ChameleonTool.prototype.createProject = function(project, callback){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.run("insert into project (name, landscape, version, path, signConfig, config) values ($name, $landscape, $version, $path, $signConfig, $config)", {
        $name: project.name,
        $landscape: project.landscape,
        $version: project.version,
        $path: project.path,
        $signConfig: JSON.stringify(project.signConfig),
        $config: JSON.stringify(project.config)
    }, function(err){
        if(err){
            callback(err);
            return;
        }
        callback(null, this.lastID);
    });
    dbContext.close();
}

ChameleonTool.prototype.deleteProject = function(id){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.run("delete from project where id=$id", {$id: id});
    dbContext.close();
}

ChameleonTool.prototype.updateProject = function(project, callback){
    var dbContext = new sqlite3.Database('data/chameleon');
    dbContext.run("update project set name=$name, landscape=$landscape, version=$version, path=$path, signConfig=$signConfig, config=$config where id=$id", {
        $id: project.id,
        $name: project.name,
        $landscape: project.landscape,
        $version: project.version,
        $path: project.path,
        $signConfig: JSON.stringify(project.signConfig),
        $config: JSON.stringify(project.config)
    }, function(err){
        if(err){
            callback(err);
            return;
        }
        callback(null, this.changes);
    });
    dbContext.close();
}

ChameleonTool.prototype.getChannelList = function(){
    try {
        var channelList = [];
        var channelInfo = fs.readJsonFileSync(this.configRoot + 'channelinfo/channellist.json');
        for (var p in channelInfo) {
            var channel = new Channel();
            channel.channelName = p;
            channel.desc = channelInfo[p].name;
            channel.checked = false;
            channel.config.pkgsuffix = channelInfo[p].pkgsuffix;
            if(channelInfo[p].splashscreen == 1) channel.config.splash = '1';
            if(channelInfo[p].splashscreen == 2) channel.config.splash = true;
            channel.config.icon = channelInfo[p].icon == 1 ? {} : undefined;
            channel.config.iconFlag = channelInfo[p].icon;
            channel.config.SDKName = channelInfo[p].sdk;

            channelList.push(channel);
        }
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }

    return channelList;
}

ChameleonTool.prototype.getSDKList = function(){
    try {
        var SDKInfo = fs.readJsonFileSync(this.configRoot + 'info.json');
        var SDKList = SDKInfo.channels;
        for (var i = 0; i < SDKList.length; i++) {
            SDKList[i].checked = false;
        }
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }

    return SDKList;
}

ChameleonTool.prototype.dirName = function(){
    return __dirname;
}

ChameleonTool.prototype.createProjectDirectory = function(name){
    var root = this.projectRoot;
    try{
        var path = root + name;
        fs.mkdirpSync(path);
        path += '/cfg';
        fs.mkdirpSync(path);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.createChannelDirectory = function(project, channelName){
    var root = this.projectRoot + project.name + '/cfg/';
    try{
        var path = root + channelName;
        fs.mkdirpSync(path);
        path1 = path + '/res/splash';
        path2 = path + '/res/drawable';
        fs.mkdirpSync(path1);
        fs.mkdirpSync(path2);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.removeProjectDirectory = function(name){
    var root = this.projectRoot;
    try{
        var path = root + name;
        fs.removeSync(path);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.removeChannelDirectory = function(project, channelName){
    var root = this.projectRoot + project.name + '/cfg/';
    try{
        var path = root + channelName;
        fs.removeSync(path);
    }catch (e){
        console.log(e);
        Logger.log(e.message, e);
    }
}

ChameleonTool.prototype.generateServerConfig = function(project){
    var result = {};
    var url = urlLib.parse(project.config.payCallbackUrl);
    var host = url.protocol + '//' + url.host;
    var pathName = url.pathname;
    result['_product.json'] = {
        appcb: {
            host: host,
            payCbUrl: pathName
        }
    }
    for(var i=0; i<project.channels; i++){
        var channel = project.channels[i];
        var config = {};
        config.sdks = [];
        for(var j=0; j<channel.sdks.length; j++){
            config.sdks.push({
                name: channel.channelName,
                type: 'pay,user',
                cfg: channel.sdks[i].config
            });
        }
        result[channel.channelName + '.json'] = config;
    }
    return result;
}

ChameleonTool.prototype.checkJavaHome = function(){
    if(process.env.JAVA_HOME){
        return true;
    }else{
        return false;
    }
}

ChameleonTool.prototype.command = function(command, args, callback, process){
    var spawn = childprocess.spawn;
    var result = spawn(command, args);
    var message = '';
    console.log(command, args.join(" "));
    result.stdout.on('data', function(data){
        console.log(data.toString());
        message += data;
        if(process){
            process(data.toString());
        }
    });
    result.stderr.on('data', function(data){
        callback(data);
        return ;
    });
    result.on('close', function (code) {
        console.log('child process exited with code ' + code);
        if(code !== 0){
            callback({message : 'failed.'});
            return;
        }
        callback(null, message);
        return ;
    });
}

module.exports = ChameleonTool;
<|endoftext|>


<commit_before>(function($) {

  jqUnit.Spec = function(name) {
    this.before = false;
    this.after = false;
    this.assigns = {};
    jqUnit.module(name);
  };

  $.extend(jqUnit.Spec.prototype, {
    // RSpec style test
    it: function(name, callback, nowait) {
      var spec = this;
      if (spec.before) spec.before.apply(spec.assigns);
      jqUnit.test(name, function() { callback.apply(spec); }, nowait);
      if (spec.after) this.after.apply(spec.assigns);
      return spec;
    },

    // Shoulda style test
    should: function(name, callback, nowait) {
      this.it('should ' + name, callback, nowait);
    },

    a: function(key) {
     if (typeof key == 'undefined') {
       return this.assigns;
     } else {
       return this.assigns[key];
     }
    }

  })

  // RSpec style describe
  // takes an arbitrary number of arguments that are contactenated as strings
  // the last argument is the configuration object
  // which can have before: after: callbacks
  function describe() {
    var args = [].splice.call(arguments, 0);
    // configuration function
    var config = (args[args.length - 1].constructor == Object) ? args.pop() : {};
    var spec = new jqUnit.Spec(args.join(' '));
    spec.before = config['before'] || config['setup'];
    spec.after  = config['after'] || config['teardown'];
    return spec;
  }

  $.extend(jqUnit, {
    // aliases for describe
    describe: describe,
    context: describe,

    // asserts that the method is defined (like respond_to?)
    defined: function(object, method) {
      return jqUnit.ok(typeof object[method] == 'function', method + 'is not defined on' + object);
    },

    // asserts that the object is of a certain type
    isType: function(object, type) {
      return jqUnit.ok(object.constructor === type, object.toString() + ' is not of type ' + type + ', is ' + object.constructor);
    },

    match: function(matcher, string) {
      return jqUnit.ok(string.match(matcher));
    }

  });

})(jQuery);
<commit_msg>Fixed should()<commit_after>(function($) {

  jqUnit.Spec = function(name) {
    this.before = false;
    this.after = false;
    this.assigns = {};
    jqUnit.module(name);
  };

  // RSpec style describe
  // takes an arbitrary number of arguments that are contactenated as strings
  // the last argument is the configuration object
  // which can have before: after: callbacks
  function describe() {
    var args = [].splice.call(arguments, 0);
    // configuration function
    var config = (args[args.length - 1].constructor == Object) ? args.pop() : {};
    var spec = new jqUnit.Spec(args.join(' '));
    spec.before = config['before'] || config['setup'];
    spec.after  = config['after'] || config['teardown'];
    return spec;
  }

  $.extend(jqUnit.Spec.prototype, {

    // RSpec style test definition
    it: function(name, callback, nowait) {
      var spec = this;
      if (spec.before) spec.before.apply(spec.assigns);
      jqUnit.test(name, function() { callback.apply(spec); }, nowait);
      if (spec.after) spec.after.apply(spec.assigns);
      return spec;
    },

    // Shoulda style test definition
    should: function(name, callback, nowait) {
      name = 'should ' + name;
      return this.it.apply(this, [name, callback, nowait]);
    },

    a: function(key) {
      if (typeof key == 'undefined') {
        return this.assigns;
      } else {
        return this.assigns[key];
      }
    }

  });

  $.extend(jqUnit, {
    // aliases for describe
    describe: describe,
    context: describe,

    // asserts that the method is defined (like respond_to?)
    defined: function(object, method) {
      return jqUnit.ok(typeof object[method] == 'function', method + 'is not defined on' + object);
    },

    // asserts that the object is of a certain type
    isType: function(object, type) {
      return jqUnit.ok(object.constructor === type, object.toString() + ' is not of type ' + type + ', is ' + object.constructor);
    },

    match: function(matcher, string) {
      return jqUnit.ok(string.match(matcher));
    }

  });

  })(jQuery);
<|endoftext|>


<commit_before>// Package metadata for Meteor.js.

Package.describe({
  name: "zenorocha:clipboard",
  summary: "Modern copy to clipboard. No Flash. Just 2kb.",
  version: "1.5.1",
  git: "https://github.com/zenorocha/clipboard.js"
});

Package.onUse(function(api) {
  api.addFiles("dist/clipboard.min.js", "client");
});
<commit_msg>Bump npm version to match the others.<commit_after>// Package metadata for Meteor.js.

Package.describe({
  name: "zenorocha:clipboard",
  summary: "Modern copy to clipboard. No Flash. Just 2kb.",
  version: "1.5.2",
  git: "https://github.com/zenorocha/clipboard.js"
});

Package.onUse(function(api) {
  api.addFiles("dist/clipboard.min.js", "client");
});
<|endoftext|>


<commit_before>/**
 * tiny
 * https://github.com/iMumuMua/tiny
 */

(function () {

  'use strict';

  /**
   * Tiny constructor
   * @return {Object}
   */
  var Tiny = function () {
    this._kind = 'init';
    this._flowTasks = [];
    this._parallelTasks = [];
    this._isDefaultErrorHandler = true;
    this._errorHandler = function (err) {
      console.log(err.stack || err);
    };
  };

  Tiny.prototype._createCell = function (args) {
    var fn, fnArgs, task, kind;

    var setKind = function (fn) {
      if (isPromise(fn)) {
        kind = 'promise';
      }
      else if (isFunction(fn)) {
        kind = 'function';
      }
      else {
        throw new Error('The first args must be a function or promise.');
      }
    };

    switch (args.length) {
      case 0:
        return;
      case 1:
        kind = 'single';
        task = args[0];
        break;
      case 2:
        fn = args[0];
        setKind(fn);
        task = args[1];
        break;
      default:
        fn = args[0];
        setKind(fn);
        fnArgs = [];
        for (var i = 1, argsLen = args.length; i < argsLen - 1; i++) {
          fnArgs.push(args[i]);
        }
        task = args[args.length - 1];
    }

    return {
      kind: kind,
      fn: fn,
      fnArgs: fnArgs,
      task: task
    };

  };

  Tiny.prototype.go = function () {
    if (this._kind === 'init') {
      this._kind = 'go';
    }
    if (this._kind !== 'init' && this._kind !== 'go') {
      throw new Error('Should not use method go in unflow control');
    }

    var cell = this._createCell(arguments);
    this._flowTasks.push(cell);
    return this;
  };

  Tiny.prototype.parallel = function () {
    if (this._kind === 'init') {
      this._kind = 'parallel';
    }
    if (this._kind !== 'init' && this._kind !== 'parallel') {
      throw new Error('Should not use method parallel in unparallel control');
    }

    var cell = this._createCell(arguments);
    this._parallelTasks.push(cell);
    return this;
  };

  Tiny.prototype._runFlowTask = function (index) {
    try {
      var self = this;
      var task = self._flowTasks[index];
      if (!task) {
        if (self._finishCallback) {
          self._finishCallback();
        }
        return;
      }

      var next = function (data) {
        try {
          var ti = task.task.apply(null, data);
          if (ti instanceof Tiny) {
            if (ti._isDefaultErrorHandler) {
              ti.onError(self._errorHandler);
            }
            ti.run(function () {
              self._runFlowTask(index + 1);
            });
          }
          else if (ti === false) {
            if (self._finishCallback) {
              self._finishCallback();
            }
          }
          else {
            self._runFlowTask(index + 1);
          }
        }
        catch (e) {
          self._errorHandler(e);
        }
      };

      switch (task.kind) {
        case 'single':
          next();
          break;
        case 'promise':
          task.fn.then(function () {
            next(arguments);
          }, self._errorHandler);
          break;
        case 'function':
          var fnCallback = function () {
            try {
              var err = arguments[0];
              if (err) {
                self._errorHandler(err);
              }
              else {
                var data = [];
                for (var i = 1, argumentsLen = arguments.length; i < argumentsLen; i++) {
                  data.push(arguments[i]);
                }
                next(data);
              }
            }
            catch (e) {
              self._errorHandler(e);
            }
          };
          var args = (task.fnArgs || []).concat(fnCallback);
          task.fn.apply(null, args);
          break;
        default:
          self._errorHandler(new Error('Unexpected kind of Tiny cell.'));
      }
    }
    catch (e) {
      self._errorHandler(e);
    }

  };

  Tiny.prototype._runParallelTasks = function () {
    try {
      var self = this;
      var finishCount = 0;
      var tasksLen = self._parallelTasks.length;

      var toFinish = function () {
        try {
          finishCount++;
          if (finishCount === tasksLen) {
            if (self._finishCallback) {
              self._finishCallback();
            }
          }
        }
        catch (e) {
          self._errorHandler(e);
        }
      };

      var runNestedTiny = function (ti) {
        if (ti instanceof Tiny) {
          if (ti._isDefaultErrorHandler) {
            ti.onError(self._errorHandler);
          }
          ti.run(function () {
            toFinish();
          });
        }
        else {
          toFinish();
        }
      };

      self._parallelTasks.forEach(function (task) {
        switch (task.kind) {
          case 'single':
            var ti = task.task();
            runNestedTiny(ti);
            break;
          case 'promise':
            task.fn.then(function () {
              try {
                var ti = task.task.apply(null, arguments);
                runNestedTiny(ti);
              }
              catch (e) {
                self._errorHandler(e);
              }
            }, self._errorHandler);
            break;
          case 'function':
            var fnCallback = function () {
              try {
                var err = arguments[0];
                if (err) {
                  self._errorHandler(err);
                }
                else {
                  var data = [];
                  for (var i = 1, argumentsLen = arguments.length; i < argumentsLen; i++) {
                    data.push(arguments[i]);
                  }

                  var ti = task.task.apply(null, arguments);
                  runNestedTiny(ti);
                }
              }
              catch (e) {
                self._errorHandler(e);
              }
            };
            var args = (task.fnArgs || []).concat(fnCallback);
            task.fn.apply(null, args);
            break;
          default:
            self._errorHandler(new Error('Unexpected kind of Tiny cell.'));
        }
      });
    }
    catch (e) {
      self._errorHandler(e);
    }
  };

  Tiny.prototype.onError = function (errCallback) {
    this._errorHandler = errCallback;
    this._isDefaultErrorHandler = false;
    return this;
  };

  Tiny.prototype.run = function (finishCallback) {
    if (finishCallback) {
      this._finishCallback = finishCallback;
    }
    switch (this._kind) {
      case 'go':
        this._runFlowTask(0);
        break;
      case 'parallel':
        this._runParallelTasks();
        break;
      default:
        throw new Error('Unexpected kind of Tiny');
    }
  };

  /**
   * Helper functions
   */

  /**
   * isPromise - Determine whether an object is a promise.
   *
   * @param  {Object} obj
   * @return {Boolean}     return true if obj is a promise.
   */
  function isPromise(obj) {
    return typeof obj.then === 'function';
  }

  /**
   * isFunction - Determine whether an object is a function.
   *
   * @param  {Object} obj
   * @return {Boolean}     return true if obj is a function.
   */
  function isFunction(obj) {
    return typeof obj === 'function';
  }

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = Tiny;
  }
  else if (typeof define !== 'undefined' && define.amd) {
    define([], function () {
      return Tiny;
    });
  }
  else {
    this.Tiny = Tiny;
  }

}());
<commit_msg>add private method runTask<commit_after>/**
 * tiny
 * https://github.com/iMumuMua/tiny
 */

(function () {

  'use strict';

  /**
   * Tiny constructor
   * @return {Object}
   */
  var Tiny = function () {
    this._kind = 'init';
    this._flowTasks = [];
    this._parallelTasks = [];
    this._isDefaultErrorHandler = true;
    this._errorHandler = function (err) {
      console.log(err.stack || err);
    };
  };

  Tiny.prototype._createCell = function (args) {
    var fn, fnArgs, task, kind;

    var setKind = function (fn) {
      if (isPromise(fn)) {
        kind = 'promise';
      }
      else if (isFunction(fn)) {
        kind = 'function';
      }
      else {
        throw new Error('The first args must be a function or promise.');
      }
    };

    switch (args.length) {
      case 0:
        return;
      case 1:
        kind = 'single';
        task = args[0];
        break;
      case 2:
        fn = args[0];
        setKind(fn);
        task = args[1];
        break;
      default:
        fn = args[0];
        setKind(fn);
        fnArgs = [];
        for (var i = 1, argsLen = args.length; i < argsLen - 1; i++) {
          fnArgs.push(args[i]);
        }
        task = args[args.length - 1];
    }

    return {
      kind: kind,
      fn: fn,
      fnArgs: fnArgs,
      task: task
    };

  };

  Tiny.prototype.go = function () {
    if (this._kind === 'init') {
      this._kind = 'go';
    }
    if (this._kind !== 'init' && this._kind !== 'go') {
      throw new Error('Should not use method go in unflow control');
    }

    var cell = this._createCell(arguments);
    this._flowTasks.push(cell);
    return this;
  };

  Tiny.prototype.parallel = function () {
    if (this._kind === 'init') {
      this._kind = 'parallel';
    }
    if (this._kind !== 'init' && this._kind !== 'parallel') {
      throw new Error('Should not use method parallel in unparallel control');
    }

    var cell = this._createCell(arguments);
    this._parallelTasks.push(cell);
    return this;
  };

  /**
   * Run a task
   * @param {Object} task a cell task
   * @param {Array} args the task fn arguments
   * @param {Function} callback callback when the task has finished, the callback looks like function(err, result) {}, the result is value that the task return.
   */
  Tiny.prototype._runTask = function (task, callback) {
    try {
      var result;
      switch (task.kind) {
        case 'single':
          result = task.task();
          callback(null, result);
          break;
        case 'promise':
          task.fn.then(function () {
            try {
              result = task.task.apply(null, arguments);
              callback(null, result);
            }
            catch (e) {
              callback(e);
            }
          }, callback);
          break;
        case 'function':
          var fnCallback = function () {
            try {
              var err = arguments[0];
              if (err) {
                callback(err);
              }
              else {
                var resData = [];
                for (var i = 1, argumentsLen = arguments.length; i < argumentsLen; i++) {
                  resData.push(arguments[i]);
                }
                result = task.task.apply(null, resData);
                callback(null, result);
              }
            }
            catch (e) {
              callback(e);
            }
          };
          var fnArgs = (task.fnArgs || []).concat(fnCallback);
          task.fn.apply(null, fnArgs);
          break;
        default:
          callback(new Error('Unexpected kind of Tiny cell.'));
      }
    }
    catch (e) {
      callback(e);
    }
  };

  Tiny.prototype._runFlowTask = function (index) {
    try {
      var self = this;
      var task = self._flowTasks[index];
      if (!task) {
        if (self._finishCallback) {
          self._finishCallback();
        }
        return;
      }

      var next = function (err, result) {
        try {
          if (err) {
            self._errorHandler(err);
            return;
          }
          if (result instanceof Tiny) {
            if (result._isDefaultErrorHandler) {
              result.onError(self._errorHandler);
            }
            result.run(function () {
              self._runFlowTask(index + 1);
            });
          }
          else if (result === false) {
            if (self._finishCallback) {
              self._finishCallback();
            }
          }
          else {
            self._runFlowTask(index + 1);
          }
        }
        catch (e) {
          self._errorHandler(e);
        }
      };

      self._runTask(task, next);

    }
    catch (e) {
      self._errorHandler(e);
    }

  };

  Tiny.prototype._runParallelTasks = function () {
    try {
      var self = this;
      var finishCount = 0;
      var tasksLen = self._parallelTasks.length;

      var toFinish = function () {
        try {
          finishCount++;
          if (finishCount === tasksLen) {
            if (self._finishCallback) {
              self._finishCallback();
            }
          }
        }
        catch (e) {
          self._errorHandler(e);
        }
      };

      var runNestedTiny = function (result) {
        if (result instanceof Tiny) {
          if (result._isDefaultErrorHandler) {
            result.onError(self._errorHandler);
          }
          result.run(function () {
            toFinish();
          });
        }
        else {
          toFinish();
        }
      };

      self._parallelTasks.forEach(function (task) {
        self._runTask(task, function (err, result) {
          if (err) {
            self._errorHandler(err);
          }
          else {
            runNestedTiny(result);
          }
        });
      });
    }
    catch (e) {
      self._errorHandler(e);
    }
  };

  Tiny.prototype.onError = function (errCallback) {
    this._errorHandler = errCallback;
    this._isDefaultErrorHandler = false;
    return this;
  };

  Tiny.prototype.run = function (finishCallback) {
    if (finishCallback) {
      this._finishCallback = finishCallback;
    }
    switch (this._kind) {
      case 'go':
        this._runFlowTask(0);
        break;
      case 'parallel':
        this._runParallelTasks();
        break;
      default:
        throw new Error('Unexpected kind of Tiny');
    }
  };

  /**
   * Helper functions
   */

  /**
   * isPromise - Determine whether an object is a promise.
   *
   * @param  {Object} obj
   * @return {Boolean}     return true if obj is a promise.
   */
  function isPromise(obj) {
    return typeof obj.then === 'function';
  }

  /**
   * isFunction - Determine whether an object is a function.
   *
   * @param  {Object} obj
   * @return {Boolean}     return true if obj is a function.
   */
  function isFunction(obj) {
    return typeof obj === 'function';
  }

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = Tiny;
  }
  else if (typeof define !== 'undefined' && define.amd) {
    define([], function () {
      return Tiny;
    });
  }
  else {
    this.Tiny = Tiny;
  }

}());
<|endoftext|>


<commit_before>Template.latestActivitiesByTypeTable.helpers({
  tableData: function () {
    // Get resident activity details from template
    var residentActivities = instance.residentDetails.get();

    if (residentActivities) {
      // Render resident details to the table
      // Columns resident name, timeAgo
      return residentActivities;
    } else {
      // return an empty array to simply render the table
      return [];
    }
  }
});

Template.latestActivitiesByTypeTable.created = function () {
  // Set instance variable for consistency
  instance = Template.instance();

  instance.residentDetails = new ReactiveVar();

  instance.autorun(function () {
    // Keep track of the selected activity type
    var residentActivities = instance.parent().latestResidentsActivityByType.get();

    var residentIds = _.map(residentActivities, function (residentActivity) {
      // Get the resident ID
      return residentActivity._id;
    });

    // Get residents from database
    instance.subscribe('selectResidents', residentIds);

    var residentNamesWithActivityDates = _.map(
      residentActivities,
      function (residentActivity) {
        // Get resident ID from activity
        var residentId = residentActivity._id;

        // Add activity date in 'time ago' format
        var activityTimeAgo = new moment(residentActivity.latestActivity).fromNow();

        // Get resident details from collection
        var resident = Residents.findOne(residentId);

        // Create an object with details
        var residentDetails = {
          firstName: resident.firstName,
          lastName: resident.lastName,
          lastActive: activityTimeAgo
        };

        return residentDetails;
    });

    instance.residentDetails.set(residentNamesWithActivityDates);
  });
};
<commit_msg>Get residents latest activities. Cleanup.<commit_after>Template.latestActivitiesByTypeTable.helpers({
  residentsLatestActivities: function () {
    // Get resident activity details from template
    var residentsLatestActivities = instance.residentLatestActivityDetails.get();

    return residentsLatestActivities;
  }
});

Template.latestActivitiesByTypeTable.created = function () {
  // Set instance variable for consistency
  instance = Template.instance();

  instance.residentLatestActivityDetails = new ReactiveVar();

  instance.autorun(function () {
    // Keep track of the selected activity type
    var activityTypeId = instance.parent().activityTypeSelection.get();

    if (activityTypeId) {
      Meteor.call(
        'getResidentsNameHomeAndLastActivityByType',
        activityTypeId,
        function (error, residentLatestActivity) {
          if (error) {
            console.log(error);
          } else {
            instance.residentLatestActivityDetails.set(residentLatestActivity);
          }
        });
      }
  });
};
<|endoftext|>


<commit_before>// Copyright 2002-2015, University of Colorado Boulder

/**
 * A carousel UI component.
 * A set of N items is divided into M 'pages', based on how many items are visible in the carousel.
 * Pressing the next and previous buttons moves through the pages.
 * Movement through the pages is animated, so that items appear to scroll by.
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var CarouselButton = require( 'SUN/buttons/CarouselButton' );
  var HSeparator = require( 'SUN/HSeparator' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PageControl = require( 'SUN/PageControl' );
  var Property = require( 'AXON/Property' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var Shape = require( 'KITE/Shape' );
  var Util = require( 'DOT/Util' );
  var VSeparator = require( 'SUN/VSeparator' );

  // constants
  var DEFAULT_OPTIONS = {

    // container
    orientation: 'horizontal', // {string} 'horizontal'|'vertical'
    fill: 'white', // {Color|string|null} background color of the carousel
    stroke: 'black', // {Color|string|null} color used to stroke the border of the carousel
    lineWidth: 1, // {number} width of the border around the carousel
    cornerRadius: 4, // {number} radius applied to the carousel and next/previous buttons
    defaultPageNumber: 0, // {number} page that is initially visible

    // items
    itemsPerPage: 4, // {number} number of items per page, or how many items are visible at a time in the carousel
    spacing: 10, // {number} spacing between items, between items and optional separators, and between items and buttons
    margin: 10, // {number} margin between items and the edges of the carousel

    // next/previous buttons
    buttonColor: 'rgba( 200, 200, 200, 0.5 )', // {Color|string} base color for the buttons
    buttonStroke: undefined, // {Color|string|null|undefined} stroke around the buttons (null is no stroke, undefined derives color from buttonColor)
    buttonLineWidth: 1, // {number} lineWidth of borders on buttons
    hideDisabledButtons: false, // {boolean} whether to hide buttons when they are disabled

    // item separators
    separatorsVisible: false, // {boolean} whether to put separators between items
    separatorColor: 'rgb( 180, 180, 180 )', // {Color|string} color for separators
    separatorLineWidth: 0.5, // {number} lineWidth for separators

    // iOS-style page control
    pageControlVisible: false, // {boolean} whether to show an iOS-style page control
    pageControlLocation: 'bottom', // {string} where to place the page control, 'top'|'bottom'|'left'|'right'
    pageControlSpacing: 6, // {number} spacing between page control and carousel background
    dotRadius: 3, // {number} radius of the dots in the page control
    dotSpacing: 10, // {number} space between dots
    pageVisibleColor: 'black', // {Color|string} dot color for the page that is visible
    pageNotVisibleColor: 'rgb( 200, 200, 200 )' // {Color|string} dot color for pages that are not visible
  };

  /**
   * @param {Node[]} items - items in the carousel
   * @param {Object} [options]
   * @constructor
   */
  function Carousel( items, options ) {

    // Make a copy of default options, so we can modify it
    var defaultOptions = _.clone( DEFAULT_OPTIONS );

    // If options doesn't specify a location for page control, set a valid default
    if ( options.orientation && !options.pageControlLocation ) {
      defaultOptions.pageControlLocation = ( options.orientation === 'horizontal' ) ? 'bottom' : 'left';
    }

    // Override defaults with specified options
    options = _.extend( defaultOptions, options );

    // Validate options
    assert && assert( _.contains( [ 'horizontal', 'vertical' ], options.orientation ), 'invalid orientation=' + options.orientation );
    assert && assert( _.contains( [ 'bottom', 'top', 'left', 'right' ], options.pageControlLocation ), 'invalid pageControlLocation=' + options.pageControlLocation );

    // To improve readability
    var isHorizontal = ( options.orientation === 'horizontal' );

    // Dimensions of largest item
    var maxItemWidth = _.max( items, function( item ) { return item.width; } ).width;
    var maxItemHeight = _.max( items, function( item ) { return item.height; } ).height;

    // This quantity is used make some other computations independent of orientation.
    var maxItemLength = isHorizontal ? maxItemWidth : maxItemHeight;

    // Options common to both buttons
    var buttonOptions = {
      xMargin: 5,
      yMargin: 5,
      baseColor: options.buttonColor,
      disabledBaseColor: options.fill, // same as carousel background
      stroke: options.buttonStroke,
      lineWidth: options.buttonLineWidth,
      cornerRadius: options.cornerRadius, // same as carousel background
      minWidth: isHorizontal ? 0 : maxItemWidth + ( 2 * options.margin ), // fill the width of a vertical carousel
      minHeight: isHorizontal ? maxItemHeight + ( 2 * options.margin ) : 0 // fill the height of a horizontal carousel
    };

    // Next/previous buttons
    var nextButton = new CarouselButton( _.extend( {
      arrowDirection: isHorizontal ? 'right' : 'down'
    }, buttonOptions ) );
    var previousButton = new CarouselButton( _.extend( {
      arrowDirection: isHorizontal ? 'left' : 'up'
    }, buttonOptions ) );

    // Computations related to layout of items
    var numberOfSeparators = ( options.separatorsVisible ) ? ( items.length - 1 ) : 0;
    var scrollingLength = ( items.length * ( maxItemLength + options.spacing ) + ( numberOfSeparators * options.spacing) + options.spacing );
    var scrollingWidth = isHorizontal ? scrollingLength : ( maxItemWidth + 2 * options.margin );
    var scrollingHeight = isHorizontal ? ( maxItemHeight + 2 * options.margin ) : scrollingLength;
    var itemCenter = options.spacing + ( maxItemLength / 2 );

    // Options common to all separators
    var separatorOptions = {
      stroke: options.separatorColor,
      lineWidth: options.separatorLineWidth
    };

    // All items, arranged in the proper orientation, with margins and spacing.
    // Horizontal carousel arrange items left-to-right, vertical is top-to-bottom.
    // Translation of this node will be animated to give the effect of scrolling through the items.
    var scrollingNode = new Rectangle( 0, 0, scrollingWidth, scrollingHeight );
    items.forEach( function( item, index ) {

      // add the item
      if ( isHorizontal ) {
        item.centerX = itemCenter;
        item.centerY = options.margin + ( maxItemHeight / 2 );
      }
      else {
        item.centerX = options.margin + ( maxItemWidth / 2 );
        item.centerY = itemCenter;
      }
      scrollingNode.addChild( item );

      // center for the next item
      itemCenter += ( options.spacing + maxItemLength );

      // add optional separator
      if ( options.separatorsVisible ) {
        var separator;
        if ( isHorizontal ) {

          // vertical separator, to the left of the item
          separator = new VSeparator( scrollingHeight, _.extend( {
            centerX: item.centerX + ( maxItemLength / 2 ) + options.spacing,
            centerY: item.centerY
          }, separatorOptions ) );
          scrollingNode.addChild( separator );

          // center for the next item
          itemCenter = separator.centerX + options.spacing + ( maxItemLength / 2 );
        }
        else {

          // horizontal separator, below the item
          separator = new HSeparator( scrollingWidth, _.extend( {
            centerX: item.centerX,
            centerY: item.centerY + ( maxItemLength / 2 ) + options.spacing
          }, separatorOptions ) );
          scrollingNode.addChild( separator );

          // center for the next item
          itemCenter = separator.centerY + options.spacing + ( maxItemLength / 2 );
        }
      }
    } );

    // How much to translate scrollingNode each time a next/previous button is pressed
    var scrollingDelta = options.itemsPerPage * ( maxItemLength + options.spacing );
    if ( options.separatorsVisible ) {
      scrollingDelta += ( options.itemsPerPage * options.spacing );
    }

    // Clipping window, to show one page at a time.
    // Clips at the midpoint of spacing between items so that you don't see any stray bits of the items that shouldn't be visible.
    var windowLength = ( scrollingDelta + options.spacing );
    if ( options.separatorsVisible ) {
      windowLength -= options.spacing;
    }
    var windowWidth = isHorizontal ? windowLength : scrollingNode.width;
    var windowHeight = isHorizontal ? scrollingNode.height : windowLength;
    var clipArea = isHorizontal ?
                   Shape.rectangle( options.spacing / 2, 0, windowWidth - options.spacing, windowHeight ) :
                   Shape.rectangle( 0, options.spacing / 2, windowWidth, windowHeight - options.spacing );
    var windowNode = new Node( {
      children: [ scrollingNode ],
      clipArea: clipArea
    } );

    // Background - displays the carousel's fill color
    var backgroundWidth = isHorizontal ? ( windowWidth + nextButton.width + previousButton.width ) : windowWidth;
    var backgroundHeight = isHorizontal ? windowHeight : ( windowHeight + nextButton.height + previousButton.height );
    var backgroundNode = new Rectangle( 0, 0, backgroundWidth, backgroundHeight, options.cornerRadius, options.cornerRadius, {
      fill: options.fill
    } );

    // Foreground - displays the carousel's outline, created as a separate node so that it can be placed on top of everything, for a clean look.
    var foregroundNode = new Rectangle( 0, 0, backgroundWidth, backgroundHeight, options.cornerRadius, options.cornerRadius, {
      stroke: options.stroke
    } );

    // Layout
    if ( isHorizontal ) {
      nextButton.centerY = previousButton.centerY = windowNode.centerY = backgroundNode.centerY;
      nextButton.right = backgroundNode.right;
      previousButton.left = backgroundNode.left;
      windowNode.centerX = backgroundNode.centerX;
    }
    else {
      nextButton.centerX = previousButton.centerX = windowNode.centerX = backgroundNode.centerX;
      nextButton.bottom = backgroundNode.bottom;
      previousButton.top = backgroundNode.top;
      windowNode.centerY = backgroundNode.centerY;
    }

    // Number of pages
    var numberOfPages = items.length / options.itemsPerPage;
    if ( !Util.isInteger( numberOfPages ) ) {
      numberOfPages = Math.floor( numberOfPages + 1 );
    }

    // Number of the page that is visible in the carousel.
    var pageNumberProperty = new Property( options.defaultPageNumber );

    // iOS-style page control
    var pageControl = null;
    if ( options.pageControlVisible ) {

      pageControl = new PageControl( numberOfPages, pageNumberProperty, {
        orientation: options.orientation,
        pageVisibleColor: options.pageVisibleColor,
        pageNotVisibleColor: options.pageNotVisibleColor,
        dotRadius: options.dotRadius,
        dotSpacing: options.dotSpacing
      } );

      // Layout
      if ( isHorizontal ) {
        pageControl.centerX = backgroundNode.centerX;
        if ( options.pageControlLocation === 'top' ) {
          pageControl.bottom = backgroundNode.top - options.pageControlSpacing;
        }
        else if ( options.pageControlLocation === 'bottom' ) {
          pageControl.top = backgroundNode.bottom + options.pageControlSpacing;
        }
        else {
          throw new Error( 'incompatible pageControlLocation=' + options.pageControlLocation + ' for orientation=' + options.orientation );
        }
      }
      else {
        pageControl.centerY = backgroundNode.centerY;
        if ( options.pageControlLocation === 'left' ) {
          pageControl.right = backgroundNode.left - options.pageControlSpacing;
        }
        else if ( options.pageControlLocation === 'right' ) {
          pageControl.left = backgroundNode.right + options.pageControlSpacing;
        }
        else {
          throw new Error( 'incompatible pageControlLocation=' + options.pageControlLocation + ' for orientation=' + options.orientation );
        }
      }
    }

    // Scroll when the buttons are pressed
    var scrollTween;
    pageNumberProperty.link( function( pageNumber ) {

      assert && assert( pageNumber >= 0 && pageNumber <= numberOfPages - 1, 'pageNumber out of range: ' + pageNumber );

      // stop any animation that's in progress
      scrollTween && scrollTween.stop();

      // button state
      nextButton.enabled = pageNumber < ( numberOfPages - 1 );
      previousButton.enabled = pageNumber > 0;
      if ( options.hideDisabledButtons ) {
        nextButton.visible = nextButton.enabled;
        previousButton.visible = previousButton.enabled;
      }

      //TODO replace calls to Tween with a wrapper
      // Set up the animation to scroll the items in the carousel.
      var parameters;
      var animationDuration = 400; // ms
      var easing = TWEEN.Easing.Cubic.InOut;
      if ( isHorizontal ) {
        parameters = { left: scrollingNode.left };
        scrollTween = new TWEEN.Tween( parameters )
          .easing( easing )
          .to( { left: -pageNumber * scrollingDelta }, animationDuration )
          .onUpdate( function() {
            scrollingNode.left = parameters.left;
          } )
          .start();
      }
      else {
        parameters = { top: scrollingNode.top };
        scrollTween = new TWEEN.Tween( parameters )
          .easing( easing )
          .to( { top: -pageNumber * scrollingDelta }, animationDuration )
          .onUpdate( function() {
            scrollingNode.top = parameters.top;
          } )
          .start();
      }
    } );

    // Buttons modify the page number
    nextButton.addListener( function() {
      pageNumberProperty.set( pageNumberProperty.get() + 1 );
    } );
    previousButton.addListener( function() {
      pageNumberProperty.set( pageNumberProperty.get() - 1 );
    } );

    // public fields
    this.numberOfPages = numberOfPages; // @public (read-only) {number} number of pages in the carousel
    this.pageNumberProperty = pageNumberProperty; // @public {Property<number>} page number that is currently visible

    // @private
    this.disposeCarousel = function() {
      if ( pageControl ) {
        pageControl.dispose();
      }
    };

    options.children = [ backgroundNode, windowNode, nextButton, previousButton, foregroundNode ];
    if ( pageControl ) {
      options.children.push( pageControl );
    }

    Node.call( this, options );
  }

  return inherit( Node, Carousel, {

    dispose: function() { this.disposeCarousel(); }
  }, {

    // @static @public (read-only)
    DEFAULT_OPTIONS: DEFAULT_OPTIONS
  } );
} );
<commit_msg>#166 add reset<commit_after>// Copyright 2002-2015, University of Colorado Boulder

/**
 * A carousel UI component.
 * A set of N items is divided into M 'pages', based on how many items are visible in the carousel.
 * Pressing the next and previous buttons moves through the pages.
 * Movement through the pages is animated, so that items appear to scroll by.
 *
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var CarouselButton = require( 'SUN/buttons/CarouselButton' );
  var HSeparator = require( 'SUN/HSeparator' );
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PageControl = require( 'SUN/PageControl' );
  var Property = require( 'AXON/Property' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var Shape = require( 'KITE/Shape' );
  var Util = require( 'DOT/Util' );
  var VSeparator = require( 'SUN/VSeparator' );

  // constants
  var DEFAULT_OPTIONS = {

    // container
    orientation: 'horizontal', // {string} 'horizontal'|'vertical'
    fill: 'white', // {Color|string|null} background color of the carousel
    stroke: 'black', // {Color|string|null} color used to stroke the border of the carousel
    lineWidth: 1, // {number} width of the border around the carousel
    cornerRadius: 4, // {number} radius applied to the carousel and next/previous buttons
    defaultPageNumber: 0, // {number} page that is initially visible

    // items
    itemsPerPage: 4, // {number} number of items per page, or how many items are visible at a time in the carousel
    spacing: 10, // {number} spacing between items, between items and optional separators, and between items and buttons
    margin: 10, // {number} margin between items and the edges of the carousel

    // next/previous buttons
    buttonColor: 'rgba( 200, 200, 200, 0.5 )', // {Color|string} base color for the buttons
    buttonStroke: undefined, // {Color|string|null|undefined} stroke around the buttons (null is no stroke, undefined derives color from buttonColor)
    buttonLineWidth: 1, // {number} lineWidth of borders on buttons
    hideDisabledButtons: false, // {boolean} whether to hide buttons when they are disabled

    // item separators
    separatorsVisible: false, // {boolean} whether to put separators between items
    separatorColor: 'rgb( 180, 180, 180 )', // {Color|string} color for separators
    separatorLineWidth: 0.5, // {number} lineWidth for separators

    // iOS-style page control
    pageControlVisible: false, // {boolean} whether to show an iOS-style page control
    pageControlLocation: 'bottom', // {string} where to place the page control, 'top'|'bottom'|'left'|'right'
    pageControlSpacing: 6, // {number} spacing between page control and carousel background
    dotRadius: 3, // {number} radius of the dots in the page control
    dotSpacing: 10, // {number} space between dots
    pageVisibleColor: 'black', // {Color|string} dot color for the page that is visible
    pageNotVisibleColor: 'rgb( 200, 200, 200 )' // {Color|string} dot color for pages that are not visible
  };

  /**
   * @param {Node[]} items - items in the carousel
   * @param {Object} [options]
   * @constructor
   */
  function Carousel( items, options ) {

    // Make a copy of default options, so we can modify it
    var defaultOptions = _.clone( DEFAULT_OPTIONS );

    // If options doesn't specify a location for page control, set a valid default
    if ( options.orientation && !options.pageControlLocation ) {
      defaultOptions.pageControlLocation = ( options.orientation === 'horizontal' ) ? 'bottom' : 'left';
    }

    // Override defaults with specified options
    options = _.extend( defaultOptions, options );

    // Validate options
    assert && assert( _.contains( [ 'horizontal', 'vertical' ], options.orientation ), 'invalid orientation=' + options.orientation );
    assert && assert( _.contains( [ 'bottom', 'top', 'left', 'right' ], options.pageControlLocation ), 'invalid pageControlLocation=' + options.pageControlLocation );

    // To improve readability
    var isHorizontal = ( options.orientation === 'horizontal' );

    // Dimensions of largest item
    var maxItemWidth = _.max( items, function( item ) { return item.width; } ).width;
    var maxItemHeight = _.max( items, function( item ) { return item.height; } ).height;

    // This quantity is used make some other computations independent of orientation.
    var maxItemLength = isHorizontal ? maxItemWidth : maxItemHeight;

    // Options common to both buttons
    var buttonOptions = {
      xMargin: 5,
      yMargin: 5,
      baseColor: options.buttonColor,
      disabledBaseColor: options.fill, // same as carousel background
      stroke: options.buttonStroke,
      lineWidth: options.buttonLineWidth,
      cornerRadius: options.cornerRadius, // same as carousel background
      minWidth: isHorizontal ? 0 : maxItemWidth + ( 2 * options.margin ), // fill the width of a vertical carousel
      minHeight: isHorizontal ? maxItemHeight + ( 2 * options.margin ) : 0 // fill the height of a horizontal carousel
    };

    // Next/previous buttons
    var nextButton = new CarouselButton( _.extend( {
      arrowDirection: isHorizontal ? 'right' : 'down'
    }, buttonOptions ) );
    var previousButton = new CarouselButton( _.extend( {
      arrowDirection: isHorizontal ? 'left' : 'up'
    }, buttonOptions ) );

    // Computations related to layout of items
    var numberOfSeparators = ( options.separatorsVisible ) ? ( items.length - 1 ) : 0;
    var scrollingLength = ( items.length * ( maxItemLength + options.spacing ) + ( numberOfSeparators * options.spacing) + options.spacing );
    var scrollingWidth = isHorizontal ? scrollingLength : ( maxItemWidth + 2 * options.margin );
    var scrollingHeight = isHorizontal ? ( maxItemHeight + 2 * options.margin ) : scrollingLength;
    var itemCenter = options.spacing + ( maxItemLength / 2 );

    // Options common to all separators
    var separatorOptions = {
      stroke: options.separatorColor,
      lineWidth: options.separatorLineWidth
    };

    // All items, arranged in the proper orientation, with margins and spacing.
    // Horizontal carousel arrange items left-to-right, vertical is top-to-bottom.
    // Translation of this node will be animated to give the effect of scrolling through the items.
    var scrollingNode = new Rectangle( 0, 0, scrollingWidth, scrollingHeight );
    items.forEach( function( item, index ) {

      // add the item
      if ( isHorizontal ) {
        item.centerX = itemCenter;
        item.centerY = options.margin + ( maxItemHeight / 2 );
      }
      else {
        item.centerX = options.margin + ( maxItemWidth / 2 );
        item.centerY = itemCenter;
      }
      scrollingNode.addChild( item );

      // center for the next item
      itemCenter += ( options.spacing + maxItemLength );

      // add optional separator
      if ( options.separatorsVisible ) {
        var separator;
        if ( isHorizontal ) {

          // vertical separator, to the left of the item
          separator = new VSeparator( scrollingHeight, _.extend( {
            centerX: item.centerX + ( maxItemLength / 2 ) + options.spacing,
            centerY: item.centerY
          }, separatorOptions ) );
          scrollingNode.addChild( separator );

          // center for the next item
          itemCenter = separator.centerX + options.spacing + ( maxItemLength / 2 );
        }
        else {

          // horizontal separator, below the item
          separator = new HSeparator( scrollingWidth, _.extend( {
            centerX: item.centerX,
            centerY: item.centerY + ( maxItemLength / 2 ) + options.spacing
          }, separatorOptions ) );
          scrollingNode.addChild( separator );

          // center for the next item
          itemCenter = separator.centerY + options.spacing + ( maxItemLength / 2 );
        }
      }
    } );

    // How much to translate scrollingNode each time a next/previous button is pressed
    var scrollingDelta = options.itemsPerPage * ( maxItemLength + options.spacing );
    if ( options.separatorsVisible ) {
      scrollingDelta += ( options.itemsPerPage * options.spacing );
    }

    // Clipping window, to show one page at a time.
    // Clips at the midpoint of spacing between items so that you don't see any stray bits of the items that shouldn't be visible.
    var windowLength = ( scrollingDelta + options.spacing );
    if ( options.separatorsVisible ) {
      windowLength -= options.spacing;
    }
    var windowWidth = isHorizontal ? windowLength : scrollingNode.width;
    var windowHeight = isHorizontal ? scrollingNode.height : windowLength;
    var clipArea = isHorizontal ?
                   Shape.rectangle( options.spacing / 2, 0, windowWidth - options.spacing, windowHeight ) :
                   Shape.rectangle( 0, options.spacing / 2, windowWidth, windowHeight - options.spacing );
    var windowNode = new Node( {
      children: [ scrollingNode ],
      clipArea: clipArea
    } );

    // Background - displays the carousel's fill color
    var backgroundWidth = isHorizontal ? ( windowWidth + nextButton.width + previousButton.width ) : windowWidth;
    var backgroundHeight = isHorizontal ? windowHeight : ( windowHeight + nextButton.height + previousButton.height );
    var backgroundNode = new Rectangle( 0, 0, backgroundWidth, backgroundHeight, options.cornerRadius, options.cornerRadius, {
      fill: options.fill
    } );

    // Foreground - displays the carousel's outline, created as a separate node so that it can be placed on top of everything, for a clean look.
    var foregroundNode = new Rectangle( 0, 0, backgroundWidth, backgroundHeight, options.cornerRadius, options.cornerRadius, {
      stroke: options.stroke
    } );

    // Layout
    if ( isHorizontal ) {
      nextButton.centerY = previousButton.centerY = windowNode.centerY = backgroundNode.centerY;
      nextButton.right = backgroundNode.right;
      previousButton.left = backgroundNode.left;
      windowNode.centerX = backgroundNode.centerX;
    }
    else {
      nextButton.centerX = previousButton.centerX = windowNode.centerX = backgroundNode.centerX;
      nextButton.bottom = backgroundNode.bottom;
      previousButton.top = backgroundNode.top;
      windowNode.centerY = backgroundNode.centerY;
    }

    // Number of pages
    var numberOfPages = items.length / options.itemsPerPage;
    if ( !Util.isInteger( numberOfPages ) ) {
      numberOfPages = Math.floor( numberOfPages + 1 );
    }

    // Number of the page that is visible in the carousel.
    var pageNumberProperty = new Property( options.defaultPageNumber );

    // iOS-style page control
    var pageControl = null;
    if ( options.pageControlVisible ) {

      pageControl = new PageControl( numberOfPages, pageNumberProperty, {
        orientation: options.orientation,
        pageVisibleColor: options.pageVisibleColor,
        pageNotVisibleColor: options.pageNotVisibleColor,
        dotRadius: options.dotRadius,
        dotSpacing: options.dotSpacing
      } );

      // Layout
      if ( isHorizontal ) {
        pageControl.centerX = backgroundNode.centerX;
        if ( options.pageControlLocation === 'top' ) {
          pageControl.bottom = backgroundNode.top - options.pageControlSpacing;
        }
        else if ( options.pageControlLocation === 'bottom' ) {
          pageControl.top = backgroundNode.bottom + options.pageControlSpacing;
        }
        else {
          throw new Error( 'incompatible pageControlLocation=' + options.pageControlLocation + ' for orientation=' + options.orientation );
        }
      }
      else {
        pageControl.centerY = backgroundNode.centerY;
        if ( options.pageControlLocation === 'left' ) {
          pageControl.right = backgroundNode.left - options.pageControlSpacing;
        }
        else if ( options.pageControlLocation === 'right' ) {
          pageControl.left = backgroundNode.right + options.pageControlSpacing;
        }
        else {
          throw new Error( 'incompatible pageControlLocation=' + options.pageControlLocation + ' for orientation=' + options.orientation );
        }
      }
    }

    // Scroll when the buttons are pressed
    var scrollTween;
    pageNumberProperty.link( function( pageNumber ) {

      assert && assert( pageNumber >= 0 && pageNumber <= numberOfPages - 1, 'pageNumber out of range: ' + pageNumber );

      // stop any animation that's in progress
      scrollTween && scrollTween.stop();

      // button state
      nextButton.enabled = pageNumber < ( numberOfPages - 1 );
      previousButton.enabled = pageNumber > 0;
      if ( options.hideDisabledButtons ) {
        nextButton.visible = nextButton.enabled;
        previousButton.visible = previousButton.enabled;
      }

      //TODO replace calls to Tween with a wrapper
      // Set up the animation to scroll the items in the carousel.
      var parameters;
      var animationDuration = 400; // ms
      var easing = TWEEN.Easing.Cubic.InOut;
      if ( isHorizontal ) {
        parameters = { left: scrollingNode.left };
        scrollTween = new TWEEN.Tween( parameters )
          .easing( easing )
          .to( { left: -pageNumber * scrollingDelta }, animationDuration )
          .onUpdate( function() {
            scrollingNode.left = parameters.left;
          } )
          .start();
      }
      else {
        parameters = { top: scrollingNode.top };
        scrollTween = new TWEEN.Tween( parameters )
          .easing( easing )
          .to( { top: -pageNumber * scrollingDelta }, animationDuration )
          .onUpdate( function() {
            scrollingNode.top = parameters.top;
          } )
          .start();
      }
    } );

    // Buttons modify the page number
    nextButton.addListener( function() {
      pageNumberProperty.set( pageNumberProperty.get() + 1 );
    } );
    previousButton.addListener( function() {
      pageNumberProperty.set( pageNumberProperty.get() - 1 );
    } );

    // public fields
    this.numberOfPages = numberOfPages; // @public (read-only) {number} number of pages in the carousel
    this.pageNumberProperty = pageNumberProperty; // @public {Property<number>} page number that is currently visible

    // @private
    this.disposeCarousel = function() {
      if ( pageControl ) {
        pageControl.dispose();
      }
    };

    options.children = [ backgroundNode, windowNode, nextButton, previousButton, foregroundNode ];
    if ( pageControl ) {
      options.children.push( pageControl );
    }

    Node.call( this, options );
  }

  return inherit( Node, Carousel, {

    // Ensures that the carousel is eligibile for GC
    dispose: function() {
      this.disposeCarousel();
    },

    // Resets the carousel to its initial state
    reset: function() {
      this.pageNumberProperty.reset();
    }
  }, {

    // @static @public (read-only)
    DEFAULT_OPTIONS: DEFAULT_OPTIONS
  } );
} );
<|endoftext|>


<commit_before>//jshint esversion: 6
Package.describe({
    name: 'elmarti:video-chat',
    version: '2.1.2',
    summary: 'Simple WebRTC Video Chat for your app.',
    git: 'https://github.com/elmarti/meteor-video-chat',
    documentation: 'README.md'
});

Package.onUse(api => {

    Npm.depends({
        "rtcfly": "0.1.5"
    });

    api.versionsFrom('1.5');
    api.use('ecmascript');
    api.use("rocketchat:streamer@0.6.1");
    api.use("mizzao:user-status@0.6.7");
    api.addFiles(['lib/index.js'], "client");
    api.addFiles(['lib/publish.js'], "server");
    api.addFiles(['lib/index.server.js'], 'server');
    api.mainModule('lib/index.js', 'client');
});
<commit_msg>bump version<commit_after>//jshint esversion: 6
Package.describe({
    name: 'elmarti:video-chat',
    version: '2.1.3',
    summary: 'Simple WebRTC Video Chat for your app.',
    git: 'https://github.com/elmarti/meteor-video-chat',
    documentation: 'README.md'
});

Package.onUse(api => {

    Npm.depends({
        "rtcfly": "0.1.5"
    });

    api.versionsFrom('1.5');
    api.use('ecmascript');
    api.use("rocketchat:streamer@0.6.1");
    api.use("mizzao:user-status@0.6.7");
    api.addFiles(['lib/index.js'], "client");
    api.addFiles(['lib/publish.js'], "server");
    api.addFiles(['lib/index.server.js'], 'server');
    api.mainModule('lib/index.js', 'client');
});
<|endoftext|>


<commit_before><commit_msg>Adding hashing and validation helper functions for hasing the password before inserting and being able to check if the passwords match when logging in. Set timestamps on to be able to track when user was created and updated<commit_after><|endoftext|>


<commit_before>import constants from '../../constants';
import Room from '../../models/Room';
import Resource from '../../models/Resource';
import Permission from '../../models/Permission';

export default function load(req, [id]) {
  return new Promise((resolve, reject) => {
    const loadRoom = async() => {
      if (id) {
        const room = await Room.findById(id).select('-__v').lean();

        if (room) {
          const user = req.user;
          let permission = undefined;

          if (user) {
            const creator = user._id === room.creator;

            if (creator) {
              // find creator permission
            } else {
              const member = room.members.find(getEmailComparator(user.email));

              if (member) {
                permission = await getMemberPermission(member.role);
              }
            }
          } else {
            const {e: email} = req.query;

            if (email) {
              const member = room.members.find(getEmailComparator(email));

              permission = await getMemberPermission(member.role);
            }
          }

          if (permission) {
            resolve({room, permission});
          } else {
            reject({status: 401, message: 'Permission denied'});
          }
        } else {
          reject({status: 400, message: 'Room not found'});
        }
      } else reject({status: 401, message: 'Id is required'});
    };

    loadRoom().catch(reject);
  });
}

function getEmailComparator(email) {
  return item => item.email === email;
}

async function getMemberPermission(role) {
  const title = constants.resources.chat;
  const resource = await Resource.findOne({title}).lean();
  const options = {role, resource: resource._id};

  return await Permission.findOne(options).select('-_id -__v -resource').lean();
}<commit_msg>implement permission selection for registered users in rooms<commit_after>import constants from '../../constants';
import Room from '../../models/Room';
import Role from '../../models/Role';
import Resource from '../../models/Resource';
import Permission from '../../models/Permission';

export default function load(req, [id]) {
  return new Promise((resolve, reject) => {
    const loadRoom = async() => {
      if (id) {
        const room = await Room.findById(id).select('-__v').lean();

        if (room) {
          const user = req.user;
          let permission = undefined;

          if (user) {
            const creator = user._id == room.creator;

            if (creator) {
              const options = {title: constants.roles.creator};
              const creator = await Role.findOne(options).select('-title').lean();

              permission = await getMemberPermission(creator._id);
            } else {
              const member = room.members.find(getEmailComparator(user.email));

              if (member) {
                permission = await getMemberPermission(member.role);
              }
            }
          } else {
            const {e: email} = req.query;

            if (email) {
              const member = room.members.find(getEmailComparator(email));

              permission = await getMemberPermission(member.role);
            }
          }

          if (permission) {
            resolve({room, permission});
          } else {
            reject({status: 401, message: 'Permission denied'});
          }
        } else {
          reject({status: 400, message: 'Room not found'});
        }
      } else reject({status: 401, message: 'Id is required'});
    };

    loadRoom().catch(reject);
  });
}

function getEmailComparator(email) {
  return item => item.email === email;
}

async function getMemberPermission(role) {
  const title = constants.resources.chat;
  const resource = await Resource.findOne({title}).lean();
  const options = {role, resource: resource._id};

  return await Permission.findOne(options).select('-_id -__v -resource').lean();
}<|endoftext|>