<commit_before>var prettyjson = process.env.EXPRESS_COV ? require('../lib-cov/prettyjson') : require('../lib/prettyjson');
var should = require('should');

describe('prettyjson general tests', function() {

  it("should output a string exactly equal as the input", function() {

    var input = 'This is a string';
    var output = prettyjson.render(input);

    output.should.equal(input);
  });

  it("should output a string with indentation", function() {

    var input = 'This is a string';
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + input);
  });

  it("should output a multiline string with indentation", function() {

    var input = 'multiple\nlines'
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    """\n      multiple\n      lines\n    """');
  });

  it("should output an array of strings", function() {

    var input = ['first string', 'second string'];
    var output = prettyjson.render(input);

    output.should.equal([
      '- '.green + input[0],
      '- '.green + input[1]
    ].join('\n'));
  });

  it("should output an array of arrays", function() {

    var input = ['first string', ['nested 1', 'nested 2'], 'second string'];
    var output = prettyjson.render(input);

    output.should.equal([
      '- '.green + input[0],
      '- '.green,
      '  ' + '- '.green + input[1][0],
      '  ' + '- '.green + input[1][1],
      '- '.green + input[2]
    ].join('\n'));
  });

  it("should output a hash of strings", function() {

    var input = {param1: 'first string', param2: 'second string'};
    var output = prettyjson.render(input);

    output.should.equal([
      'param1: '.green + 'first string',
      'param2: '.green + 'second string'
    ].join('\n'));
  });

  it("should output a hash of hashes", function() {

    var input = {first_param: {subparam: 'first string', subparam2: 'another string'}, second_param: 'second string'};
    var output = prettyjson.render(input);

    output.should.equal([
      'first_param: '.green,
      '  ' + 'subparam: '.green + ' first string',
      '  ' + 'subparam2: '.green + 'another string',
      'second_param: '.green + 'second string'
    ].join('\n'));
  });

  it("should indent correctly the hashes keys", function() {

    var input = {very_large_param: 'first string', param: 'second string'};
    var output = prettyjson.render(input);

    output.should.equal([
      'very_large_param: '.green + 'first string',
      'param: '.green + '           second string'
    ].join('\n'));
  });

  it("should output a really nested object", function() {

    var input = {
      first_param: {
        subparam: 'first string',
        subparam2: 'another string',
        subparam3: ["different", "values", "in an array"]
      },
      second_param: 'second string',
      an_array: [{
        param3: 'value',
        param10: 'other value'
      }],
      empty_array: []
    };

    var output = prettyjson.render(input);

    output.should.equal([
      'first_param: '.green,
      '  ' + 'subparam: '.green + ' first string',
      '  ' + 'subparam2: '.green + 'another string',
      '  ' + 'subparam3: '.green,
      '    ' + '- '.green + 'different',
      '    ' + '- '.green + 'values',
      '    ' + '- '.green + 'in an array',
      'second_param: '.green + 'second string',
      'an_array: '.green,
      '  ' + '- '.green,
      '    ' + 'param3: '.green + ' value',
      '    ' + 'param10: '.green + 'other value',
      'empty_array: '.green,
      '  (empty array)'
    ].join('\n'));
  });

  it("should allow to configure colors for hash keys", function() {
    var input = {param1: 'first string', param2: 'second string'};
    var output = prettyjson.render(input, {keysColor: 'blue'});

    output.should.equal([
      'param1: '.blue + 'first string',
      'param2: '.blue + 'second string'
    ].join('\n'));
  });

  it("should allow to configure colors for numbers", function() {
    var input = {param1: 17, param2: 22.3};
    var output = prettyjson.render(input, {numberColor: 'red'});

    output.should.equal([
      'param1: '.green + '17'.red,
      'param2: '.green + '22.3'.red
    ].join('\n'));
  });

  it("should allow to configure rainbow as color", function() {
    var input = {param_long: 'first string', param2: 'second string'};
    var output = prettyjson.render(input, {keysColor: 'rainbow'});

    output.should.equal([
      'param_long: '.rainbow + 'first string',
      'param2: '.rainbow + '    second string'
    ].join('\n'));
  });

  it("should allow to configure the default indentation", function() {
    var input = {param: ['first string', "second string"]};
    var output = prettyjson.render(input, {defaultIndentation: 4});

    output.should.equal([
      'param: '.green,
      '    ' + '- '.green + 'first string',
      '    ' + '- '.green + 'second string'
    ].join('\n'));
  });

  it("should allow to configure the empty message for arrays", function() {
    var input = [];
    var output = prettyjson.render(input, {emptyArrayMsg: '(empty)'});

    output.should.equal([
      '(empty)'
    ].join('\n'));
  });

  it("should allow to configure colors for strings", function() {
    var input = {param1: 'first string', param2: 'second string'};
    var output = prettyjson.render(input, {keysColor: 'blue', stringColor: 'red'});

    output.should.equal([
      'param1: '.blue + 'first string'.red,
      'param2: '.blue + 'second string'.red
    ].join('\n'));
  });

  it("should allow to not use colors", function() {
    var input = {param1: 'first string', param2: ['second string']};
    var output = prettyjson.render(input, {noColor: true});

    output.should.equal([
      'param1: first string',
      'param2: ',
      '  - second string'
    ].join('\n'));
  });

  it("should allow to print simple arrays inline", function() {
    var input = {installs: ['first string', 'second string', false, 13]};
    var output = prettyjson.render(input, {inlineArrays: true});

    output.should.equal(
      'installs: '.green + 'first string, second string, false, 13');

    input = {installs: [ ['first string', 'second string'], 'third string']};
    output = prettyjson.render(input, {inlineArrays: true});

    output.should.equal([
      'installs: '.green,
      '  ' + '- '.green + 'first string, second string',
      '  ' + '- '.green + 'third string'
      ].join('\n'));
  });

  it("should not print an object prototype", function() {
    var Input = function() {
      this.param1 = 'first string';
      this.param2 = 'second string';
    };
    Input.prototype = {randomProperty: 'idontcare'};

    var output = prettyjson.render(new Input);

    output.should.equal([
      'param1: '.green + 'first string',
      'param2: '.green + 'second string'
    ].join('\n'));
  });
});

describe('Printing numbers, booleans and other objects', function() {
  it("should print numbers correctly ", function() {
    var input = 12345;
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + '12345'.blue);
  });

  it("should print booleans correctly ", function() {
    var input = true;
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + 'true'.green);

    input = false;
    output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + 'false'.red);
  });

  it("should print a null object correctly ", function() {
    var input = null;
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + 'null'.grey);
  });

  it("should print an Error correctly ", function() {
    Error.stackTraceLimit = 1;
    var input = new Error('foo');
    var stack = input.stack.split('\n');
    var output = prettyjson.render(input, {}, 4);

    output.should.equal([
      '    ' + 'stack: '.green,
      '      ' + '- '.green + stack[0],
      '      ' + '- '.green + stack[1],
      '    ' + 'message: '.green + '  foo'
    ].join('\n'));
  });

  it('should print serializable items in an array inline', function() {
	var dt = new Date();
    var output = prettyjson.render([ 'a', 3, null, true, false, dt]);

    output.should.equal([
      '- '.green + 'a',
      '- '.green + '3'.blue,
      '- '.green + 'null'.grey,
      '- '.green + 'true'.green,
      '- '.green + 'false'.red,
	  '- '.green + dt
    ].join('\n'));
  });

  it('should print dates correctly', function() {
	var input = new Date();
	var expected = input.toString();
	var output = prettyjson.render(input, {}, 4);

	output.should.equal('    ' + expected);
  });

  it('should print dates in objects correctly', function() {
	var dt1 = new Date();
	var dt2 = new Date();

	var input = {
		dt1: dt2,
		dt2: dt2
	};

	var output = prettyjson.render(input, {}, 4);

	output.should.equal([
		'    ' + 'dt1: '.green + dt1.toString(),
		'    ' + 'dt2: '.green + dt2.toString()].join('\n'));
  });
});

describe('prettyjson.renderString() method', function(){
  it('should return an empty string if input is empty', function(){
    var input = '';

    var output = prettyjson.renderString(input);

    output.should.equal('');
  });

  it('should return an empty string if input is not a string', function(){
    var output = prettyjson.renderString({});
    output.should.equal('');
  });

  it('should return an error message if the input is an invalid JSON string', function(){
    var output = prettyjson.renderString('not valid!!');
    output.should.equal('Error:'.red + ' Not valid JSON!');
  });

  it('should return the prettyfied string if it is a valid JSON string', function(){
    var output = prettyjson.renderString('{"test": "OK"}');
    output.should.equal('test: '.green + 'OK');
  });

  it('should dismiss trailing characters which are not JSON', function(){
    var output = prettyjson.renderString('characters that are not JSON at all... {"test": "OK"}');
    output.should.equal("characters that are not JSON at all... \n" + 'test: '.green + 'OK');
  });

  it('should dismiss trailing characters which are not JSON with an array', function(){
    var output = prettyjson.renderString('characters that are not JSON at all... ["test"]');
    output.should.equal("characters that are not JSON at all... \n" + '- '.green + 'test');
  });

  it('should be able to accept the options parameter', function(){
    var output = prettyjson.renderString('{"test": "OK"}', {stringColor: 'red'});
    output.should.equal('test: '.green + 'OK'.red);
  });
});
<commit_msg>Fix tests format<commit_after>var prettyjson = process.env.EXPRESS_COV ? require('../lib-cov/prettyjson') : require('../lib/prettyjson');
var should = require('should');

describe('prettyjson general tests', function() {

  it("should output a string exactly equal as the input", function() {

    var input = 'This is a string';
    var output = prettyjson.render(input);

    output.should.equal(input);
  });

  it("should output a string with indentation", function() {

    var input = 'This is a string';
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + input);
  });

  it("should output a multiline string with indentation", function() {

    var input = 'multiple\nlines'
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    """\n      multiple\n      lines\n    """');
  });

  it("should output an array of strings", function() {

    var input = ['first string', 'second string'];
    var output = prettyjson.render(input);

    output.should.equal([
      '- '.green + input[0],
      '- '.green + input[1]
    ].join('\n'));
  });

  it("should output an array of arrays", function() {

    var input = ['first string', ['nested 1', 'nested 2'], 'second string'];
    var output = prettyjson.render(input);

    output.should.equal([
      '- '.green + input[0],
      '- '.green,
      '  ' + '- '.green + input[1][0],
      '  ' + '- '.green + input[1][1],
      '- '.green + input[2]
    ].join('\n'));
  });

  it("should output a hash of strings", function() {

    var input = {param1: 'first string', param2: 'second string'};
    var output = prettyjson.render(input);

    output.should.equal([
      'param1: '.green + 'first string',
      'param2: '.green + 'second string'
    ].join('\n'));
  });

  it("should output a hash of hashes", function() {

    var input = {first_param: {subparam: 'first string', subparam2: 'another string'}, second_param: 'second string'};
    var output = prettyjson.render(input);

    output.should.equal([
      'first_param: '.green,
      '  ' + 'subparam: '.green + ' first string',
      '  ' + 'subparam2: '.green + 'another string',
      'second_param: '.green + 'second string'
    ].join('\n'));
  });

  it("should indent correctly the hashes keys", function() {

    var input = {very_large_param: 'first string', param: 'second string'};
    var output = prettyjson.render(input);

    output.should.equal([
      'very_large_param: '.green + 'first string',
      'param: '.green + '           second string'
    ].join('\n'));
  });

  it("should output a really nested object", function() {

    var input = {
      first_param: {
        subparam: 'first string',
        subparam2: 'another string',
        subparam3: ["different", "values", "in an array"]
      },
      second_param: 'second string',
      an_array: [{
        param3: 'value',
        param10: 'other value'
      }],
      empty_array: []
    };

    var output = prettyjson.render(input);

    output.should.equal([
      'first_param: '.green,
      '  ' + 'subparam: '.green + ' first string',
      '  ' + 'subparam2: '.green + 'another string',
      '  ' + 'subparam3: '.green,
      '    ' + '- '.green + 'different',
      '    ' + '- '.green + 'values',
      '    ' + '- '.green + 'in an array',
      'second_param: '.green + 'second string',
      'an_array: '.green,
      '  ' + '- '.green,
      '    ' + 'param3: '.green + ' value',
      '    ' + 'param10: '.green + 'other value',
      'empty_array: '.green,
      '  (empty array)'
    ].join('\n'));
  });

  it("should allow to configure colors for hash keys", function() {
    var input = {param1: 'first string', param2: 'second string'};
    var output = prettyjson.render(input, {keysColor: 'blue'});

    output.should.equal([
      'param1: '.blue + 'first string',
      'param2: '.blue + 'second string'
    ].join('\n'));
  });

  it("should allow to configure colors for numbers", function() {
    var input = {param1: 17, param2: 22.3};
    var output = prettyjson.render(input, {numberColor: 'red'});

    output.should.equal([
      'param1: '.green + '17'.red,
      'param2: '.green + '22.3'.red
    ].join('\n'));
  });

  it("should allow to configure rainbow as color", function() {
    var input = {param_long: 'first string', param2: 'second string'};
    var output = prettyjson.render(input, {keysColor: 'rainbow'});

    output.should.equal([
      'param_long: '.rainbow + 'first string',
      'param2: '.rainbow + '    second string'
    ].join('\n'));
  });

  it("should allow to configure the default indentation", function() {
    var input = {param: ['first string', "second string"]};
    var output = prettyjson.render(input, {defaultIndentation: 4});

    output.should.equal([
      'param: '.green,
      '    ' + '- '.green + 'first string',
      '    ' + '- '.green + 'second string'
    ].join('\n'));
  });

  it("should allow to configure the empty message for arrays", function() {
    var input = [];
    var output = prettyjson.render(input, {emptyArrayMsg: '(empty)'});

    output.should.equal([
      '(empty)'
    ].join('\n'));
  });

  it("should allow to configure colors for strings", function() {
    var input = {param1: 'first string', param2: 'second string'};
    var output = prettyjson.render(input, {keysColor: 'blue', stringColor: 'red'});

    output.should.equal([
      'param1: '.blue + 'first string'.red,
      'param2: '.blue + 'second string'.red
    ].join('\n'));
  });

  it("should allow to not use colors", function() {
    var input = {param1: 'first string', param2: ['second string']};
    var output = prettyjson.render(input, {noColor: true});

    output.should.equal([
      'param1: first string',
      'param2: ',
      '  - second string'
    ].join('\n'));
  });

  it("should allow to print simple arrays inline", function() {
    var input = {installs: ['first string', 'second string', false, 13]};
    var output = prettyjson.render(input, {inlineArrays: true});

    output.should.equal(
      'installs: '.green + 'first string, second string, false, 13');

    input = {installs: [ ['first string', 'second string'], 'third string']};
    output = prettyjson.render(input, {inlineArrays: true});

    output.should.equal([
      'installs: '.green,
      '  ' + '- '.green + 'first string, second string',
      '  ' + '- '.green + 'third string'
      ].join('\n'));
  });

  it("should not print an object prototype", function() {
    var Input = function() {
      this.param1 = 'first string';
      this.param2 = 'second string';
    };
    Input.prototype = {randomProperty: 'idontcare'};

    var output = prettyjson.render(new Input);

    output.should.equal([
      'param1: '.green + 'first string',
      'param2: '.green + 'second string'
    ].join('\n'));
  });
});

describe('Printing numbers, booleans and other objects', function() {
  it("should print numbers correctly ", function() {
    var input = 12345;
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + '12345'.blue);
  });

  it("should print booleans correctly ", function() {
    var input = true;
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + 'true'.green);

    input = false;
    output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + 'false'.red);
  });

  it("should print a null object correctly ", function() {
    var input = null;
    var output = prettyjson.render(input, {}, 4);

    output.should.equal('    ' + 'null'.grey);
  });

  it("should print an Error correctly ", function() {
    Error.stackTraceLimit = 1;
    var input = new Error('foo');
    var stack = input.stack.split('\n');
    var output = prettyjson.render(input, {}, 4);

    output.should.equal([
      '    ' + 'stack: '.green,
      '      ' + '- '.green + stack[0],
      '      ' + '- '.green + stack[1],
      '    ' + 'message: '.green + '  foo'
    ].join('\n'));
  });

  it('should print serializable items in an array inline', function() {
	var dt = new Date();
    var output = prettyjson.render([ 'a', 3, null, true, false, dt]);

    output.should.equal([
      '- '.green + 'a',
      '- '.green + '3'.blue,
      '- '.green + 'null'.grey,
      '- '.green + 'true'.green,
      '- '.green + 'false'.red,
	  '- '.green + dt
    ].join('\n'));
  });

  it('should print dates correctly', function() {
	var input = new Date();
	var expected = input.toString();
	var output = prettyjson.render(input, {}, 4);

	output.should.equal('    ' + expected);
  });

  it('should print dates in objects correctly', function() {
	var dt1 = new Date();
	var dt2 = new Date();

	var input = {
		dt1: dt2,
		dt2: dt2
	};

	var output = prettyjson.render(input, {}, 4);

	output.should.equal([
		'    ' + 'dt1: '.green + dt1.toString(),
		'    ' + 'dt2: '.green + dt2.toString()].join('\n'));
  });
});

describe('prettyjson.renderString() method', function(){
  it('should return an empty string if input is empty', function(){
    var input = '';

    var output = prettyjson.renderString(input);

    output.should.equal('');
  });

  it('should return an empty string if input is not a string', function(){
    var output = prettyjson.renderString({});
    output.should.equal('');
  });

  it('should return an error message if the input is an invalid JSON string', function(){
    var output = prettyjson.renderString('not valid!!');
    output.should.equal('Error:'.red + ' Not valid JSON!');
  });

  it('should return the prettyfied string if it is a valid JSON string', function(){
    var output = prettyjson.renderString('{"test": "OK"}');
    output.should.equal('test: '.green + 'OK');
  });

  it('should dismiss trailing characters which are not JSON', function(){
    var output = prettyjson.renderString('characters that are not JSON at all... {"test": "OK"}');
    output.should.equal("characters that are not JSON at all... \n" + 'test: '.green + 'OK');
  });

  it('should dismiss trailing characters which are not JSON with an array', function(){
    var output = prettyjson.renderString('characters that are not JSON at all... ["test"]');
    output.should.equal("characters that are not JSON at all... \n" + '- '.green + 'test');
  });

  it('should be able to accept the options parameter', function(){
    var output = prettyjson.renderString('{"test": "OK"}', {stringColor: 'red'});
    output.should.equal('test: '.green + 'OK'.red);
  });
});
<|endoftext|>


<commit_before>var env = process.env,
    port = env.PORT || 80,
    ip = env.PORT ? '0.0.0.0' : '127.0.0.1',
    http = require('http'),
    https = require('https'),
    gzip = require('zlib');
    /*Twitter = require('ntwitter');

var twitter = new Twitter({
    consumer_key: env.TWITTER_CONSUMER_KEY,
    consumer_secret: env.TWITTER_CONSUMER_SECRET,
    access_token_key: env.TWITTER_TOKEN_KEY,
    access_token_secret: env.TWITTER_TOKEN_SECRET
});*/

function lastUTCMinusMinutes(mins) {
    var now = new Date();
    now = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(),  now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
    now.setMinutes(now.getMinutes() - mins);
    return now.getTime();
}

function getSOUrl() {
    var time = lastUTCMinusMinutes(+env.MINUTES),
        url = '/2.0/questions?fromdate=';
        url += Math.floor(time / 1000);
        url += '&order=desc&sort=creation&tagged=yui&site=stackoverflow';
        url += '&key=' + env.SO_KEY;
    return url;
}

http.createServer(function (req, res) {
    var url;
    if (req.url == '/favicon.ico') {
		res.writeHead(200, { 'Content-Type': 'image/png' });
		res.end();
    } else {
		res.writeHead(200, { 'Content-Type': 'text/plain' });
		url = getSOUrl();

		console.log('getting url: ' + url);
		https.get({
            host: 'api.stackexchange.com',
            path: url
        }, function (so) {
			var result = '';
			so.pipe(gzip.createGunzip()).on('data', function (chunk) {
				result += chunk;
			}).on('end', function () {
				res.end(result + '\n');
			});
		}).on('error', function (err) {
			res.end('An error ocurred: ' + err.message);
		});
    }
}).listen(port, ip);
console.log('Server running at http://' + ip + ':' + port + '/');<commit_msg>twitter connection<commit_after>var env = process.env,
    port = env.PORT || 80,
    ip = env.PORT ? '0.0.0.0' : '127.0.0.1',
    http = require('http'),
    https = require('https'),
    gzip = require('zlib'),
    Twitter = require('ntwitter');

var twitter = new Twitter({
    consumer_key: env.TWITTER_CONSUMER_KEY,
    consumer_secret: env.TWITTER_CONSUMER_SECRET,
    access_token_key: env.TWITTER_TOKEN_KEY,
    access_token_secret: env.TWITTER_TOKEN_SECRET
});

function lastUTCMinusMinutes(mins) {
    var now = new Date();
    now = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(),  now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
    now.setMinutes(now.getMinutes() - mins);
    return now.getTime();
}

function getSOUrl() {
    var time = lastUTCMinusMinutes(+env.MINUTES),
        url = '/2.0/questions?fromdate=';
        url += Math.floor(time / 1000);
        url += '&order=desc&sort=creation&tagged=yui&site=stackoverflow';
        url += '&key=' + env.SO_KEY;
    return url;
}

http.createServer(function (req, res) {

    function handleError(err) {
        console.error(err);
        res.end('An error has ocurred\n');
    }

    function sendToTwitter(questions) {
        questions.forEach(function (question) {
            var title = question.title;
            if (title.length > 115) {
                title = title.substr(0, 112) + '...';
            }
            twitter.updateStatus(title + 'http://stackoverflow.com/questions/' + question.question_id, function (err) {
                if (err) {
                    console.error(err);
                }
            });
        });
        res.end('published ' + questions.length + ' questions\n');
    }

    if (req.url == '/favicon.ico') {
		res.writeHead(200, { 'Content-Type': 'image/png' });
		res.end();
    } else {
		res.writeHead(200, { 'Content-Type': 'text/plain' });

		https.get({
            host: 'api.stackexchange.com',
            path: getSOUrl()
        }, function (so) {
			var result = '';
			so.pipe(gzip.createGunzip()).on('data', function (chunk) {
				result += chunk;
			}).on('end', function () {
				result = JSON.parse(result);
                if (result.error_id) {
                    handleError(result);
                } else {
                    sendToTwitter(result.items);
                }
			});
		}).on('error', handleError);
    }
}).listen(port, ip);
console.log('Server running at http://' + ip + ':' + port + '/');<|endoftext|>


<commit_before>'use strict'

import wildcard from 'socketio-wildcard'
import io from 'socket.io-client'
import Signal from 'signals'
import logger from './logger'

const patch = wildcard(io.Manager)

let config = {
  channelName: null,
  clientName: null,
  packers: [],
  unpackers: [],
  sendBack: true,
  verbose: true,
  multiService: false
}

let connected = false
let unpackers = []
let packers = []
let sockets = []
let events = {}

function connect (_address, _port, _options) {
  let address = (typeof _address === 'object') ? null : _address
  let port = (typeof _address === 'object') ? null : (typeof _port === 'object') ? null : _port
  let options = (typeof _address === 'object') ? _address : (typeof _port === 'object') ? _port : _options

  Object.assign(config, options)
  logger.setup(config.verbose)
  logger.log(`Trying to connect on ${address}:${port} with config:\n`, config)

  if (address && port) {
    initSocketIO(address, port, null)
  } else {
    logger.warn('please provide a server address and port')
  }

  for (let packer of config.packers){
    addPacker(packer.handler, packer.priority, packer.eventName)
  }
  for (let unpacker of config.unpackers){
    addUnpacker(unpacker.handler, unpacker.priority, unpacker.eventName)
  }
}

function initSocketIO (address, port) {
  let parsedURI = require('url').parse(address)
  let protocol = parsedURI.protocol ? '' : 'ws://'
  let url = `${protocol}${address}:${port}`

  let socket = io(url)

  patch(socket)

  socket
    .on('connect', function () {
      connected = true
      logger.log('socket connected')
      if (sockets.length < 1) {
        sockets.push(socket)
      } else {
        sockets.forEach((el) => {
          if (el.id !== socket.id) {
            sockets.push(socket)
          }
        })
      }
      socket.emit('register', {
        clientName: config.clientName,
        channelName: config.channelName
      })
      events['connect'] && events['connect'].dispatch(socket)
    })
    .on('connect_error', (err) => {
      logger.warn('error', err)
      connected = false
      events['connect_error'] && events['connect_error'].dispatch(err)
    })
    .on('connect_timeout', ()=>{
      logger.warn('connection timeout')
      events['connect_timeout'] && events['connect_timeout'].dispatch()
    })
    .on('error', function (err) {
      logger.warn('error', err)
      connected = false
      events['error'] && events['error'].dispatch(err)
    })
    .on('disconnect', function (err) {
      logger.log('socket down')
      events['disconnect'] && events['disconnect'].dispatch(err)
      connected = false
    })
    .on('reconnect', function (data) {
      logger.log('socket reconnected')
      events['reconnect'] && events['reconnect'].dispatch(data)
      connected = true
    })
    .on('reconnect_attempt', function (attempt) {
      logger.log(`socket reconnect attempt: ${attempt}`)
      events['reconnect_attempt'] && events['reconnect_attempt'].dispatch(attempt)
    })
    .on('reconnecting', function (attempt) {
      logger.log(`socket try to reconnect, attempt: ${attempt}`)
      events['reconnecting'] && events['reconnecting'].dispatch(attempt)
    }).on('reconnect_error', function (err) {
      logger.warn(`socket reconnection error`)
      logger.warn(err)
      events['reconnect_error'] && events['reconnect_error'].dispatch(err)
    }).on('reconnect_failed', function (err) {
      logger.warn(`socket can't reconnect`)
      logger.warn(err)
      events['reconnect_failed'] && events['reconnect_failed'].dispatch(err)
    })

    .on('*', function ({ data }) {
      let [eventName, args] = data
      if (!config.sendBack && args._from === config.clientName) {
        return
      } else if (events[eventName]) {
        logger.log(`socket received ${eventName} with data:`, args)
        for (let unpack of filterHooks(eventName, unpackers)) {
          const unpacked = unpack({ eventName, data: args })
          args = unpacked || args
        }
        events[eventName].dispatch(args)
      }
    })
}

function addPacker (handler, priority, eventName) { addHook(packers, eventName, handler, priority) }
function addUnpacker (handler, priority, eventName) { addHook(unpackers, eventName, handler, priority) }

function emit (eventName, data = {}) {
  // null is a type of Object. so we have to check null and undefined with loosy compare
  if (typeof data !== 'object' || data == null) {
    data = {data: data}
    data.altered = true
  }
  sendTo(eventName, null, data)
}

function sendTo (eventName, to = null, data = {}) {
  if (connected) {
    data._to = to
    data._from = config.clientName
    for (let pack of filterHooks(eventName, packers)) {
      data = pack({eventName, data}) || data
    }
    for (let socket of sockets) {
      socket.emit(eventName, data)
    }
  } else {
    logger.warn('can\'t emit, not connected.')
  }
}

// Reception
function on (eventName, handler, handlerContext, priority) {
  events[eventName] = new Signal()
  events[eventName].add(handler, handlerContext, priority)
}

function once (eventName, handler, handlerContext, priority) {
  events[eventName] = new Signal()
  events[eventName].addOnce(handler, handlerContext, priority)
}

function off (eventName) {
  delete events[eventName]
}

function filterHooks (eventName, hooks) {
  return hooks
    .filter(hook => [eventName, '*'].indexOf(hook.eventName) !== -1)
    .sort(hook => -hook.priority || 0)
    .map(hook => hook.handler)
}

function addHook (hooks, eventName = '*' , handler, priority = 0) {
  hooks.push({ eventName, handler, priority})
}
var send = emit

export default { connect, addPacker, addUnpacker, emit, send, sendTo, on, once, off }
<commit_msg>fix standard<commit_after>'use strict'

import wildcard from 'socketio-wildcard'
import io from 'socket.io-client'
import Signal from 'signals'
import logger from './logger'

const patch = wildcard(io.Manager)

let config = {
  channelName: null,
  clientName: null,
  packers: [],
  unpackers: [],
  sendBack: true,
  verbose: true,
  multiService: false
}

let connected = false
let unpackers = []
let packers = []
let sockets = []
let events = {}

function connect (_address, _port, _options) {
  let address = (typeof _address === 'object') ? null : _address
  let port = (typeof _address === 'object') ? null : (typeof _port === 'object') ? null : _port
  let options = (typeof _address === 'object') ? _address : (typeof _port === 'object') ? _port : _options

  Object.assign(config, options)
  logger.setup(config.verbose)
  logger.log(`Trying to connect on ${address}:${port} with config:\n`, config)

  if (address && port) {
    initSocketIO(address, port, null)
  } else {
    logger.warn('please provide a server address and port')
  }

  for (let packer of config.packers) {
    addPacker(packer.handler, packer.priority, packer.eventName)
  }
  for (let unpacker of config.unpackers) {
    addUnpacker(unpacker.handler, unpacker.priority, unpacker.eventName)
  }
}

function initSocketIO (address, port) {
  let parsedURI = require('url').parse(address)
  let protocol = parsedURI.protocol ? '' : 'ws://'
  let url = `${protocol}${address}:${port}`

  let socket = io(url)

  patch(socket)

  socket
    .on('connect', function () {
      connected = true
      logger.log('socket connected')
      if (sockets.length < 1) {
        sockets.push(socket)
      } else {
        sockets.forEach((el) => {
          if (el.id !== socket.id) {
            sockets.push(socket)
          }
        })
      }
      socket.emit('register', {
        clientName: config.clientName,
        channelName: config.channelName
      })
      events['connect'] && events['connect'].dispatch(socket)
    })
    .on('connect_error', (err) => {
      logger.warn('error', err)
      connected = false
      events['connect_error'] && events['connect_error'].dispatch(err)
    })
    .on('connect_timeout', () => {
      logger.warn('connection timeout')
      events['connect_timeout'] && events['connect_timeout'].dispatch()
    })
    .on('error', function (err) {
      logger.warn('error', err)
      connected = false
      events['error'] && events['error'].dispatch(err)
    })
    .on('disconnect', function (err) {
      logger.log('socket down')
      events['disconnect'] && events['disconnect'].dispatch(err)
      connected = false
    })
    .on('reconnect', function (data) {
      logger.log('socket reconnected')
      events['reconnect'] && events['reconnect'].dispatch(data)
      connected = true
    })
    .on('reconnect_attempt', function (attempt) {
      logger.log(`socket reconnect attempt: ${attempt}`)
      events['reconnect_attempt'] && events['reconnect_attempt'].dispatch(attempt)
    })
    .on('reconnecting', function (attempt) {
      logger.log(`socket try to reconnect, attempt: ${attempt}`)
      events['reconnecting'] && events['reconnecting'].dispatch(attempt)
    }).on('reconnect_error', function (err) {
      logger.warn(`socket reconnection error`)
      logger.warn(err)
      events['reconnect_error'] && events['reconnect_error'].dispatch(err)
    }).on('reconnect_failed', function (err) {
      logger.warn(`socket can't reconnect`)
      logger.warn(err)
      events['reconnect_failed'] && events['reconnect_failed'].dispatch(err)
    })

    .on('*', function ({ data }) {
      let [eventName, args] = data
      if (!config.sendBack && args._from === config.clientName) {
      } else if (events[eventName]) {
        logger.log(`socket received ${eventName} with data:`, args)
        for (let unpack of filterHooks(eventName, unpackers)) {
          const unpacked = unpack({ eventName, data: args })
          args = unpacked || args
        }
        events[eventName].dispatch(args)
      }
    })
}

function addPacker (handler, priority, eventName) { addHook(packers, eventName, handler, priority) }
function addUnpacker (handler, priority, eventName) { addHook(unpackers, eventName, handler, priority) }

function emit (eventName, data = {}) {
  // null is a type of Object. so we have to check null and undefined with loosy compare
  if (typeof data !== 'object' || data == null) {
    data = {data: data}
    data.altered = true
  }
  sendTo(eventName, null, data)
}

function sendTo (eventName, to = null, data = {}) {
  if (connected) {
    data._to = to
    data._from = config.clientName
    for (let pack of filterHooks(eventName, packers)) {
      data = pack({eventName, data}) || data
    }
    for (let socket of sockets) {
      socket.emit(eventName, data)
    }
  } else {
    logger.warn('can\'t emit, not connected.')
  }
}

// Reception
function on (eventName, handler, handlerContext, priority) {
  events[eventName] = new Signal()
  events[eventName].add(handler, handlerContext, priority)
}

function once (eventName, handler, handlerContext, priority) {
  events[eventName] = new Signal()
  events[eventName].addOnce(handler, handlerContext, priority)
}

function off (eventName) {
  delete events[eventName]
}

function filterHooks (eventName, hooks) {
  return hooks
    .filter(hook => [eventName, '*'].indexOf(hook.eventName) !== -1)
    .sort(hook => -hook.priority || 0)
    .map(hook => hook.handler)
}

function addHook (hooks, eventName = '*', handler, priority = 0) {
  hooks.push({eventName, handler, priority})
}
var send = emit

export default { connect, addPacker, addUnpacker, emit, send, sendTo, on, once, off }
<|endoftext|>


<commit_before>// USE WORDWRAP AND MAXIMIZE THE WINDOW TO SEE THIS FILE
// v5

// === 1 === EXTRAS
s_hideTimeout=500;//1000=1 second
s_subShowTimeout=300;//if <=100 the menus will function like SM4.x
s_subMenuOffsetX=4;//pixels (if no subs, leave as you like)
s_subMenuOffsetY=1;
s_keepHighlighted=true;
s_autoSELECTED=false;//make the item linking to the current page SELECTED
s_autoSELECTEDItemsClickable=false;//look at IMPORTANT NOTES 1 in the Manual
s_autoSELECTEDTree=true;//look at IMPORTANT NOTES 1 in the Manual
s_autoSELECTEDTreeItemsClickable=true;//look at IMPORTANT NOTES 1 in the Manual
s_scrollingInterval=30;//scrolling for tall menus
s_rightToLeft=false;
s_hideSELECTsInIE=false;//look at IMPORTANT HOWTOS 7 in the Manual

// === 2 === Default TARGET for all the links
// for navigation to frame, calling functions or
// different target for any link look at
// IMPORTANT HOWTOS 1 NOTES in the Manual
s_target='self';//(newWindow/self/top)

// === 3 === STYLESHEETS- you can define different arrays and then assign
// them to any menu you want with the s_add() function
s_CSSTop=[
'#5C5C5C',	// BorderColorDOM ('top right bottom left' or 'all')
'#5C5C5C',	// BorderColorNS4
1,		// BorderWidth
'#5C5C5C',	// BgColor
1,		// Padding
'#5C5C5C',	// ItemBgColor
'#6A8989',	// ItemOverBgColor
'#FFFFFF',	// ItemFontColor
'#FFFFFF',	// ItemOverFontColor
'verdana,arial,helvetica,sans-serif',	// ItemFontFamily
'10px',		// ItemFontSize (css)
'1',		// ItemFontSize Netscape4 (look at KNOWN BUGS 3 in the Manual)
'bold',		// ItemFontWeight (bold/normal)
'left',		// ItemTextAlign (left/center/right)
3,		// ItemPadding
1,		// ItemSeparatorSize
'#8A8CCC',	// ItemSeparatorColor
'',		// IEfilter (look at Samples\IE4(5.5)Filters dirs)
true,				// UseSubImg
'',		// SubImgSrc
'',	// OverSubImgSrc
7,				// SubImgWidth
7,				// SubImgHeight
5,				// SubImgTop px (from item top)
'#6A8989',			// SELECTED ItemBgColor
'#FFFFFF',			// SELECTED ItemFontColor
'',	// SELECTED SubImgSrc
true,				// UseScrollingForTallMenus
'',	// ScrollingImgTopSrc
'',	// ScrollingImgBottomSrc
68,				// ScrollingImgWidth
12,				// ScrollingImgHeight
'',		// ItemClass (css)
'',		// ItemOverClass (css)
'',		// SELECTED ItemClass (css)
0,		// ItemBorderWidth
'#5C5C5C',	// ItemBorderColor ('top right bottom left' or 'all')
'#6A8989',	// ItemBorderOverColor ('top right bottom left' or 'all')
'#6A8989',	// SELECTED ItemBorderColor ('top right bottom left' or 'all')
0,		// ItemSeparatorSpacing
'',		// ItemSeparatorBgImage
'',		// ItemBgImage
'',		// ItemOnBgImage
''		// SELECTED ItemBgImage
];

// === 4 === MENU DEFINITIONS
//Workflow
s_add(
{
N:'workflow',	// NAME
LV:1,		// LEVEL (look at IMPORTANT NOTES 1 in the Manual)
MinW:130,	// MINIMAL WIDTH
T:138,		// TOP (look at IMPORTANT HOWTOS 6 in the Manual)
L:270,		// LEFT (look at IMPORTANT HOWTOS 6 in the Manual)
P:false,	// menu is PERMANENT (you can only set true if this is LEVEL 1 menu)
S:s_CSSTop	// STYLE Array to use for this menu
},
[		// define items {U:'url',T:'text' ...} look at the Manual for details
{U:'createRun.jsp',T:'Execute Workflow'}
]
);
//administration
s_add(
{
N:'administration',	// NAME
LV:1,		// LEVEL (look at IMPORTANT NOTES 1 in the Manual)
MinW:130,	// MINIMAL WIDTH
T:138,		// TOP (look at IMPORTANT HOWTOS 6 in the Manual)
L:352,		// LEFT (look at IMPORTANT HOWTOS 6 in the Manual)
P:false,	// menu is PERMANENT (you can only set true if this is LEVEL 1 menu)
S:s_CSSTop	// STYLE Array to use for this menu
},
[		// define items {U:'url',T:'text' ...} look at the Manual for details
{U:'preCreateSample.do',T:'Manage Samples'},
{U:'preCreateAliquot.do',T:'Manage Aliquots'}
]
);

//Search
s_add(
{
N:'search',	// NAME
LV:1,		// LEVEL (look at IMPORTANT NOTES 1 in the Manual)
MinW:130,	// MINIMAL WIDTH
T:138,		// TOP (look at IMPORTANT HOWTOS 6 in the Manual)
L:457,		// LEFT (look at IMPORTANT HOWTOS 6 in the Manual)
P:false,	// menu is PERMANENT (you can only set true if this is LEVEL 1 menu)
S:s_CSSTop	// STYLE Array to use for this menu
},
[		// define items {U:'url',T:'text' ...} look at the Manual for details
{U:'searchWorkflow.jsp',T:'Search Workflow'},
{U:'searchSample.jsp',T:'Search Sample'}
]
);

///////////////////////////////////////////////////////////////////////
//TOOL TIP
///////////////////////////////////////////////////////////////////////

//workflow Search section assayName
s_add(
{N:'workflowSearch_assayName',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Assay Name',SELECTED:true},
{U:'',T:'The Assay name could be wild carded by \'*\'.',NOROLL:true}
]
);
//Assay Type
s_add(
{N:'workflowSearch_assayType',LV:1,W:186,T:'mouseY+10',L:'mouseX+10',P:false,S:s_CSSTop},
[
{U:'',T:'Assay Type',SELECTED:true},
{U:'',T:'The Assay type could be selected from the list.',NOROLL:true}
]
);
//workflow Search section assay Run Date
s_add(
{N:'workflowSearch_assayRunDate',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Assay Run Date',SELECTED:true},
{U:'',T:'The Assay date could be selected using the icon or entered in mm/dd/yyyy format.',ROLL:true}
]
);
//workflow Search section aliquot Id
s_add(
{N:'workflowSearch_aliquotId',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Aliquot Id',SELECTED:true},
{U:'',T:'The Assay name could be wild carded by \'*\'.',NOROLL:true}
]
);
//workflow Search on Masked aliquots
s_add(
{N:'workflowSearch_maskedAliquots',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Include Masked Aliquots',SELECTED:true},
{U:'',T:'Check to search on Masked Aliquots.',NOROLL:true}
]
);
//workflow Search on File names
s_add(
{N:'workflowSearch_fileName',LV:1,W:186,T:'mouseY-50',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Name',SELECTED:true},
{U:'',T:'The File Name could be wild carded by \'*\'. Select whether the file is In or Out.',NOROLL:true}
]
);
//workflow Search File Submission Date
s_add(
{N:'workflowSearch_fileSubmissionDate',LV:1,W:186,T:'mouseY-100',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Submission Date',SELECTED:true},
{U:'',T:'The File Submission date could be selected using the icon or entered in mm/dd/yyyy format.',NOROLL:true}
]
);
//workflow Search section File Type
s_add(
{N:'workflowSearch_fileType',LV:1,W:186,T:'mouseY-100',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Type',SELECTED:true},
{U:'',T:'Available File extension type could be selected from the list .',NOROLL:true}
]
);
//workflow Search section File Submitter
s_add(
{N:'workflowSearch_fileSubmitter',LV:1,W:186,T:'mouseY+20',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Submitter',SELECTED:true},
{U:'',T:'Available File submitter could be selected from the list .',NOROLL:true}
]
);
//workflow Search on Masked Files
s_add(
{N:'workflowSearch_maskedFiles',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Include Masked Files',SELECTED:true},
{U:'',T:'Check to search on Masked Files.',NOROLL:true}
]
);

//////////////////////////////////////
//Sample Search on Masked Files
/////////////////////////////////////
s_add(
{N:'sampleSearch_sampleId',LV:1,W:186,T:'mouseY-70',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Sample ID',SELECTED:true},
{U:'',T:'The Sample ID could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_lotId',LV:1,W:186,T:'mouseY-70',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Lot ID',SELECTED:true},
{U:'',T:'The Lot ID could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_aliquotId',LV:1,W:186,T:'mouseY-70',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Aliquot ID',SELECTED:true},
{U:'',T:'The Aliquot ID could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_sampleType',LV:1,W:186,T:'mouseY-10',L:'mouseX+120',P:false,S:s_CSSTop},
[
{U:'',T:'Sample Type',SELECTED:true},
{U:'',T:'The Sample Type could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_dateAccessioned',LV:1,W:186,T:'mouseY-10',L:'mouseX+15',P:false,S:s_CSSTop},
[
{U:'',T:'Date Accessioned',SELECTED:true},
{U:'',T:'The Date at which the sample was entered into the system. The Date could be selected using the icon or entered in mm/dd/yyyy format.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_sampleSubmitter',LV:1,W:186,T:'mouseY-10',L:'mouseX+20',P:false,S:s_CSSTop},
[
{U:'',T:'Sample Submitter',SELECTED:true},
{U:'',T:'The Name of the user who submitted the Sample.',NOROLL:true}
]
);

<commit_msg>updated reference to create aliquot and create sample<commit_after>// USE WORDWRAP AND MAXIMIZE THE WINDOW TO SEE THIS FILE
// v5

// === 1 === EXTRAS
s_hideTimeout=500;//1000=1 second
s_subShowTimeout=300;//if <=100 the menus will function like SM4.x
s_subMenuOffsetX=4;//pixels (if no subs, leave as you like)
s_subMenuOffsetY=1;
s_keepHighlighted=true;
s_autoSELECTED=false;//make the item linking to the current page SELECTED
s_autoSELECTEDItemsClickable=false;//look at IMPORTANT NOTES 1 in the Manual
s_autoSELECTEDTree=true;//look at IMPORTANT NOTES 1 in the Manual
s_autoSELECTEDTreeItemsClickable=true;//look at IMPORTANT NOTES 1 in the Manual
s_scrollingInterval=30;//scrolling for tall menus
s_rightToLeft=false;
s_hideSELECTsInIE=false;//look at IMPORTANT HOWTOS 7 in the Manual

// === 2 === Default TARGET for all the links
// for navigation to frame, calling functions or
// different target for any link look at
// IMPORTANT HOWTOS 1 NOTES in the Manual
s_target='self';//(newWindow/self/top)

// === 3 === STYLESHEETS- you can define different arrays and then assign
// them to any menu you want with the s_add() function
s_CSSTop=[
'#5C5C5C',	// BorderColorDOM ('top right bottom left' or 'all')
'#5C5C5C',	// BorderColorNS4
1,		// BorderWidth
'#5C5C5C',	// BgColor
1,		// Padding
'#5C5C5C',	// ItemBgColor
'#6A8989',	// ItemOverBgColor
'#FFFFFF',	// ItemFontColor
'#FFFFFF',	// ItemOverFontColor
'verdana,arial,helvetica,sans-serif',	// ItemFontFamily
'10px',		// ItemFontSize (css)
'1',		// ItemFontSize Netscape4 (look at KNOWN BUGS 3 in the Manual)
'bold',		// ItemFontWeight (bold/normal)
'left',		// ItemTextAlign (left/center/right)
3,		// ItemPadding
1,		// ItemSeparatorSize
'#8A8CCC',	// ItemSeparatorColor
'',		// IEfilter (look at Samples\IE4(5.5)Filters dirs)
true,				// UseSubImg
'',		// SubImgSrc
'',	// OverSubImgSrc
7,				// SubImgWidth
7,				// SubImgHeight
5,				// SubImgTop px (from item top)
'#6A8989',			// SELECTED ItemBgColor
'#FFFFFF',			// SELECTED ItemFontColor
'',	// SELECTED SubImgSrc
true,				// UseScrollingForTallMenus
'',	// ScrollingImgTopSrc
'',	// ScrollingImgBottomSrc
68,				// ScrollingImgWidth
12,				// ScrollingImgHeight
'',		// ItemClass (css)
'',		// ItemOverClass (css)
'',		// SELECTED ItemClass (css)
0,		// ItemBorderWidth
'#5C5C5C',	// ItemBorderColor ('top right bottom left' or 'all')
'#6A8989',	// ItemBorderOverColor ('top right bottom left' or 'all')
'#6A8989',	// SELECTED ItemBorderColor ('top right bottom left' or 'all')
0,		// ItemSeparatorSpacing
'',		// ItemSeparatorBgImage
'',		// ItemBgImage
'',		// ItemOnBgImage
''		// SELECTED ItemBgImage
];

// === 4 === MENU DEFINITIONS
//Workflow
s_add(
{
N:'workflow',	// NAME
LV:1,		// LEVEL (look at IMPORTANT NOTES 1 in the Manual)
MinW:130,	// MINIMAL WIDTH
T:138,		// TOP (look at IMPORTANT HOWTOS 6 in the Manual)
L:270,		// LEFT (look at IMPORTANT HOWTOS 6 in the Manual)
P:false,	// menu is PERMANENT (you can only set true if this is LEVEL 1 menu)
S:s_CSSTop	// STYLE Array to use for this menu
},
[		// define items {U:'url',T:'text' ...} look at the Manual for details
{U:'createRun.jsp',T:'Execute Workflow'}
]
);
//administration
s_add(
{
N:'administration',	// NAME
LV:1,		// LEVEL (look at IMPORTANT NOTES 1 in the Manual)
MinW:130,	// MINIMAL WIDTH
T:138,		// TOP (look at IMPORTANT HOWTOS 6 in the Manual)
L:352,		// LEFT (look at IMPORTANT HOWTOS 6 in the Manual)
P:false,	// menu is PERMANENT (you can only set true if this is LEVEL 1 menu)
S:s_CSSTop	// STYLE Array to use for this menu
},
[		// define items {U:'url',T:'text' ...} look at the Manual for details
{U:'initSession.do?forwardPage=createSample',T:'Manage Samples'},
{U:'initSession.do?forwardPage=createAliquot',T:'Manage Aliquots'}
]
);

//Search
s_add(
{
N:'search',	// NAME
LV:1,		// LEVEL (look at IMPORTANT NOTES 1 in the Manual)
MinW:130,	// MINIMAL WIDTH
T:138,		// TOP (look at IMPORTANT HOWTOS 6 in the Manual)
L:457,		// LEFT (look at IMPORTANT HOWTOS 6 in the Manual)
P:false,	// menu is PERMANENT (you can only set true if this is LEVEL 1 menu)
S:s_CSSTop	// STYLE Array to use for this menu
},
[		// define items {U:'url',T:'text' ...} look at the Manual for details
{U:'searchWorkflow.jsp',T:'Search Workflow'},
{U:'searchSample.jsp',T:'Search Sample'}
]
);

///////////////////////////////////////////////////////////////////////
//TOOL TIP
///////////////////////////////////////////////////////////////////////

//workflow Search section assayName
s_add(
{N:'workflowSearch_assayName',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Assay Name',SELECTED:true},
{U:'',T:'The Assay name could be wild carded by \'*\'.',NOROLL:true}
]
);
//Assay Type
s_add(
{N:'workflowSearch_assayType',LV:1,W:186,T:'mouseY+10',L:'mouseX+10',P:false,S:s_CSSTop},
[
{U:'',T:'Assay Type',SELECTED:true},
{U:'',T:'The Assay type could be selected from the list.',NOROLL:true}
]
);
//workflow Search section assay Run Date
s_add(
{N:'workflowSearch_assayRunDate',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Assay Run Date',SELECTED:true},
{U:'',T:'The Assay date could be selected using the icon or entered in mm/dd/yyyy format.',ROLL:true}
]
);
//workflow Search section aliquot Id
s_add(
{N:'workflowSearch_aliquotId',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Aliquot Id',SELECTED:true},
{U:'',T:'The Assay name could be wild carded by \'*\'.',NOROLL:true}
]
);
//workflow Search on Masked aliquots
s_add(
{N:'workflowSearch_maskedAliquots',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Include Masked Aliquots',SELECTED:true},
{U:'',T:'Check to search on Masked Aliquots.',NOROLL:true}
]
);
//workflow Search on File names
s_add(
{N:'workflowSearch_fileName',LV:1,W:186,T:'mouseY-50',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Name',SELECTED:true},
{U:'',T:'The File Name could be wild carded by \'*\'. Select whether the file is In or Out.',NOROLL:true}
]
);
//workflow Search File Submission Date
s_add(
{N:'workflowSearch_fileSubmissionDate',LV:1,W:186,T:'mouseY-100',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Submission Date',SELECTED:true},
{U:'',T:'The File Submission date could be selected using the icon or entered in mm/dd/yyyy format.',NOROLL:true}
]
);
//workflow Search section File Type
s_add(
{N:'workflowSearch_fileType',LV:1,W:186,T:'mouseY-100',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Type',SELECTED:true},
{U:'',T:'Available File extension type could be selected from the list .',NOROLL:true}
]
);
//workflow Search section File Submitter
s_add(
{N:'workflowSearch_fileSubmitter',LV:1,W:186,T:'mouseY+20',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'File Submitter',SELECTED:true},
{U:'',T:'Available File submitter could be selected from the list .',NOROLL:true}
]
);
//workflow Search on Masked Files
s_add(
{N:'workflowSearch_maskedFiles',LV:1,W:186,T:'mouseY-10',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Include Masked Files',SELECTED:true},
{U:'',T:'Check to search on Masked Files.',NOROLL:true}
]
);

//////////////////////////////////////
//Sample Search on Masked Files
/////////////////////////////////////
s_add(
{N:'sampleSearch_sampleId',LV:1,W:186,T:'mouseY-70',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Sample ID',SELECTED:true},
{U:'',T:'The Sample ID could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_lotId',LV:1,W:186,T:'mouseY-70',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Lot ID',SELECTED:true},
{U:'',T:'The Lot ID could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_aliquotId',LV:1,W:186,T:'mouseY-70',L:'mouseX+5',P:false,S:s_CSSTop},
[
{U:'',T:'Aliquot ID',SELECTED:true},
{U:'',T:'The Aliquot ID could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_sampleType',LV:1,W:186,T:'mouseY-10',L:'mouseX+120',P:false,S:s_CSSTop},
[
{U:'',T:'Sample Type',SELECTED:true},
{U:'',T:'The Sample Type could be could be selected from the list.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_dateAccessioned',LV:1,W:186,T:'mouseY-10',L:'mouseX+15',P:false,S:s_CSSTop},
[
{U:'',T:'Date Accessioned',SELECTED:true},
{U:'',T:'The Date at which the sample was entered into the system. The Date could be selected using the icon or entered in mm/dd/yyyy format.',NOROLL:true}
]
);
s_add(
{N:'sampleSearch_sampleSubmitter',LV:1,W:186,T:'mouseY-10',L:'mouseX+20',P:false,S:s_CSSTop},
[
{U:'',T:'Sample Submitter',SELECTED:true},
{U:'',T:'The Name of the user who submitted the Sample.',NOROLL:true}
]
);

<|endoftext|>


<commit_before>/**
 * Basic pattern for packery
 * Copyright 2013-2014 Simplon B.V. - Wichert Akkerman
 */

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery', 'pat-registry', 'pat-parser'], function ($, registry, Parser) {
            return factory($, registry, Parser);
        });
    } else {
        factory(root.jQuery, root.patterns, root.patterns.Parser);
    }
}(this, function($, registry, Parser) {
    var parser = new Parser('redactor');

    parser.add_argument('toolbar-type', 'standard', ['standard', 'fixed', 'air']);
    parser.add_argument('toolbar-external', null);
    parser.add_argument('toolbar-fixed-target', null);

    parser.add_argument('buttons',
        ['html', 'formatting', 'bold', 'italic', 'unordered-list', 'ordered-list', 'image', 'video', 'link', 'horizontal-rule', 'table'],
        ['formatting', 'bold', 'italic', 'unordered-list', 'ordered-list', 'image', 'video', 'link', 'horizontal-rule'], true);

    parser.add_argument('air-buttons', [],
        ['formatting', 'bold', 'italic', 'unordered-list', 'ordered-list', 'image', 'video', 'link', 'horizontal-rule'], true);

    parser.add_argument('allowed-tags', [], [], true);
    parser.add_argument('denied-tags', [], [], true);
    parser.add_argument('fileupload', null);
    parser.add_argument('imageupload', null);
    parser.add_argument('imagegetjson', null);

    var redactor = {
        name: 'redactor',
        trigger: '.pat-redactor',

        init: function($el, opts) {
            var i,
                poptions = parser.parse($el, opts),
                options = {'rangy': true};

            switch (poptions.toolbar.type) {
                case 'air':
                    options.air = true;
                    if (poptions.airButtons.length !==0) {
                        options.airButtons = poptions.airButtons;
                    }
                    break;
                case 'fixed':
                    options.toolbarFixed = true;
                    if (poptions.toolbar['fixed-target']) {
                        options.toolbarFixedTarget = poptions.toolbar['fixed-target'];
                    }
                    break;
                default:
                    break;
            }

            if (poptions.toolbar.external) {
                options.toolbarExternal = poptions.toolbar.external;
            }

            // Remove dashes from button names, per redactor convention
            for (i=0; i< poptions.buttons.length; i++) {
                poptions.buttons[i] = poptions.buttons[i].replace('-', '');
            }

            options.buttons = poptions.buttons;

            if (poptions.allowedTags.length>0) {
                options.allowedTags = poptions.allowedTags;
            } else if (poptions.deniedTags.length>0) {
                options.deniedTags = poptions.deniedTags;
            }

            if (poptions.fileUpload) {
                options.fileUpload = poptions.fileUpload;
            }

            if (poptions.imageupload) {
                options.imageUpload = poptions.imageupload;
            }
            if (poptions.imagegetjson) {
                options.imageGetJson = poptions.imagegetjson;
            }

            $el.redactor(options);
        }
    };

    registry.register(redactor);
    return redactor;
}));

<commit_msg>adding the rangy option only if we are actually in ie8. If it is present in other browsers, redactor will not activate its buttons.<commit_after>/**
 * Basic pattern for packery
 * Copyright 2013-2014 Simplon B.V. - Wichert Akkerman
 */

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery', 'pat-registry', 'pat-parser'], function ($, registry, Parser) {
            return factory($, registry, Parser);
        });
    } else {
        factory(root.jQuery, root.patterns, root.patterns.Parser);
    }
}(this, function($, registry, Parser) {
    var parser = new Parser('redactor');

    parser.add_argument('toolbar-type', 'standard', ['standard', 'fixed', 'air']);
    parser.add_argument('toolbar-external', null);
    parser.add_argument('toolbar-fixed-target', null);

    parser.add_argument('buttons',
        ['html', 'formatting', 'bold', 'italic', 'unordered-list', 'ordered-list', 'image', 'video', 'link', 'horizontal-rule', 'table'],
        ['formatting', 'bold', 'italic', 'unordered-list', 'ordered-list', 'image', 'video', 'link', 'horizontal-rule'], true);

    parser.add_argument('air-buttons', [],
        ['formatting', 'bold', 'italic', 'unordered-list', 'ordered-list', 'image', 'video', 'link', 'horizontal-rule'], true);

    parser.add_argument('allowed-tags', [], [], true);
    parser.add_argument('denied-tags', [], [], true);
    parser.add_argument('fileupload', null);
    parser.add_argument('imageupload', null);
    parser.add_argument('imagegetjson', null);

    var redactor = {
        name: 'redactor',
        trigger: '.pat-redactor',

        init: function($el, opts) {
            var i,
                poptions = parser.parse($el, opts),
                options = {};

            if ($.browser.msie && parseInt($.browser.version, 10) === 8) {
                options.rangy = true;
            }

            switch (poptions.toolbar.type) {
                case 'air':
                    options.air = true;
                    if (poptions.airButtons.length !==0) {
                        options.airButtons = poptions.airButtons;
                    }
                    break;
                case 'fixed':
                    options.toolbarFixed = true;
                    if (poptions.toolbar['fixed-target']) {
                        options.toolbarFixedTarget = poptions.toolbar['fixed-target'];
                    }
                    break;
                default:
                    break;
            }

            if (poptions.toolbar.external) {
                options.toolbarExternal = poptions.toolbar.external;
            }

            // Remove dashes from button names, per redactor convention
            for (i=0; i< poptions.buttons.length; i++) {
                poptions.buttons[i] = poptions.buttons[i].replace('-', '');
            }

            options.buttons = poptions.buttons;

            if (poptions.allowedTags.length>0) {
                options.allowedTags = poptions.allowedTags;
            } else if (poptions.deniedTags.length>0) {
                options.deniedTags = poptions.deniedTags;
            }

            if (poptions.fileUpload) {
                options.fileUpload = poptions.fileUpload;
            }

            if (poptions.imageupload) {
                options.imageUpload = poptions.imageupload;
            }
            if (poptions.imagegetjson) {
                options.imageGetJson = poptions.imagegetjson;
            }

            $el.redactor(options);
        }
    };

    registry.register(redactor);
    return redactor;
}));

<|endoftext|>


<commit_before>//Test code taken from
//https://github.com/heroku-examples/node-ws-test/blob/master/server.js

var WebSocketServer = require('ws').Server,
  MongoClient = require('mongodb').MongoClient,
  MongoServer = require('mongodb').Server,
  fs = require('fs'),
	http = require('http'),
	path = require('path'),
	express = require('express'),
	app = express(),
	port = process.env.PORT || 5000,
  router = express.Router();

MongoClient.connect(process.env.MONGOHQ_URL, function(err, db){
//MongoClient.connect(new MongoServer('localhost', 27017), function(err, db){
  if(err) throw err;
  var collection = db.collection('test_insert');
  collection.insert({a:2}, function(err, docs){
      collection.count(function(err, count){
          console.log(format("count = %s", count));
      });
  });
  collection.find().toArray(function(err, results){
      console.dir(results);
      db.close();
  });
});

router.route('/courses/:filename')

  .get(function(req, res){
    fs.readFile(path.join(process.cwd(),'/data/courses/'+req.params.filename), 'utf8', function(err, data){
      if (err){
        res.send(err);
      } else {
        res.json(JSON.parse(data)); //JSON.parse needed to convert string to JSON object
      }
    });
  });

app.use('/data', router);

app.use(express.static(__dirname + '/public'));

var server = http.createServer(app);
server.listen(port);

//WebSocket stuff...not needed in 1.0
/*var wss = new WebSocketServer({server: server});
wss.on('connection', function(ws){
		var id = setInterval(function(){
				ws.send(JSON.stringify(new Date()), function(){});
		}, 100);

		ws.on('close', function(){
				clearInterval(id);
		});
});*/<commit_msg>Removed mongo server<commit_after>//Test code taken from
//https://github.com/heroku-examples/node-ws-test/blob/master/server.js

var WebSocketServer = require('ws').Server,
  MongoClient = require('mongodb').MongoClient,
  //MongoServer = require('mongodb').Server,
  fs = require('fs'),
	http = require('http'),
	path = require('path'),
	express = require('express'),
	app = express(),
	port = process.env.PORT || 5000,
  router = express.Router();

MongoClient.connect(process.env.MONGOHQ_URL, function(err, db){
//MongoClient.connect(new MongoServer('localhost', 27017), function(err, db){
  if(err) throw err;
  var collection = db.collection('test_insert');
  collection.insert({a:2}, function(err, docs){
      collection.count(function(err, count){
          console.log(format("count = %s", count));
      });
  });
  collection.find().toArray(function(err, results){
      console.dir(results);
      db.close();
  });
});

router.route('/courses/:filename')

  .get(function(req, res){
    fs.readFile(path.join(process.cwd(),'/data/courses/'+req.params.filename), 'utf8', function(err, data){
      if (err){
        res.send(err);
      } else {
        res.json(JSON.parse(data)); //JSON.parse needed to convert string to JSON object
      }
    });
  });

app.use('/data', router);

app.use(express.static(__dirname + '/public'));

var server = http.createServer(app);
server.listen(port);

//WebSocket stuff...not needed in 1.0
/*var wss = new WebSocketServer({server: server});
wss.on('connection', function(ws){
		var id = setInterval(function(){
				ws.send(JSON.stringify(new Date()), function(){});
		}, 100);

		ws.on('close', function(){
				clearInterval(id);
		});
});*/<|endoftext|>


<commit_before>

const testProgram = require('@grancalavera/test-program')
    , path = require('path')
    , bin = path.resolve(__dirname, '../bin/prufer')
    , prufer = testProgram(bin)
    , test = require('tap').test

test('prufer bin', t => {

  t.plan(11)

  prufer('--help', {}, function(err, code, stdout, stderr) {
    t.match(stdout, /Usage\: prufer/, 'Should display help message')
  })

  prufer('-h', {}, (err, code, stdout, stderr) => {
    t.match(stdout, /Usage\: prufer/, 'Should display help message')
  })

  prufer(['foo'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^Unknown command "foo"/
    , 'Should fail with unknown commands'
    )
  })

  prufer(['random-tree', '0'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^randomTree requires at least 3 nodes/
    , 'must require at least 3 nodes'
    )
  })

  prufer(['random-tree', '1'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^randomTree requires at least 3 nodes/
    , 'must require at least 3 nodes'
    )
  })

  prufer(['random-tree', '2'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^randomTree requires at least 3 nodes/
    , 'must require at least 3 nodes'
    )
  })

  prufer(['random-tree', '3'], {}, (err, code, stdout, stderr) => {
    const tree = JSON.parse(stdout)
    t.ok(Array.isArray(tree), 'should return a tree')
  })

  prufer(['random-code', '0'], {}, (err, code, stdout, stderr) => {
    const seq = JSON.parse(stdout)
    t.same(seq, [], 'should produce an empty code')
  })

  prufer(['random-code', '10'], {}, (err, code, stdout, stderr) => {
    const seq = JSON.parse(stdout)
    t.same(seq.length, 10, 'should pruduce a code with known length')
  })

  prufer(['tree', '[3,3,3,4]'], {}, (err, code, stdout, stderr) => {
    const expected = [[3, 0], [3,1], [3, 2], [4, 3], [4, 5]]
        , actual = JSON.parse(stdout)
    t.same(actual, expected, 'should produce a known tree')
  })

  prufer(['tree', '[ 3 ,3  ,3  ,4   ]'], {}, (err, code, stdout, stderr) => {
    const expected = [[3, 0], [3,1], [3, 2], [4, 3], [4, 5]]
        , actual = JSON.parse(stdout)
    t.same(actual, expected, 'whitespace should not matter')
  })
})
<commit_msg>Cleanup<commit_after>const testProgram = require('@grancalavera/test-program')
    , path = require('path')
    , bin = path.resolve(__dirname, '../bin/prufer')
    , prufer = testProgram(bin)
    , test = require('tap').test

test('prufer bin', t => {

  t.plan(11)

  prufer('--help', {}, function(err, code, stdout, stderr) {
    t.match(stdout, /Usage\: prufer/, 'Should display help message')
  })

  prufer('-h', {}, (err, code, stdout, stderr) => {
    t.match(stdout, /Usage\: prufer/, 'Should display help message')
  })

  prufer(['foo'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^Unknown command "foo"/
    , 'Should fail with unknown commands'
    )
  })

  prufer(['random-tree', '0'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^randomTree requires at least 3 nodes/
    , 'must require at least 3 nodes'
    )
  })

  prufer(['random-tree', '1'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^randomTree requires at least 3 nodes/
    , 'must require at least 3 nodes'
    )
  })

  prufer(['random-tree', '2'], {}, (err, code, stdout, stderr) => {
    t.match(
      stderr
    , /^randomTree requires at least 3 nodes/
    , 'must require at least 3 nodes'
    )
  })

  prufer(['random-tree', '3'], {}, (err, code, stdout, stderr) => {
    const tree = JSON.parse(stdout)
    t.ok(Array.isArray(tree), 'should return a tree')
  })

  prufer(['random-code', '0'], {}, (err, code, stdout, stderr) => {
    const seq = JSON.parse(stdout)
    t.same(seq, [], 'should produce an empty code')
  })

  prufer(['random-code', '10'], {}, (err, code, stdout, stderr) => {
    const seq = JSON.parse(stdout)
    t.same(seq.length, 10, 'should pruduce a code with known length')
  })

  prufer(['tree', '[3,3,3,4]'], {}, (err, code, stdout, stderr) => {
    const expected = [[3, 0], [3,1], [3, 2], [4, 3], [4, 5]]
        , actual = JSON.parse(stdout)
    t.same(actual, expected, 'should produce a known tree')
  })

  prufer(['tree', '[ 3 ,3  ,3  ,4   ]'], {}, (err, code, stdout, stderr) => {
    const expected = [[3, 0], [3,1], [3, 2], [4, 3], [4, 5]]
        , actual = JSON.parse(stdout)
    t.same(actual, expected, 'whitespace should not matter')
  })
})
<|endoftext|>


<commit_before><commit_msg>clean up codes.<commit_after><|endoftext|>


<commit_before>/**
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

'use strict';

import * as utils from './utils'
import {addEventListener as nativeAddEventListener,
  removeEventListener as nativeRemoveEventListener} from './native-methods'

// https://github.com/w3c/webcomponents/issues/513#issuecomment-224183937
let alwaysComposed = {
  'focusin': true,
  'focusout': true,
  'click': true,
  'dblclick': true,
  'mousedown': true,
  'mouseenter': true,
  'mouseleave': true,
  'mousemove': true,
  'mouseout': true,
  'mouseover': true,
  'mouseup': true,
  'wheel': true,
  'beforeinput': true,
  'input': true,
  'keydown': true,
  'keyup': true,
  'compositionstart': true,
  'compositionupdate': true,
  'compositionend': true,
  'touchstart': true,
  'touchend': true,
  'touchmove': true,
  'touchcancel': true,
  'pointerover': true,
  'pointerenter': true,
  'pointerdown': true,
  'pointermove': true,
  'pointerup': true,
  'pointercancel': true,
  'pointerout': true,
  'pointerleave': true,
  'gotpointercapture': true,
  'lostpointercapture': true,
  'dragstart': true,
  'drag': true,
  'dragenter': true,
  'dragleave': true,
  'dragover': true,
  'drop': true,
  'dragend': true,
  'DOMActivate': true,
  'DOMFocusIn': true,
  'DOMFocusOut': true,
  'keypress': true
};

function pathComposer(startNode, composed) {
  let composedPath = [];
  let current = startNode;
  let startRoot = startNode === window ? window : startNode.getRootNode();
  while (current) {
    composedPath.push(current);
    if (current.assignedSlot) {
      current = current.assignedSlot;
    } else if (current.nodeType === Node.DOCUMENT_FRAGMENT_NODE && current.host && (composed || current !== startRoot)) {
      current = current.host;
    } else {
      current = current.parentNode;
    }
  }
  // event composedPath includes window when startNode's ownerRoot is document
  if (composedPath[composedPath.length - 1] === document) {
    composedPath.push(window);
  }
  return composedPath;
}

function retarget(refNode, path) {
  if (!utils.isShadyRoot) {
    return refNode;
  }
  // If ANCESTOR's root is not a shadow root or ANCESTOR's root is BASE's
  // shadow-including inclusive ancestor, return ANCESTOR.
  let refNodePath = pathComposer(refNode, true);
  let p$ = path;
  for (let i=0, ancestor, lastRoot, root, rootIdx; i < p$.length; i++) {
    ancestor = p$[i];
    root = ancestor === window ? window : ancestor.getRootNode();
    if (root !== lastRoot) {
      rootIdx = refNodePath.indexOf(root);
      lastRoot = root;
    }
    if (!utils.isShadyRoot(root) || rootIdx > -1) {
      return ancestor;
    }
  }
}

let eventMixin = {

  /**
   * @this {Event}
   */
  get composed() {
    // isTrusted may not exist in this browser, so just check if isTrusted is explicitly false
    if (this.isTrusted !== false && this.__composed === undefined) {
      this.__composed = alwaysComposed[this.type];
    }
    return this.__composed || false;
  },

  /**
   * @this {Event}
   */
  composedPath() {
    if (!this.__composedPath) {
      this.__composedPath = pathComposer(this['__target'], this.composed);
    }
    return this.__composedPath;
  },

  /**
   * @this {Event}
   */
  get target() {
    return retarget(this.currentTarget, this.composedPath());
  },

  // http://w3c.github.io/webcomponents/spec/shadow/#event-relatedtarget-retargeting
  /**
   * @this {Event}
   */
  get relatedTarget() {
    if (!this.__relatedTarget) {
      return null;
    }
    if (!this.__relatedTargetComposedPath) {
      this.__relatedTargetComposedPath = pathComposer(this.__relatedTarget, true);
    }
    // find the deepest node in relatedTarget composed path that is in the same root with the currentTarget
    return retarget(this.currentTarget, this.__relatedTargetComposedPath);
  },
  /**
   * @this {Event}
   */
  stopPropagation() {
    Event.prototype.stopPropagation.call(this);
    this.__propagationStopped = true;
  },
  /**
   * @this {Event}
   */
  stopImmediatePropagation() {
    Event.prototype.stopImmediatePropagation.call(this);
    this.__immediatePropagationStopped = true;
    this.__propagationStopped = true;
  }

};

function mixinComposedFlag(Base) {
  // NOTE: avoiding use of `class` here so that transpiled output does not
  // try to do `Base.call` with a dom construtor.
  let klazz = function(type, options) {
    let event = new Base(type, options);
    event.__composed = options && Boolean(options['composed']);
    return event;
  }
  // put constructor properties on subclass
  utils.mixin(klazz, Base);
  klazz.prototype = Base.prototype;
  return klazz;
}

let nonBubblingEventsToRetarget = {
  'focus': true,
  'blur': true
};

function fireHandlers(event, node, phase) {
  let hs = node.__handlers && node.__handlers[event.type] &&
    node.__handlers[event.type][phase];
  if (hs) {
    for (let i = 0, fn; (fn = hs[i]); i++) {
      fn.call(node, event);
      if (event.__immediatePropagationStopped) {
        return;
      }
    }
  }
}

function retargetNonBubblingEvent(e) {
  let path = e.composedPath();
  let node;
  // override `currentTarget` to let patched `target` calculate correctly
  Object.defineProperty(e, 'currentTarget', {
    get: function() {
      return node;
    },
    configurable: true
  });
  for (let i = path.length - 1; i >= 0; i--) {
    node = path[i];
    // capture phase fires all capture handlers
    fireHandlers(e, node, 'capture');
    if (e.__propagationStopped) {
      return;
    }
  }

  // set the event phase to `AT_TARGET` as in spec
  Object.defineProperty(e, 'eventPhase', {value: Event.AT_TARGET});

  // the event only needs to be fired when owner roots change when iterating the event path
  // keep track of the last seen owner root
  let lastFiredRoot;
  for (let i = 0; i < path.length; i++) {
    node = path[i];
    if (i === 0 || (node.shadowRoot && node.shadowRoot === lastFiredRoot)) {
      fireHandlers(e, node, 'bubble');
      // don't bother with window, it doesn't have `getRootNode` and will be last in the path anyway
      if (node !== window) {
        lastFiredRoot = node.getRootNode();
      }
      if (e.__propagationStopped) {
        return;
      }
    }
  }
}

/**
 * @this {Event}
 */
export function addEventListener(type, fn, optionsOrCapture) {
  if (!fn) {
    return;
  }

  // The callback `fn` might be used for multiple nodes/events. Since we generate
  // a wrapper function, we need to keep track of it when we remove the listener.
  // It's more efficient to store the node/type/options information as Array in
  // `fn` itself rather than the node (we assume that the same callback is used
  // for few nodes at most, whereas a node will likely have many event listeners).
  // NOTE(valdrin) invoking external functions is costly, inline has better perf.
  let capture, once, passive;
  if (typeof optionsOrCapture === 'object') {
    capture = Boolean(optionsOrCapture.capture);
    once = Boolean(optionsOrCapture.once);
    passive = Boolean(optionsOrCapture.passive);
  } else {
    capture = Boolean(optionsOrCapture);
    once = false;
    passive = false;
  }
  if (fn.__eventWrappers) {
    // Stop if the wrapper function has already been created.
    for (let i = 0; i < fn.__eventWrappers.length; i++) {
      if (fn.__eventWrappers[i].node === this &&
          fn.__eventWrappers[i].type === type &&
          fn.__eventWrappers[i].capture === capture &&
          fn.__eventWrappers[i].once === once &&
          fn.__eventWrappers[i].passive === passive) {
        return;
      }
    }
  } else {
    fn.__eventWrappers = [];
  }

  /**
   * @this {HTMLElement}
   */
  const wrapperFn = function(e) {
    // Support `once` option.
    if (once) {
      this.removeEventListener(type, fn, optionsOrCapture);
    }
    if (!e['__target']) {
      patchEvent(e);
    }
    // There are two critera that should stop events from firing on this node
    // 1. the event is not composed and the current node is not in the same root as the target
    // 2. when bubbling, if after retargeting, relatedTarget and target point to the same node
    if (e.composed || e.composedPath().indexOf(this) > -1) {
      if (e.eventPhase === Event.BUBBLING_PHASE) {
        if (e.target === e.relatedTarget) {
          e.stopImmediatePropagation();
          return;
        }
      }
      return fn(e);
    }
  };
  // Store the wrapper information.
  fn.__eventWrappers.push({
    node: this,
    type: type,
    capture: capture,
    once: once,
    passive: passive,
    wrapperFn: wrapperFn
  });

  if (nonBubblingEventsToRetarget[type]) {
    this.__handlers = this.__handlers || {};
    this.__handlers[type] = this.__handlers[type] ||
      {'capture': [], 'bubble': []};
    this.__handlers[type][capture ? 'capture' : 'bubble'].push(wrapperFn);
  } else {
    nativeAddEventListener.call(this, type, wrapperFn, optionsOrCapture);
  }
}

/**
 * @this {Event}
 */
export function removeEventListener(type, fn, optionsOrCapture) {
  if (!fn) {
    return;
  }

  // NOTE(valdrin) invoking external functions is costly, inline has better perf.
  let capture, once, passive;
  if (typeof optionsOrCapture === 'object') {
    capture = Boolean(optionsOrCapture.capture);
    once = Boolean(optionsOrCapture.once);
    passive = Boolean(optionsOrCapture.passive);
  } else {
    capture = Boolean(optionsOrCapture);
    once = false;
    passive = false;
  }
  // Search the wrapped function.
  let wrapperFn = undefined;
  if (fn.__eventWrappers) {
    for (let i = 0; i < fn.__eventWrappers.length; i++) {
      if (fn.__eventWrappers[i].node === this &&
          fn.__eventWrappers[i].type === type &&
          fn.__eventWrappers[i].capture === capture &&
          fn.__eventWrappers[i].once === once &&
          fn.__eventWrappers[i].passive === passive) {
        wrapperFn = fn.__eventWrappers.splice(i, 1)[0].wrapperFn;
        // Cleanup.
        if (!fn.__eventWrappers.length) {
          fn.__eventWrappers = undefined;
        }
        break;
      }
    }
  }

  nativeRemoveEventListener.call(this, type, wrapperFn || fn, optionsOrCapture);
  if (wrapperFn && nonBubblingEventsToRetarget[type] &&
      this.__handlers && this.__handlers[type]) {
    const arr = this.__handlers[type][capture ? 'capture' : 'bubble'];
    const idx = arr.indexOf(wrapperFn);
    if (idx > -1) {
      arr.splice(idx, 1);
    }
  }
}

function activateFocusEventOverrides() {
  for (let ev in nonBubblingEventsToRetarget) {
    window.addEventListener(ev, function(e) {
      if (!e['__target']) {
        patchEvent(e);
        retargetNonBubblingEvent(e);
        e.stopImmediatePropagation();
      }
    }, true);
  }
}

function patchEvent(event) {
  event['__target'] = event.target;
  event.__relatedTarget = event.relatedTarget;
  // patch event prototype if we can
  if (utils.settings.hasDescriptors) {
    utils.patchPrototype(event, eventMixin);
  // and fallback to patching instance
  } else {
    utils.extend(event, eventMixin);
  }
}

let PatchedEvent = mixinComposedFlag(window.Event);
let PatchedCustomEvent = mixinComposedFlag(window.CustomEvent);
let PatchedMouseEvent = mixinComposedFlag(window.MouseEvent);

export function patchEvents() {
  window.Event = PatchedEvent;
  window.CustomEvent = PatchedCustomEvent;
  window.MouseEvent = PatchedMouseEvent;
  activateFocusEventOverrides();
}
<commit_msg>Preserve scope of event callbacks<commit_after>/**
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

'use strict';

import * as utils from './utils'
import {addEventListener as nativeAddEventListener,
  removeEventListener as nativeRemoveEventListener} from './native-methods'

// https://github.com/w3c/webcomponents/issues/513#issuecomment-224183937
let alwaysComposed = {
  'focusin': true,
  'focusout': true,
  'click': true,
  'dblclick': true,
  'mousedown': true,
  'mouseenter': true,
  'mouseleave': true,
  'mousemove': true,
  'mouseout': true,
  'mouseover': true,
  'mouseup': true,
  'wheel': true,
  'beforeinput': true,
  'input': true,
  'keydown': true,
  'keyup': true,
  'compositionstart': true,
  'compositionupdate': true,
  'compositionend': true,
  'touchstart': true,
  'touchend': true,
  'touchmove': true,
  'touchcancel': true,
  'pointerover': true,
  'pointerenter': true,
  'pointerdown': true,
  'pointermove': true,
  'pointerup': true,
  'pointercancel': true,
  'pointerout': true,
  'pointerleave': true,
  'gotpointercapture': true,
  'lostpointercapture': true,
  'dragstart': true,
  'drag': true,
  'dragenter': true,
  'dragleave': true,
  'dragover': true,
  'drop': true,
  'dragend': true,
  'DOMActivate': true,
  'DOMFocusIn': true,
  'DOMFocusOut': true,
  'keypress': true
};

function pathComposer(startNode, composed) {
  let composedPath = [];
  let current = startNode;
  let startRoot = startNode === window ? window : startNode.getRootNode();
  while (current) {
    composedPath.push(current);
    if (current.assignedSlot) {
      current = current.assignedSlot;
    } else if (current.nodeType === Node.DOCUMENT_FRAGMENT_NODE && current.host && (composed || current !== startRoot)) {
      current = current.host;
    } else {
      current = current.parentNode;
    }
  }
  // event composedPath includes window when startNode's ownerRoot is document
  if (composedPath[composedPath.length - 1] === document) {
    composedPath.push(window);
  }
  return composedPath;
}

function retarget(refNode, path) {
  if (!utils.isShadyRoot) {
    return refNode;
  }
  // If ANCESTOR's root is not a shadow root or ANCESTOR's root is BASE's
  // shadow-including inclusive ancestor, return ANCESTOR.
  let refNodePath = pathComposer(refNode, true);
  let p$ = path;
  for (let i=0, ancestor, lastRoot, root, rootIdx; i < p$.length; i++) {
    ancestor = p$[i];
    root = ancestor === window ? window : ancestor.getRootNode();
    if (root !== lastRoot) {
      rootIdx = refNodePath.indexOf(root);
      lastRoot = root;
    }
    if (!utils.isShadyRoot(root) || rootIdx > -1) {
      return ancestor;
    }
  }
}

let eventMixin = {

  /**
   * @this {Event}
   */
  get composed() {
    // isTrusted may not exist in this browser, so just check if isTrusted is explicitly false
    if (this.isTrusted !== false && this.__composed === undefined) {
      this.__composed = alwaysComposed[this.type];
    }
    return this.__composed || false;
  },

  /**
   * @this {Event}
   */
  composedPath() {
    if (!this.__composedPath) {
      this.__composedPath = pathComposer(this['__target'], this.composed);
    }
    return this.__composedPath;
  },

  /**
   * @this {Event}
   */
  get target() {
    return retarget(this.currentTarget, this.composedPath());
  },

  // http://w3c.github.io/webcomponents/spec/shadow/#event-relatedtarget-retargeting
  /**
   * @this {Event}
   */
  get relatedTarget() {
    if (!this.__relatedTarget) {
      return null;
    }
    if (!this.__relatedTargetComposedPath) {
      this.__relatedTargetComposedPath = pathComposer(this.__relatedTarget, true);
    }
    // find the deepest node in relatedTarget composed path that is in the same root with the currentTarget
    return retarget(this.currentTarget, this.__relatedTargetComposedPath);
  },
  /**
   * @this {Event}
   */
  stopPropagation() {
    Event.prototype.stopPropagation.call(this);
    this.__propagationStopped = true;
  },
  /**
   * @this {Event}
   */
  stopImmediatePropagation() {
    Event.prototype.stopImmediatePropagation.call(this);
    this.__immediatePropagationStopped = true;
    this.__propagationStopped = true;
  }

};

function mixinComposedFlag(Base) {
  // NOTE: avoiding use of `class` here so that transpiled output does not
  // try to do `Base.call` with a dom construtor.
  let klazz = function(type, options) {
    let event = new Base(type, options);
    event.__composed = options && Boolean(options['composed']);
    return event;
  }
  // put constructor properties on subclass
  utils.mixin(klazz, Base);
  klazz.prototype = Base.prototype;
  return klazz;
}

let nonBubblingEventsToRetarget = {
  'focus': true,
  'blur': true
};

function fireHandlers(event, node, phase) {
  let hs = node.__handlers && node.__handlers[event.type] &&
    node.__handlers[event.type][phase];
  if (hs) {
    for (let i = 0, fn; (fn = hs[i]); i++) {
      fn.call(node, event);
      if (event.__immediatePropagationStopped) {
        return;
      }
    }
  }
}

function retargetNonBubblingEvent(e) {
  let path = e.composedPath();
  let node;
  // override `currentTarget` to let patched `target` calculate correctly
  Object.defineProperty(e, 'currentTarget', {
    get: function() {
      return node;
    },
    configurable: true
  });
  for (let i = path.length - 1; i >= 0; i--) {
    node = path[i];
    // capture phase fires all capture handlers
    fireHandlers(e, node, 'capture');
    if (e.__propagationStopped) {
      return;
    }
  }

  // set the event phase to `AT_TARGET` as in spec
  Object.defineProperty(e, 'eventPhase', {value: Event.AT_TARGET});

  // the event only needs to be fired when owner roots change when iterating the event path
  // keep track of the last seen owner root
  let lastFiredRoot;
  for (let i = 0; i < path.length; i++) {
    node = path[i];
    if (i === 0 || (node.shadowRoot && node.shadowRoot === lastFiredRoot)) {
      fireHandlers(e, node, 'bubble');
      // don't bother with window, it doesn't have `getRootNode` and will be last in the path anyway
      if (node !== window) {
        lastFiredRoot = node.getRootNode();
      }
      if (e.__propagationStopped) {
        return;
      }
    }
  }
}

/**
 * @this {Event}
 */
export function addEventListener(type, fn, optionsOrCapture) {
  if (!fn) {
    return;
  }

  // The callback `fn` might be used for multiple nodes/events. Since we generate
  // a wrapper function, we need to keep track of it when we remove the listener.
  // It's more efficient to store the node/type/options information as Array in
  // `fn` itself rather than the node (we assume that the same callback is used
  // for few nodes at most, whereas a node will likely have many event listeners).
  // NOTE(valdrin) invoking external functions is costly, inline has better perf.
  let capture, once, passive;
  if (typeof optionsOrCapture === 'object') {
    capture = Boolean(optionsOrCapture.capture);
    once = Boolean(optionsOrCapture.once);
    passive = Boolean(optionsOrCapture.passive);
  } else {
    capture = Boolean(optionsOrCapture);
    once = false;
    passive = false;
  }
  if (fn.__eventWrappers) {
    // Stop if the wrapper function has already been created.
    for (let i = 0; i < fn.__eventWrappers.length; i++) {
      if (fn.__eventWrappers[i].node === this &&
          fn.__eventWrappers[i].type === type &&
          fn.__eventWrappers[i].capture === capture &&
          fn.__eventWrappers[i].once === once &&
          fn.__eventWrappers[i].passive === passive) {
        return;
      }
    }
  } else {
    fn.__eventWrappers = [];
  }

  /**
   * @this {HTMLElement}
   */
  const wrapperFn = function(e) {
    // Support `once` option.
    if (once) {
      this.removeEventListener(type, fn, optionsOrCapture);
    }
    if (!e['__target']) {
      patchEvent(e);
    }
    // There are two critera that should stop events from firing on this node
    // 1. the event is not composed and the current node is not in the same root as the target
    // 2. when bubbling, if after retargeting, relatedTarget and target point to the same node
    if (e.composed || e.composedPath().indexOf(this) > -1) {
      if (e.eventPhase === Event.BUBBLING_PHASE) {
        if (e.target === e.relatedTarget) {
          e.stopImmediatePropagation();
          return;
        }
      }
      return fn.call(this, e);
    }
  };
  // Store the wrapper information.
  fn.__eventWrappers.push({
    node: this,
    type: type,
    capture: capture,
    once: once,
    passive: passive,
    wrapperFn: wrapperFn
  });

  if (nonBubblingEventsToRetarget[type]) {
    this.__handlers = this.__handlers || {};
    this.__handlers[type] = this.__handlers[type] ||
      {'capture': [], 'bubble': []};
    this.__handlers[type][capture ? 'capture' : 'bubble'].push(wrapperFn);
  } else {
    nativeAddEventListener.call(this, type, wrapperFn, optionsOrCapture);
  }
}

/**
 * @this {Event}
 */
export function removeEventListener(type, fn, optionsOrCapture) {
  if (!fn) {
    return;
  }

  // NOTE(valdrin) invoking external functions is costly, inline has better perf.
  let capture, once, passive;
  if (typeof optionsOrCapture === 'object') {
    capture = Boolean(optionsOrCapture.capture);
    once = Boolean(optionsOrCapture.once);
    passive = Boolean(optionsOrCapture.passive);
  } else {
    capture = Boolean(optionsOrCapture);
    once = false;
    passive = false;
  }
  // Search the wrapped function.
  let wrapperFn = undefined;
  if (fn.__eventWrappers) {
    for (let i = 0; i < fn.__eventWrappers.length; i++) {
      if (fn.__eventWrappers[i].node === this &&
          fn.__eventWrappers[i].type === type &&
          fn.__eventWrappers[i].capture === capture &&
          fn.__eventWrappers[i].once === once &&
          fn.__eventWrappers[i].passive === passive) {
        wrapperFn = fn.__eventWrappers.splice(i, 1)[0].wrapperFn;
        // Cleanup.
        if (!fn.__eventWrappers.length) {
          fn.__eventWrappers = undefined;
        }
        break;
      }
    }
  }

  nativeRemoveEventListener.call(this, type, wrapperFn || fn, optionsOrCapture);
  if (wrapperFn && nonBubblingEventsToRetarget[type] &&
      this.__handlers && this.__handlers[type]) {
    const arr = this.__handlers[type][capture ? 'capture' : 'bubble'];
    const idx = arr.indexOf(wrapperFn);
    if (idx > -1) {
      arr.splice(idx, 1);
    }
  }
}

function activateFocusEventOverrides() {
  for (let ev in nonBubblingEventsToRetarget) {
    window.addEventListener(ev, function(e) {
      if (!e['__target']) {
        patchEvent(e);
        retargetNonBubblingEvent(e);
        e.stopImmediatePropagation();
      }
    }, true);
  }
}

function patchEvent(event) {
  event['__target'] = event.target;
  event.__relatedTarget = event.relatedTarget;
  // patch event prototype if we can
  if (utils.settings.hasDescriptors) {
    utils.patchPrototype(event, eventMixin);
  // and fallback to patching instance
  } else {
    utils.extend(event, eventMixin);
  }
}

let PatchedEvent = mixinComposedFlag(window.Event);
let PatchedCustomEvent = mixinComposedFlag(window.CustomEvent);
let PatchedMouseEvent = mixinComposedFlag(window.MouseEvent);

export function patchEvents() {
  window.Event = PatchedEvent;
  window.CustomEvent = PatchedCustomEvent;
  window.MouseEvent = PatchedMouseEvent;
  activateFocusEventOverrides();
}
<|endoftext|>