<commit_before>seedrandom = require("seedrandom")

isType = (type) ->
    (arg) -> Object::toString.call(arg) == "[object #{ type }]"

isFunc = isType("Function")

isObject = isType("Object")

randomBoundedFloat = (prng, min = 0, max = 1) ->
    spread = max - min
    prng() * spread + min

randomBoundedInteger = (prng, min = 0, max = 1) ->
    spread = 1 + max - min
    Math.floor(prng() * spread) + min

randomColor = (prng) ->
    byte = kind: "integer", min: 0, max: 255, prng: prng
    mutator = (bytes) ->
        [red, green, blue] = bytes
        { red, green, blue }

    new Stochator(byte, byte, byte, mutator).next

randomNormallyDistributedFloat = (prng, mean, stdev, min, max) ->
    seed = randomBoundedFloat(prng)
    float = inverseNormalCumulativeDistribution(seed) * stdev + mean
    if min? and max?
        Math.min(max, Math.max(min, float))
    else
        float

randomCharacter = (prng, lowercase) ->
    [min, max] = if lowercase then [97, 122] else [65, 90]
    mutator = (charCode) -> String.fromCharCode(charCode)
    new Stochator({ kind: "integer", min, max, prng }, mutator).next

randomSetMember = (prng, set) ->
    max = set.length - 1
    set.get(randomBoundedInteger(prng, 0, max))

randomSetMemberWithoutReplacement = (prng, set) ->
    return undefined unless set.get(0)
    set.length -= 1
    set.pop(randomBoundedInteger(prng, 0, set.length))

randomWeightedSetMember = (prng, set, weights) ->
    [member, weightSum, float] = [undefined, 0, randomBoundedFloat(prng)]
    set.each((value, index) ->
        return if member
        weight = weights.get(index)
        if float <= weightSum + weight and float >= weightSum
            member = value
        weightSum += weight
    )

    member

inverseNormalCumulativeDistribution = (probability) ->
    high = probability > 0.97575
    low = probability < 0.02425

    if low or high
        numCoefficients = new Set([
            -7.784894002430293e-3, -3.223964580411365e-1, -2.400758277161838,
            -2.549732539343734, 4.374664141464968
        ])
        denomCoeffcients = new Set([
            7.784695709041462e-3, 3.224671290700398e-1,
            2.445134137142996, 3.754408661907416
        ])

        [numMaxExponent, denomMaxExponent] = [5, 4]
        coefficient = if low then 1 else -1
        base = Math.sqrt(
            -2 * Math.log(if low then probability else 1 - probability)
        )
    else
        numCoefficients = new Set([
            -3.969683028665376e1, 2.209460984245205e2, -2.759285104469687e2,
            1.383577518672690e2, -3.066479806614716e1, 2.506628277459239
        ])
        denomCoeffcients = new Set([
            -5.447609879822406e1, 1.615858368580409e2, -1.556989798598866e2,
            6.680131188771972e1, -1.328068155288572e1
        ])

        [numMaxExponent, denomMaxExponent] = [5, 5]
        coefficient = probability - 0.5
        base = Math.pow(coefficient, 2)

    mapMaxExp = (maxExp) ->
        (value, index) -> value * Math.pow(base, maxExp - index)

    numerator = numCoefficients.map(mapMaxExp(numMaxExponent)).sum()
    denominator = denomCoeffcients.map(mapMaxExp(denomMaxExponent)).sum() + 1

    coefficient * numerator / denominator

shuffleSet = (prng, set) ->
    values = set.copy()
    for index in [values.length - 1...0]
        randomIndex = randomBoundedInteger(prng, 0, index)

        tmp = values[index]
        values[index] = values[randomIndex]
        values[randomIndex] = tmp

    values

floatGenerator = (prng, min, max, mean, stdev) ->
    if mean and stdev
        -> randomNormallyDistributedFloat(prng, mean, stdev, min, max)
    else
        -> randomBoundedFloat(prng, min, max)

integerGenerator = (prng, min = 0, max = 1) ->
    -> randomBoundedInteger(prng, min, max)

setGenerator = (prng, values, replacement = true, shuffle = false, weights = null) ->
    if not values or not values.length
        throw Error("Must provide a 'values' array for a set generator.")

    set = new Set(values)
    if shuffle
        -> shuffleSet(prng, set)
    else if replacement
        if weights
            weightsSet = new Set(weights)
            -> randomWeightedSetMember(prng, set, weightsSet)
        else
            -> randomSetMember(prng, set)
    else
        -> randomSetMemberWithoutReplacement(prng, set)

createGenerator = (config) ->
    kind = config.kind or "float"

    defaultPrng = if config.seed then seedrandom else Math.random
    basePrng = config.prng or defaultPrng
    prng = if config.seed then basePrng(config.seed) else basePrng

    generator = switch kind
        when "float"
            { min, max, mean, stdev } = config
            floatGenerator(prng, min, max, mean, stdev)
        when "integer"
            integerGenerator(prng, config.min, config.max)
        when "set"
            { values, replacement, shuffle, weights } = config
            setGenerator(prng, values, replacement, shuffle, weights)
        when "color", "rgb" then randomColor(prng)
        when "a-z", "A-Z" then randomCharacter(prng, kind is "a-z")
    if not generator
        throw Error("#{ kind } not a recognized kind.")
    else
        generator

getNextValueGenerator = (configs) ->
    configs[0] ?= {}
    generators = (createGenerator(config) for config in configs)
    if generators.length is 1
        -> generators[0]()
    else
        -> (generator() for generator in generators)

class Stochator

    VERSION = "0.4"

    constructor: (configs..., mutator=null, name="next") ->
        # If the last arg is an object, all args are config args.
        # If the penultimate arg is an object, check whether the last arg
        # is a string (hence, the name) or a function (hence, the mutator).
        if isObject(name)
            configs[configs.length..configs.length + 2] = [mutator, name]
            [mutator, name] = [null, "next"]
        else if isObject(mutator)
            configs[configs.length] = mutator
            [mutator, name] = if isFunc(name)
                [name, "next"]
            else
                [null, name]

        # If the mutator is provided, override the default identity func.
        if mutator
            @mutate = (nextValue) -> mutator(nextValue, @getValue())

        # Transform the configs to a func to get the next value.
        getNext = getNextValueGenerator(configs)

        # Assign `name` to the next mutated value(s), after `times` iterations.
        # If `times` is 1, just return the value, otherwise return an array.
        @[name] = (times=1) ->
            values = (@setValue(@mutate(getNext())) for time in [1..times])
            if times == 1 then values[0] else values

    getValue: (value) -> @_value

    mutate: (value) -> value

    setValue: (value) -> @_value = value

    toString: -> "[object Stochator]"

    _value: 0

if module?.exports
    module.exports = Stochator
else
    this.Stochator = Stochator

<commit_msg>Replace CoffeeScript thin arrows with ES6 fat arrows.<commit_after>seedrandom = require("seedrandom")

isType = (type) =>
    (arg) => Object::toString.call(arg) == "[object #{ type }]"

isFunc = isType("Function")

isObject = isType("Object")

randomBoundedFloat = (prng, min = 0, max = 1) =>
    spread = max - min
    prng() * spread + min

randomBoundedInteger = (prng, min = 0, max = 1) =>
    spread = 1 + max - min
    Math.floor(prng() * spread) + min

randomColor = (prng) =>
    byte = kind: "integer", min: 0, max: 255, prng: prng
    mutator = (bytes) =>
        [red, green, blue] = bytes
        { red, green, blue }

    new Stochator(byte, byte, byte, mutator).next

randomNormallyDistributedFloat = (prng, mean, stdev, min, max) =>
    seed = randomBoundedFloat(prng)
    float = inverseNormalCumulativeDistribution(seed) * stdev + mean
    if min? and max?
        Math.min(max, Math.max(min, float))
    else
        float

randomCharacter = (prng, lowercase) =>
    [min, max] = if lowercase then [97, 122] else [65, 90]
    mutator = (charCode) => String.fromCharCode(charCode)
    new Stochator({ kind: "integer", min, max, prng }, mutator).next

randomSetMember = (prng, set) =>
    max = set.length - 1
    set.get(randomBoundedInteger(prng, 0, max))

randomSetMemberWithoutReplacement = (prng, set) =>
    return undefined unless set.get(0)
    set.length -= 1
    set.pop(randomBoundedInteger(prng, 0, set.length))

randomWeightedSetMember = (prng, set, weights) =>
    [member, weightSum, float] = [undefined, 0, randomBoundedFloat(prng)]
    set.each((value, index) =>
        return if member
        weight = weights.get(index)
        if float <= weightSum + weight and float >= weightSum
            member = value
        weightSum += weight
    )

    member

inverseNormalCumulativeDistribution = (probability) =>
    high = probability > 0.97575
    low = probability < 0.02425

    if low or high
        numCoefficients = new Set([
            -7.784894002430293e-3, -3.223964580411365e-1, -2.400758277161838,
            -2.549732539343734, 4.374664141464968
        ])
        denomCoeffcients = new Set([
            7.784695709041462e-3, 3.224671290700398e-1,
            2.445134137142996, 3.754408661907416
        ])

        [numMaxExponent, denomMaxExponent] = [5, 4]
        coefficient = if low then 1 else -1
        base = Math.sqrt(
            -2 * Math.log(if low then probability else 1 - probability)
        )
    else
        numCoefficients = new Set([
            -3.969683028665376e1, 2.209460984245205e2, -2.759285104469687e2,
            1.383577518672690e2, -3.066479806614716e1, 2.506628277459239
        ])
        denomCoeffcients = new Set([
            -5.447609879822406e1, 1.615858368580409e2, -1.556989798598866e2,
            6.680131188771972e1, -1.328068155288572e1
        ])

        [numMaxExponent, denomMaxExponent] = [5, 5]
        coefficient = probability - 0.5
        base = Math.pow(coefficient, 2)

    mapMaxExp = (maxExp) =>
        (value, index) => value * Math.pow(base, maxExp - index)

    numerator = numCoefficients.map(mapMaxExp(numMaxExponent)).sum()
    denominator = denomCoeffcients.map(mapMaxExp(denomMaxExponent)).sum() + 1

    coefficient * numerator / denominator

shuffleSet = (prng, set) =>
    values = set.copy()
    for index in [values.length - 1...0]
        randomIndex = randomBoundedInteger(prng, 0, index)

        tmp = values[index]
        values[index] = values[randomIndex]
        values[randomIndex] = tmp

    values

floatGenerator = (prng, min, max, mean, stdev) =>
    if mean and stdev
        => randomNormallyDistributedFloat(prng, mean, stdev, min, max)
    else
        => randomBoundedFloat(prng, min, max)

integerGenerator = (prng, min = 0, max = 1) =>
    => randomBoundedInteger(prng, min, max)

setGenerator = (prng, values, replacement = true, shuffle = false, weights = null) =>
    if not values or not values.length
        throw Error("Must provide a 'values' array for a set generator.")

    set = new Set(values)
    if shuffle
        => shuffleSet(prng, set)
    else if replacement
        if weights
            weightsSet = new Set(weights)
            => randomWeightedSetMember(prng, set, weightsSet)
        else
            => randomSetMember(prng, set)
    else
        => randomSetMemberWithoutReplacement(prng, set)

createGenerator = (config) =>
    kind = config.kind or "float"

    defaultPrng = if config.seed then seedrandom else Math.random
    basePrng = config.prng or defaultPrng
    prng = if config.seed then basePrng(config.seed) else basePrng

    generator = switch kind
        when "float"
            { min, max, mean, stdev } = config
            floatGenerator(prng, min, max, mean, stdev)
        when "integer"
            integerGenerator(prng, config.min, config.max)
        when "set"
            { values, replacement, shuffle, weights } = config
            setGenerator(prng, values, replacement, shuffle, weights)
        when "color", "rgb" then randomColor(prng)
        when "a-z", "A-Z" then randomCharacter(prng, kind is "a-z")
    if not generator
        throw Error("#{ kind } not a recognized kind.")
    else
        generator

getNextValueGenerator = (configs) =>
    configs[0] ?= {}
    generators = (createGenerator(config) for config in configs)
    if generators.length is 1
        => generators[0]()
    else
        => (generator() for generator in generators)

class Stochator

    VERSION = "0.4"

    constructor: (configs..., mutator=null, name="next") =>
        # If the last arg is an object, all args are config args.
        # If the penultimate arg is an object, check whether the last arg
        # is a string (hence, the name) or a function (hence, the mutator).
        if isObject(name)
            configs[configs.length..configs.length + 2] = [mutator, name]
            [mutator, name] = [null, "next"]
        else if isObject(mutator)
            configs[configs.length] = mutator
            [mutator, name] = if isFunc(name)
                [name, "next"]
            else
                [null, name]

        # If the mutator is provided, override the default identity func.
        if mutator
            @mutate = (nextValue) => mutator(nextValue, @getValue())

        # Transform the configs to a func to get the next value.
        getNext = getNextValueGenerator(configs)

        # Assign `name` to the next mutated value(s), after `times` iterations.
        # If `times` is 1, just return the value, otherwise return an array.
        @[name] = (times=1) =>
            values = (@setValue(@mutate(getNext())) for time in [1..times])
            if times == 1 then values[0] else values

    getValue: (value) => @_value

    mutate: (value) => value

    setValue: (value) => @_value = value

    toString: => "[object Stochator]"

    _value: 0

if module?.exports
    module.exports = Stochator
else
    this.Stochator = Stochator

<|endoftext|>


<commit_before>var isArray = Array.isArray;

function toArray(target) {
	return Array.prototype.slice.apply(target);
}

function isUndefined(target) {
	return typeof target === 'undefined';
}

function isNull (target) {
	return target == null && typeof target == 'object';
}

function isBoolean(target) {
	return typeof target === 'boolean';
}

function isDefined(target) {
	return isUndefined(target) === false;
}

function isDate(value) {
  return toString.call(value) === '[object Date]';
}

function isRegExp(value) {
  return toString.call(value) === '[object RegExp]';
}

function isWindow(value) {
  return toString.call(value) === '[object Window]';
}

function inherit(parent, extra) {
	return extend(Object.create(parent), extra);
}

function isEqual(o1, o2) {
  var v1,
      v2,
      t1 = typeof o1,
      t2 = typeof o2,
      keys,
      length;

  if(o1 === o2) return true;
  if(o1 === null || o2 === null) return false;

  // Compares the type of each variable
  if(t1 !== t2) return false;

  if(isNumber(o1)) {
    if(o1 != o2) {
      return false;
    }
  } else if(isString(o1)) {
    if(o1.length != o2.length || o1 != o2) {
      return false;
    }
  } else if(isArray(o1)) {
    // Check for difference lengths between arrays
    if(o1.length != o2.length) return false;

    length = o1.length;

    while(length--) {
      if(isEqual(o1[length], o2[length])) {
        continue;
      }

      return false;
    }
  } else if (isObject(o1)) {
    keys = Object.keys(o1);
    length = keys.length;

    while(length--) {
      if(isEqual(o1[keys[length]], o2[keys[length]])) {
        continue;
      }

      return false;
    }
  }

  return true;
}

function first(array) {
	return array[0];
}

function copy (destination, source, stack) {
	if(isObject(source)) {
		var keys = Object.keys(source);
		var i,
				ii = keys.length,
				key,
				value;

		stack = stack || [];

		for(i = 0; i < ii; i++) {
			key 		= keys[i];
			value 	= source[key];

			stack.push(value);

			if(isObject(value) && stack.indexOf(value) === -1) {
				value = copy(isArray(value) ? [] : {}, value, stack);
			}

			destination[key] = value;
		}

		return destination;
	}
	return source;
}

function clone (object) {
	return copy(isArray(object) ? [] : {}, object);
}

function values (object) {
	var keys = Object.keys(object);
	var i,
			ii = keys.length,
			values = [];
	for(i = 0; i < ii; i++) {
		values[i] = object[keys[i]];
	}
	return values;
}

function some(array, iterator, context) {
	var i,
			ii = array.length,
			result = false;
	for(i = 0; i < ii; i++) {
		if(iterator.call(context, array, i)) {
			result = true;
		}
	}
	return result;
}

function get (object, path) {
	var keys = path.split('.');

	var i,
			ii = keys.length,
			result = object;
	for(i = 0; i < ii; i++) {
		if(result) {
			result = result[keys[i]];
		}
	}

	return result;
}

function set (object, path, value) {
	if(!path) path = '';

	var keys = path.split('.');

	var i,
			ii = keys.length,
			result = object;

	for(i = 0; i < ii; i++) {
		if(!result) result = {};
		if(i === (ii - 1)) {
			result[keys[i]] = value;
		} else if(result && result.hasOwnProperty(keys[i])) {
			result = result[keys[i]];
		} else {
			result = result[keys[i]] = {};
		}
	}

	return result;
}

function has (object, path) {
	var keys = path.split('.');

	var i,
			ii = keys.length,
			has = false,
			result = object;

	for(i = 0; i < ii; i++) {
		has = false;

		if(!result) result = {};
		if(result.hasOwnProperty(keys[i])) {
			result = result[keys[i]];
		} else {
			break;
		}

		has = true;
	}

	return has;
}

function noop() {
	return;
}

function isObject (value) {
	return value !== null && (typeof value === 'object');
}

function isString (value) {
	return typeof value === 'string';
}

function isFunction (value) {
	return typeof value === 'function';
}

function isNumber (value) {
	return typeof value === 'number';
}

function pick(object, keys) {
	if(isString(keys)) {
		keys = [keys];
	}

	var i,
			ii = keys.length,
			key,
			cloned = {};

	for(i = 0; i < ii; i++) {
		key = keys[i];

		cloned[key] = object[key];
	}

	return cloned;
}

function omit(object, keys) {
	if(isString(keys)) {
		keys = [keys];
	}

	var objectKeys = Object.keys(object).filter(function(key) {
		return keys.indexOf(key) > -1;
	});

	return pick(object, objectKeys);
}

function extend (target) {
	if(!target) target = {};

	var sources = toArray(arguments).slice(1).filter(isDefined);

	var source,
			value,
			keys,
			key,
			ii = sources.length,
			jj,
			i,
			j;

	for(i = 0; i < ii; i++) {
		if((source = sources[i]) && isObject(source)) {
			keys = Object.keys(source);
			jj = keys.length;

			for(j = 0; j < jj; j++) {
				key 					= keys[j];
				value 				= source[key];

				target[key] 	= value;
			}
		}
	}

	return target;
}

function defaults (object, source) {
	var keys = Object.keys(source);
	var i, ii = keys.length, key, value;

	for(i = 0; i < ii; i++) {
		key 		= keys[i];
		value		= source[key];

		if(!object.hasOwnProperty(key)) {
			object[key] = value;
		}
	}
}

function forEach (array, iterator, context) {
	var length;

	if(isArray(array)) {
		for(i = 0, length = array.length; i < length; i++) {
			iterator.call(context, array[i], i, array);
		}
	} else {
		var keys = Object.keys(array);
		var ii = keys.length, i, key, value;

		for(i = 0; i < ii; i++) {
			key = keys[i];
			value = array[key];

			iterator.call(context, value, key, array);
		}
	}
	return array;
}

function map (array, iterator, context) {
  var i,
      cloned = isArray(array) ? [] : {};

  if(isArray(array)) {
    for(i = 0; i < array.length; i++) {
      cloned[i] = iterator.call(context, array[i], i, array);
    }
  } else if (isObject(array)) {
    var keys = Object.keys(array);

    for(i = 0; i < keys.length; i++) {
      cloned[keys[i]] = iterator.call(context, array[keys[i]], keys[i], array);
    }
  }

  return cloned;
}

function camelCase (str) {
	return (str = str.replace(/[^A-z]/g, ' ')) && lowercase(str).replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function(match, index) {
		if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
		return index == 0 ? match.toLowerCase() : match.toUpperCase();
	});
}

function kebabCase(str) {
	return lowercase(str.replace(/[A-Z]/g, '-$&'));
}

function lowercase(str) {
	return String(str).toLowerCase();
}

function lazy(callback, context) {
	return function() {
		return bind(callback, context);
	};
}

function last(array) {
	return array && array[array.length - 1];
}

function bind(callback, context) {
	var args = toArray(arguments).slice(1);

	return function() {
		args = args.concat(toArray(arguments));

		return callback.apply(args[0], args.slice(1));
	};
}

function inherits (ctor, superCtor, attrs, ctorAttrs) {
	if (ctor === undefined || ctor === null)
		throw new TypeError('The constructor to "inherits" must not be ' +
												'null or undefined');

	if (superCtor === undefined || superCtor === null)
		throw new TypeError('The super constructor to "inherits" must not ' +
												'be null or undefined');

	if (superCtor.prototype === undefined)
		throw new TypeError('The super constructor to "inherits" must ' +
												'have a prototype');

	ctor.super_ = superCtor;
	Object.setPrototypeOf(ctor.prototype, superCtor.prototype);

	if(attrs) {
		extend(ctor.prototype, attrs);
	}

  if(ctorAttrs) {
    extend(ctor, ctorAttrs);
  }
}

var id = 0;
function nextId() {
	return ++id;
}

function elementData(node, key, value) {
	if(!node.hasOwnProperty(cacheKey)) {
		node[cacheKey] = nextId();

		elCache[node[cacheKey]] = {};
	}

	var cache = elCache[node[cacheKey]];

	if(!key) {
		return cache;
	}

	if(!value && cache.hasOwnProperty(key)) {
		return cache[key];
	} else if(value) {
		cache[key] = value;
	}

	return null;
}

function elementInheritedData(element, name, value) {
	// if element is the document object work with the html element instead
	// this makes $(document).scope() possible
	if (element.nodeType == Node.DOCUMENT_NODE) {
		element = element.documentElement;
	}

	var names = isArray(name) ? name : [name];

	while (element) {
		for (var i = 0, ii = names.length; i < ii; i++) {
			if (value = elementData(element, names[i])) return value;
		}

		// If dealing with a document fragment node with a host element, and no parent, use the host
		// element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
		// to lookup parent controllers.
		element = element.parentNode || (element.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.host);
	}
}

function request (url, successFn, errorFn) {
	var xhr = new XMLHttpRequest();

	if(!successFn) {
		throw new Error('you must pass a success callback');
	}

	xhr.addEventListener('readystatechange', function(e) {
		if(xhr.readyState == XMLHttpRequest.DONE) {
			setTimeout(function() {
				successFn(xhr.responseText);
			});
		}
	});

	xhr.open('GET', url, true);
	xhr.send(null);
}
<commit_msg>chore(src/helpers.js): `bind()` function update<commit_after>var isArray = Array.isArray;

function toArray(target) {
	return Array.prototype.slice.apply(target);
}

function isUndefined(target) {
	return typeof target === 'undefined';
}

function isNull (target) {
	return target == null && typeof target == 'object';
}

function isBoolean(target) {
	return typeof target === 'boolean';
}

function isDefined(target) {
	return isUndefined(target) === false;
}

function isDate(value) {
  return toString.call(value) === '[object Date]';
}

function isRegExp(value) {
  return toString.call(value) === '[object RegExp]';
}

function isWindow(value) {
  return toString.call(value) === '[object Window]';
}

function inherit(parent, extra) {
	return extend(Object.create(parent), extra);
}

function isEqual(o1, o2) {
  var v1,
      v2,
      t1 = typeof o1,
      t2 = typeof o2,
      keys,
      length;

  if(o1 === o2) return true;
  if(o1 === null || o2 === null) return false;

  // Compares the type of each variable
  if(t1 !== t2) return false;

  if(isNumber(o1)) {
    if(o1 != o2) {
      return false;
    }
  } else if(isString(o1)) {
    if(o1.length != o2.length || o1 != o2) {
      return false;
    }
  } else if(isArray(o1)) {
    // Check for difference lengths between arrays
    if(o1.length != o2.length) return false;

    length = o1.length;

    while(length--) {
      if(isEqual(o1[length], o2[length])) {
        continue;
      }

      return false;
    }
  } else if (isObject(o1)) {
    keys = Object.keys(o1);
    length = keys.length;

    while(length--) {
      if(isEqual(o1[keys[length]], o2[keys[length]])) {
        continue;
      }

      return false;
    }
  }

  return true;
}

function first(array) {
	return array[0];
}

function copy (destination, source, stack) {
	if(isObject(source)) {
		var keys = Object.keys(source);
		var i,
				ii = keys.length,
				key,
				value;

		stack = stack || [];

		for(i = 0; i < ii; i++) {
			key 		= keys[i];
			value 	= source[key];

			stack.push(value);

			if(isObject(value) && stack.indexOf(value) === -1) {
				value = copy(isArray(value) ? [] : {}, value, stack);
			}

			destination[key] = value;
		}

		return destination;
	}
	return source;
}

function clone (object) {
	return copy(isArray(object) ? [] : {}, object);
}

function values (object) {
	var keys = Object.keys(object);
	var i,
			ii = keys.length,
			values = [];
	for(i = 0; i < ii; i++) {
		values[i] = object[keys[i]];
	}
	return values;
}

function some(array, iterator, context) {
	var i,
			ii = array.length,
			result = false;
	for(i = 0; i < ii; i++) {
		if(iterator.call(context, array, i)) {
			result = true;
		}
	}
	return result;
}

function get (object, path) {
	var keys = path.split('.');

	var i,
			ii = keys.length,
			result = object;
	for(i = 0; i < ii; i++) {
		if(result) {
			result = result[keys[i]];
		}
	}

	return result;
}

function set (object, path, value) {
	if(!path) path = '';

	var keys = path.split('.');

	var i,
			ii = keys.length,
			result = object;

	for(i = 0; i < ii; i++) {
		if(!result) result = {};
		if(i === (ii - 1)) {
			result[keys[i]] = value;
		} else if(result && result.hasOwnProperty(keys[i])) {
			result = result[keys[i]];
		} else {
			result = result[keys[i]] = {};
		}
	}

	return result;
}

function has (object, path) {
	var keys = path.split('.');

	var i,
			ii = keys.length,
			has = false,
			result = object;

	for(i = 0; i < ii; i++) {
		has = false;

		if(!result) result = {};
		if(result.hasOwnProperty(keys[i])) {
			result = result[keys[i]];
		} else {
			break;
		}

		has = true;
	}

	return has;
}

function noop() {
	return;
}

function isObject (value) {
	return value !== null && (typeof value === 'object');
}

function isString (value) {
	return typeof value === 'string';
}

function isFunction (value) {
	return typeof value === 'function';
}

function isNumber (value) {
	return typeof value === 'number';
}

function pick(object, keys) {
	if(isString(keys)) {
		keys = [keys];
	}

	var i,
			ii = keys.length,
			key,
			cloned = {};

	for(i = 0; i < ii; i++) {
		key = keys[i];

		cloned[key] = object[key];
	}

	return cloned;
}

function omit(object, keys) {
	if(isString(keys)) {
		keys = [keys];
	}

	var objectKeys = Object.keys(object).filter(function(key) {
		return keys.indexOf(key) > -1;
	});

	return pick(object, objectKeys);
}

function extend (target) {
	if(!target) target = {};

	var sources = toArray(arguments).slice(1).filter(isDefined);

	var source,
			value,
			keys,
			key,
			ii = sources.length,
			jj,
			i,
			j;

	for(i = 0; i < ii; i++) {
		if((source = sources[i]) && isObject(source)) {
			keys = Object.keys(source);
			jj = keys.length;

			for(j = 0; j < jj; j++) {
				key 					= keys[j];
				value 				= source[key];

				target[key] 	= value;
			}
		}
	}

	return target;
}

function defaults (object, source) {
	var keys = Object.keys(source);
	var i, ii = keys.length, key, value;

	for(i = 0; i < ii; i++) {
		key 		= keys[i];
		value		= source[key];

		if(!object.hasOwnProperty(key)) {
			object[key] = value;
		}
	}
}

function forEach (array, iterator, context) {
	var length;

	if(isArray(array)) {
		for(i = 0, length = array.length; i < length; i++) {
			iterator.call(context, array[i], i, array);
		}
	} else {
		var keys = Object.keys(array);
		var ii = keys.length, i, key, value;

		for(i = 0; i < ii; i++) {
			key = keys[i];
			value = array[key];

			iterator.call(context, value, key, array);
		}
	}
	return array;
}

function map (array, iterator, context) {
  var i,
      cloned = isArray(array) ? [] : {};

  if(isArray(array)) {
    for(i = 0; i < array.length; i++) {
      cloned[i] = iterator.call(context, array[i], i, array);
    }
  } else if (isObject(array)) {
    var keys = Object.keys(array);

    for(i = 0; i < keys.length; i++) {
      cloned[keys[i]] = iterator.call(context, array[keys[i]], keys[i], array);
    }
  }

  return cloned;
}

function camelCase (str) {
	return (str = str.replace(/[^A-z]/g, ' ')) && lowercase(str).replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function(match, index) {
		if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
		return index == 0 ? match.toLowerCase() : match.toUpperCase();
	});
}

function kebabCase(str) {
	return lowercase(str.replace(/[A-Z]/g, '-$&'));
}

function lowercase(str) {
	return String(str).toLowerCase();
}

function lazy(callback, context) {
	return function() {
		return bind(callback, context);
	};
}

function last(array) {
	return array && array[array.length - 1];
}

function bind(callback, context) {
	return function() {
		return callback.apply(context, arguments);
	};
}

function inherits (ctor, superCtor, attrs, ctorAttrs) {
	if (ctor === undefined || ctor === null)
		throw new TypeError('The constructor to "inherits" must not be ' +
												'null or undefined');

	if (superCtor === undefined || superCtor === null)
		throw new TypeError('The super constructor to "inherits" must not ' +
												'be null or undefined');

	if (superCtor.prototype === undefined)
		throw new TypeError('The super constructor to "inherits" must ' +
												'have a prototype');

	ctor.super_ = superCtor;
	Object.setPrototypeOf(ctor.prototype, superCtor.prototype);

	if(attrs) {
		extend(ctor.prototype, attrs);
	}

  if(ctorAttrs) {
    extend(ctor, ctorAttrs);
  }
}

var id = 0;
function nextId() {
	return ++id;
}

function elementData(node, key, value) {
	if(!node.hasOwnProperty(cacheKey)) {
		node[cacheKey] = nextId();

		elCache[node[cacheKey]] = {};
	}

	var cache = elCache[node[cacheKey]];

	if(!key) {
		return cache;
	}

	if(!value && cache.hasOwnProperty(key)) {
		return cache[key];
	} else if(value) {
		cache[key] = value;
	}

	return null;
}

function elementInheritedData(element, name, value) {
	// if element is the document object work with the html element instead
	// this makes $(document).scope() possible
	if (element.nodeType == Node.DOCUMENT_NODE) {
		element = element.documentElement;
	}

	var names = isArray(name) ? name : [name];

	while (element) {
		for (var i = 0, ii = names.length; i < ii; i++) {
			if (value = elementData(element, names[i])) return value;
		}

		// If dealing with a document fragment node with a host element, and no parent, use the host
		// element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
		// to lookup parent controllers.
		element = element.parentNode || (element.nodeType === Node.DOCUMENT_FRAGMENT_NODE && element.host);
	}
}

function request (url, successFn, errorFn) {
	var xhr = new XMLHttpRequest();

	if(!successFn) {
		throw new Error('you must pass a success callback');
	}

	xhr.addEventListener('readystatechange', function(e) {
		if(xhr.readyState == XMLHttpRequest.DONE) {
			setTimeout(function() {
				successFn(xhr.responseText);
			});
		}
	});

	xhr.open('GET', url, true);
	xhr.send(null);
}
<|endoftext|>


<commit_before>const config = require('../config/config.json').PREFIX;
let channelsArr = [];
exports.run = async (client, guild) => {

  let Id = guild.channels.get(guild.channels.filter(i=> i.type === "text").map(i => i)[0].id);
  let p = guild.channels.filter(o => o.type === 'text').map(o => o);
  Id.send(`Hey :wave:, Thank you very much for adding me to \`${guild.name}\` to get access to the command list do \`${config}help\``);

  /**
  * Check if there's a channel with the name of may-log
  * @type {Array}
  */
  for (let i = 0; i < p.length; i++) {
    channelsArr.push(p[i].name)
  }

  /**
  * Create a channel for may to print out punishments
  * @returns {Error}
  * @returns {Promise}
  */
  if(!channelsArr.includes('may-log')) {
    channelsArr.shift();
    guild.createChannel("may-log", "text").then(channel => channel.overwritePermissions(guild.id, {
      SEND_MESSAGES: false
    }))
    .catch(e => {
      logger.error(e);
    });
  }

  /*
  * Check if may-muted is already exists.
  */
  let checkIfMayMutedExists = guild.roles.filter(o => o.name === 'may-muted').map(o => o);
  /**
  * Create muted role
  * @param {Object} data
  * @param {String} name
  * @param {String} color
  * @param {Array} permissions
  * @param {String} reason
  * @returns {Error}
  * @returns {Promise}
  */
  if (checkIfMayMutedExists.length < 1) {
      guild.createRole({
        name: 'may-muted',
        permissions: ["USE_VAD", "ADD_REACTIONS", "READ_MESSAGE_HISTORY", "CREATE_INSTANT_INVITE", "READ_MESSAGES"],
        reason: 'we needed a role for muted',
    })
      .then(role => logger.info(`Created role ${role.name}`))
      .catch(e => {
       logger.error(e);
    });
  } else {
    logger.log('The role is already exists.')
  }

  /*
    Loop through all the channels and block muted people to talk there
  */
  setTimeout(function () {
    guild.channels.filter(textchannel => textchannel.type === 'text').forEach(cnl => {
      cnl.overwritePermissions(guild.roles.find('name', 'may-muted').id, {
          SEND_MESSAGES: false
      })
        .catch(e => logger.error(e))
  });
  }, 2000);
};<commit_msg>Indentation<commit_after>const config = require('../config/config.json').PREFIX;
let channelsArr = [];
exports.run = async (client, guild) => {

    let Id = guild.channels.get(guild.channels.filter(i=> i.type === "text").map(i => i)[0].id);
    let p = guild.channels.filter(o => o.type === 'text').map(o => o);
    Id.send(`Hey :wave:, Thank you very much for adding me to \`${guild.name}\` to get access to the command list do \`${config}help\``);

    /**
     * Check if there's a channel with the name of may-log
     * @type {Array}
     */
    for (let i = 0; i < p.length; i++) {
        channelsArr.push(p[i].name)
    }

    /**
     * Create a channel for may to print out punishments
     * @returns {Error}
     * @returns {Promise}
     */
    if(!channelsArr.includes('may-log')) {
        channelsArr.shift();
        guild.createChannel("may-log", "text").then(channel => channel.overwritePermissions(guild.id, {
            SEND_MESSAGES: false
        }))
            .catch(e => {
                logger.error(e);
            });
    }

    /*
  * Check if may-muted is already exists.
  */
    let checkIfMayMutedExists = guild.roles.filter(o => o.name === 'may-muted').map(o => o);
    /**
     * Create muted role
     * @param {Object} data
     * @param {String} name
     * @param {String} color
     * @param {Array} permissions
     * @param {String} reason
     * @returns {Error}
     * @returns {Promise}
     */
    if (checkIfMayMutedExists.length < 1) {
        guild.createRole({
            name: 'may-muted',
            permissions: ["USE_VAD", "ADD_REACTIONS", "READ_MESSAGE_HISTORY", "CREATE_INSTANT_INVITE", "READ_MESSAGES"],
            reason: 'we needed a role for muted',
        })
            .then(role => logger.info(`Created role ${role.name}`))
            .catch(e => {
                logger.error(e);
            });
    } else {
        logger.log('The role is already exists.')
    }

    /*
    Loop through all the channels and block muted people to talk there
  */
    setTimeout(function () {
        guild.channels.filter(textchannel => textchannel.type === 'text').forEach(cnl => {
            cnl.overwritePermissions(guild.roles.find('name', 'may-muted').id, {
                SEND_MESSAGES: false
            })
                .catch(e => logger.error(e))
        });
    }, 2000);
};<|endoftext|>


<commit_before>  /* validates add a request form */
  $(document).ready(function(){

    $("#submitRequest").validate({
      rules: {
        request_text: {
          required: true,
          minlength: 2
             }
         },
      highlight: function(element) {
        $(element).closest('.control-group').removeClass('success').addClass('error');
        },
      success: function(element) {
        .closest('.control-group').removeClass('error').addClass('success');
        }
    });

  });

$(document).ready(function() {
var map = {};
var departments = [];
var doc_types = [];
$.getJSON("static/json/doctypes.json", function(data) {
      $.each(data, function (i, line) {
        var department = line['DEPARTMENT'];
        var doc_type = line['DOC_TYPE'];
        if($.inArray(department, departments) == -1) {
          departments.push(department);
         }
          map[doc_type + " - " + department] = department;
          doc_types.push(doc_type + " - " + department);
       });
    });
/* typeahead for email in reroute form */
$('#inputDepartment').typeahead({
      source: doc_types
      , updater: function (item) {
        department = map[item];
        return department;
      }
      ,matcher: function(item) {
        if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1){
        return true;
       }
      }
    , items: 8
    , menu: '

'
    , item: '

'
    , minLength: 1
    })

  $('#requestTextarea').on('blur', function() {
    request_text = $(this).val();
    request = $.ajax({
      url: '/is_public_record',
      type: 'post',
      data: {
        request_text: request_text
      }
    });
    request.done( function(data) {
      $div = $('#not_public_record');
      if (data != '') {
        $div.addClass('alert').addClass('alert-error');
        $div.html(data);
        $div.prepend("");
      } else {
        $div.empty();
        $div.removeClass('alert').removeClass('alert-error');
      }
    });
  })
});<commit_msg>Reverting back to earlier new_request.js<commit_after>  /* validates add a request form */
  $(document).ready(function(){

    $("#submitRequest").validate({
      // ignore: ".ignore",
      rules: {
        request_text: {
          required: true,
          minlength: 2
             }
         },
      highlight: function(element) {
          // $('#inputEmail').addClass('ignore');
          // $('#requestButton').html(
          //   "
"+
          //     "
Oops, you forgot to provide an email address.
"+
          //       "
Your email is how we contact you.  If you choose to leave it blank, you will not receive updates about your request.  Your request may take longer or be dismissed if it is missing important information. You can still enter your e-mail address at this time, and continue with submission.
"+
          //       "<button id='submit_anyway' class='btn btn-danger' type='submit'>Got it, submit my request!</button>"+
          //     "
"
          //   );
        $(element).closest('.control-group').removeClass('success').addClass('error');
        },
      success: function(element) {
        // $('#requestButton').html(
        //   "
"+
        //     "
"+
        //       "<button type='submit' class='btn btn-large btn-primary'>Request</button>"+
        //     "
"+
        //   "
"
        //   );
        element
        // .text('OK!').addClass('valid')
        .closest('.control-group').removeClass('error').addClass('success');
        }
    });

  });

$(document).ready(function() {
var map = {};
var departments = [];
var doc_types = [];
$.getJSON("static/json/doctypes.json", function(data) {
      $.each(data, function (i, line) {
        var department = line['DEPARTMENT'];
        var doc_type = line['DOC_TYPE'];
        if($.inArray(department, departments) == -1) {
          departments.push(department);
         }
          map[doc_type + " - " + department] = department;
          doc_types.push(doc_type + " - " + department);
       });
    });
/* typeahead for email in reroute form */
$('#inputDepartment').typeahead({
      source: doc_types
      , updater: function (item) {
        department = map[item];
        return department;
      }
      ,matcher: function(item) {
        if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1){
        return true;
       }
      }
    , items: 8
    , menu: '

'
    , item: '

'
    , minLength: 1
    })

  $('#requestTextarea').on('blur', function() {
    request_text = $(this).val();
    request = $.ajax({
      url: '/is_public_record',
      type: 'post',
      data: {
        request_text: request_text
      }
    });
    request.done( function(data) {
      $div = $('#not_public_record');
      if (data != '') {
        $div.addClass('alert').addClass('alert-error');
        $div.html(data);
        $div.prepend(" ");
      } else {
        $div.empty();
        $div.removeClass('alert').removeClass('alert-error');
      }
    });
  })
});<|endoftext|>


<commit_before>$(document).ready(function() {
    "use strict";

    var $perfResults = $('#perf-results'),
        platforms = JSON.parse($perfResults.attr('data-platforms')),
        results = [];

    // We only show 10 at the beginning and toggle the rest here.
    $('#perf-more a').click(function(e) {
        e.preventDefault();
        $('#perf-more').remove();
        $perfResults.addClass('show-more');
    });

    // Add All to the platforms map.
    platforms[gettext('All')] = 0;

    // Gather all the os-specific data.
    $perfResults.find('tbody tr').each(function(i, e) {
        var p = $(this).attr('data-platforms')
        results.push(p ? JSON.parse(p) : {});
    });

    if ($('#show').length == 0) {
        return;
    }

    // Switch to js strings so we have consistent gettext.
    switchNumbers(gettext('All'));

    $('#show').delegate('a', 'click', function(e) {
        e.preventDefault();
        switchNumbers($.trim($(this).text()));
    });

    // Change numbers and bar graphs to the selected platform data.
    function switchNumbers(selected) {
        var platform = platforms[selected],
            numbers = $.map(results, function(e) { return e[platform] || 0; }),
            worst = Math.max.apply(null, numbers);
        $perfResults.find('tbody tr').each(function(i, e) {
            var $this = $(this),
                num = results[i][platform] || 0;
            $this.find('.slower b').text(num === 0 ? gettext('N/A') : num + '%');
            $this.find('.bar').css('width', num / worst * 100 + '%');
        });
        showPlatforms(selected);
    }

    // Redisplay the list of names to select the current platform.
    function showPlatforms(selected) {
        var _names = _.keys(platforms);
        _names.sort()
        var names = $.map(_names, function(e) {
            var name = e == selected ? '' + e + '' : e;
            return format('{0}', name);
        });
        $('#show span').html(names.join(', '));
    }
});
<commit_msg>Prevents a JSON parse error on every single page except performance.<commit_after>(function() {
// protect globals

$(document).ready(function() {
    "use strict";

    if ($('#perf-results').length) {
        initPerf();
    }
});

function initPerf() {
    "use strict";

    var $perfResults = $('#perf-results'),
        platforms = JSON.parse($perfResults.attr('data-platforms')),
        results = [];

    // We only show 10 at the beginning and toggle the rest here.
    $('#perf-more a').click(function(e) {
        e.preventDefault();
        $('#perf-more').remove();
        $perfResults.addClass('show-more');
    });

    // Add All to the platforms map.
    platforms[gettext('All')] = 0;

    // Gather all the os-specific data.
    $perfResults.find('tbody tr').each(function(i, e) {
        var p = $(this).attr('data-platforms')
        results.push(p ? JSON.parse(p) : {});
    });

    if ($('#show').length == 0) {
        return;
    }

    // Switch to js strings so we have consistent gettext.
    switchNumbers(gettext('All'));

    $('#show').delegate('a', 'click', function(e) {
        e.preventDefault();
        switchNumbers($.trim($(this).text()));
    });

    // Change numbers and bar graphs to the selected platform data.
    function switchNumbers(selected) {
        var platform = platforms[selected],
            numbers = $.map(results, function(e) { return e[platform] || 0; }),
            worst = Math.max.apply(null, numbers);
        $perfResults.find('tbody tr').each(function(i, e) {
            var $this = $(this),
                num = results[i][platform] || 0;
            $this.find('.slower b').text(num === 0 ? gettext('N/A') : num + '%');
            $this.find('.bar').css('width', num / worst * 100 + '%');
        });
        showPlatforms(selected);
    }

    // Redisplay the list of names to select the current platform.
    function showPlatforms(selected) {
        var _names = _.keys(platforms);
        _names.sort()
        var names = $.map(_names, function(e) {
            var name = e == selected ? '' + e + '' : e;
            return format('{0}', name);
        });
        $('#show span').html(names.join(', '));
    }
}

// END global protection
})();
<|endoftext|>


<commit_before>/**
 * 弹出层
 */
onkeydown(document, function (e) {
    if (e.which === 27 && rootElements.length) {
        var r = rootElements.pop();
        if (r) {
            r.blur();
            remove(r);
        }
    }
});
var animationStyle = "opacity:0;transform:scale(1.2);transition:.1s opacity ease-out,.2s transform ease-out;";
var setInitialStyle = function (element) {
    if (!element.initialStyle) element.initialStyle = animationStyle;
};
var windowFactory = function (window) {
    css(window, `min-height:10px;min-width:10px;position:absolute;`);
    return window;
};
var loadingFactory = function (element) {
    css(element, `position:absolute;`);
    return element;
}
/**
 * 弹出子窗口的函数
 * @param {string} path 窗口路径的唯一索引
 * @param {any} parameters 给窗口的作域预先赋值
 * @param {object} style 自定义样式，主要是width,height等位置参数
 * @returns {Element} 给调用弹窗的命令暴露的可选方法
 */
var popup = function (path) {
    if (isString(path)) {
        return popup_path.apply(null, arguments);
    }
    if (isNode(path)) {
        return popup_view.apply(null, arguments);
    }
    throw new Error(`path isn't valid:${path}`);
};
var popup_path = function (path = "", parameters, target) {
    if (!popup.go || !popup.prepare) throw new Error("当前环境无法使用");
    // 3 has mask has view control
    var element;
    if (/^[#\+]/.test(path)) {
        // mask
        path = path.replace(/^[#\+]/, "");
        var load = function () {
            windowFactory(element);
            setInitialStyle(element);
            popup_with_mask(element, target);
            if (element.dragHandle) drag.on(element);
        };
    }
    // 2 has view control has no mask
    else if (/^@/.test(path)) {
        path = path.replace(/^@/, "");
        var load = function () {
            windowFactory(element);
            setInitialStyle(element);
            popup_as_single(element);
            if (element.dragHandle) drag.on(element);
        };
    }
    // 1 has mask has no control
    else if (/^!/.test(path)) {
        path = path.replace(/^!/, "");
        var load = function () {
            loadingFactory(element);
            setInitialStyle(element);
            popup_with_mask(element);
        };
    }
    // 0 has no mask no control
    else {
        var load = function () {
            loadingFactory(element);
            if (isNode(target)) {
                popup_as_extra(element, target);
            }
            else if (target instanceof Event) {
                popup_to_event(element, target);
            } else if (target instanceof Array) {
                popup_to_point(element, target);
            } else if (target) {
                popup_with_mask(element);
            } else {
                if (parameters !== false && target !== false) setInitialStyle(element);
                popup_as_single(element);
            }
        };
    }
    var fullfill = function () {
        remove(element);
        remove(element && element.mask);
        element = popup.create(path, parameters);
        if (!element) return;
        load();
        element.$reload = fullfill;
        if (!target && target !== false && parameters !== false) {
            element.style.opacity = 0;
            if (element.parentNode) move.bindPosition(element, [.5, .5]), element.style.opacity = 1;
            else once('append')(element, function () {
                move.bindPosition(element, [.5, .5]);
                element.style.opacity = 1;
            });
        }
        callbacks.forEach(f => f(element));
    };
    var callbacks = [];
    popup.prepare(path, fullfill);
    return element || {
        then(ok) {
            if (element) return ok(element);
            else callbacks.push(ok);
        }, fullfill
    };
};

var popup_view = function (element, target, style) {
    if (isNode(target)) {
        if (target.isMask) {
            popup_with_mask(element, target);
            return element;
        }
        return popup_as_extra(element, target, style);
    }
    if (target instanceof Event) {
        popup_to_event(element, target);
    } else if (target instanceof Array) {
        popup_to_point(element, target);
    } else if (target) {
        popup_with_mask(element);
    } else {
        popup_as_single(element);
    }
    return element;
};

css(".mask", `position:absolute;position:fixed;left:0;right:0;bottom:0;top:0;width:auto;height:auto;background:#000;opacity:0.2;transform:scale(1);display:block`);
var createMask = function (element) {
    var masks = element.with;
    if (masks) for (var cx = 0, dx = masks.length; cx < dx; cx++) {
        var m = masks[cx];
        if (m.isMask) return m;
    }
    var mask = document.createElement("mask");
    mask.initialStyle = animationStyle;
    css(mask, `z-index:${zIndex()};`);
    mask.className = "mask";
    mask.isMask = true;
    return mask;
};
var popup_with_mask = function (element, mask = createMask(element)) {
    if (!mask.clean) {
        mask.clean = new Cleanup(element.with);
    }
    onremove(element, mask.clean);
    css(element, `z-index:${zIndex()};`);
    if (mask.parentNode) {
        global(element, false);
    }
    if (!element.with) {
        element.with = [mask];
    } else if (element.with instanceof Array) {
        if (!~element.with.indexOf(element)) element.with.push(mask);
    } else {
        if (element.with !== element) element.with = [element.with, mask];
    }
    if (!element.parentNode) global(element, false);
    return element;
};
var isypop = function (target) {
    if (!target) return false;
    var { offsetParent, nextSibling, previousSibling } = target;
    if (
        nextSibling && nextSibling.tagName === target.tagName
        && (
            nextSibling.offsetLeft - target.offsetLeft >= target.offsetWidth / 2
            || target.offsetLeft - nextSibling.offsetLeft >= nextSibling.offsetWidth / 2
        )
        || previousSibling && previousSibling.tagName === target.tagName
        && (
            previousSibling.offsetLeft - target.offsetLeft >= target.offsetWidth / 2
            || target.offsetLeft - previousSibling.offsetLeft >= previousSibling.offsetWidth / 2
        )
    ) return true;
    var padding = parseFloat(getComputedStyle(offsetParent).paddingTop) + parseFloat(getComputedStyle(offsetParent).paddingBottom);
    if (offsetParent && target.offsetTop / target.offsetHeight < .2 && (offsetParent.clientWidth - padding) / target.offsetWidth > 1.5) return true;

};
var isxpop = arriswise(isypop, arguments);
var popup_as_extra = function (element, target, style) {
    element.target = target;
    if (style) {
        if (/^[vy]/i.test(style)) {
            popup_as_yextra(element, target, style);
            return;
        }
        if (/^[hx]/i.test(style)) {
            popup_as_xextra(element, target, style);
            return;
        }

    }
    if (isypop(target)) {
        popup_as_yextra(element, target, style);
    } else if (isxpop(target)) {
        popup_as_xextra(element, target, style);
    } else if (isypop(target.offsetParent)) {
        popup_as_yextra(element, target, style);
    } else if (isxpop(target.offsetParent)) {
        popup_as_xextra(element, target, style);
    } else {
        if (/inline|cell/i.test(getComputedStyle(target).display)) {
            popup_as_yextra(element, target, style);
        } else {
            popup_as_xextra(element, target, style);
        }
    }

};
var _as_yextra = function (global, innerWidth, innerHeight, element, target, pointer) {
    var withRhomb = pointer && /rhomb|rhombus|diamond|lozenge|triangle|[drlt]$/i.test(pointer);
    if (withRhomb) {
        var _rhomb = rhomb();
    }
    if (!element.origin) {
        element.origin = {
            height: element.style.height,
            width: element.style.width,
            minWidth: element.style.minWidth,
            display: element.style.display
        };
    }
    var zindex = zIndex();
    css(element, `position:absolute;z-index:${zindex}`);
    css(_rhomb, { zIndex: zindex });
    var release1 = onremove(target, function () {
        remove(element);
    });
    var release2 = onremove(element, function () {
        release1();
        release2();
        remove(_rhomb);
        if (document.removeEventListener) {
            document.removeEventListener("scroll", reshape, true);
            window.removeEventListener("resize", reshape);
        }
    });
    global(element, false);
    var reshape = function () {
        extend(element.style, element.origin);
        var position = getScreenPosition(target);
        var viewrect = getScreenPosition(element.offsetParent);
        var documentbody = document.body;
        if (element.offsetParent === documentbody && !/^(absolute|relative|fixed)$/i.test(getComputedStyle(documentbody).position)) {
            viewrect.left = 0;
            viewrect.top = 0;
            viewrect.right += innerWidth - viewrect.right;
            viewrect.bottom += innerHeight - viewrect.bottom;
            viewrect.width = viewrect.right - viewrect.left;
            viewrect.height = viewrect.bottom - viewrect.top;
        } else {
            viewrect.top += documentbody.clientTop;
            viewrect.left += documentbody.clientLeft;
            viewrect.height = documentbody.clientHeight;
            viewrect.width = documentbody.clientWidth;
            viewrect.right = viewrect.left + viewrect.width;
            viewrect.bottom = viewrect.top + viewrect.height;
        }
        var maxHeight = Math.max(position.top, innerHeight - position.top - position.height) | 0;
        var maxWidth = Math.max(position.left + position.width, innerWidth - position.left);
        var height = element.offsetHeight;
        //如果高度超出可视区，调整高度
        if (height > maxHeight) {
            css(element, { height: fromOffset(maxHeight), maxHeight: fromOffset(maxHeight) });
        }

        css(element, `min-width:auto;`);
        var aimedWidth = getScreenPosition(element).width;
        //如果宽度不足其附着元素的宽度
        if (aimedWidth < position.width) {
            aimedWidth = position.width;
        }

        //如果宽度超出可视区，调整宽度
        if (aimedWidth > maxWidth) {
            aimedWidth = maxWidth;
        }
        var side;
        if (aimedWidth !== element.offsetWidth) {
            css(element, { width: fromOffset(aimedWidth) });
        }
        if (position.top + element.offsetHeight + position.height > innerHeight) {
            side = 'bottom';
            var temp = `bottom:${fromOffset(viewrect.height - position.top + viewrect.top)};top:auto;`;
        } else {
            side = 'top';
            var temp = `top:${fromOffset(position.top - viewrect.top + position.height)};bottom:auto;`
        }
        css(element, temp);
        if (_rhomb) {
            css(_rhomb, temp);
            _rhomb.setSide(side);
        }
        if (_rhomb) {
            var targetX = position.left + (position.width - element.offsetWidth) / 2;
            if (targetX < 0) {
                css(element, `left:0;right:auto`);
                css(_rhomb, `left:${fromOffset(position.left + position.width / 2)};right:auto`);
            }
            else if (targetX + element.offsetWidth > innerWidth) {
                css(element, `right:0;left:auto`);
                css(_rhomb, `right:${fromOffset(innerWidth - position.left - position.width / 2)};left:auto`);
            }
            else {
                css(element, `left:${fromOffset(targetX)};right:auto`);
                css(_rhomb, `left:${fromOffset(position.left + position.width / 2)};right:auto`);

            }
        } else {
            if (position.left + element.offsetWidth > innerWidth) {
                css(element, `right:${fromOffset(viewrect.width + viewrect.left - position.left - position.width)};left:auto;`);
            }
            else {
                css(element, `left:${fromOffset(position.left - viewrect.left)};right:auto;`);
            }
        }

        var offsetParent = target.offsetParent;
        if (offsetParent) {
            if (overlap(target, offsetParent) > 0) {
                element.style.display = element.origin.display;
                if (_rhomb && !_rhomb.parentNode) {
                    appendChild.before(element, _rhomb)
                }
            } else {
                element.style.display = "none";
                remove(_rhomb);
            };
        } else if (_rhomb && !_rhomb.parentNode) {
            appendChild.before(element, _rhomb)
        }
    }
    if (document.addEventListener) {
        document.addEventListener("scroll", reshape, true);
        window.addEventListener("resize", reshape);
    }
    reshape();
    lazy(reshape)();
};
var _as_xextra = arriswise(_as_yextra, arguments);
var popup_as_single = function (element) {
    css(element, `z-index:${zIndex()};`);
    global(element, false);
};
var popup_to_point = function (element, [x, y]) {
    if (x <= 1 && y <= 1 && x >= 0 && y >= 0) {
        popup_as_single(element);
        move.bindPosition(element, [x, y]);
    } else {
        x = calcPixel(x), y = calcPixel(y);
        popup_fixup(element, x, y);
    }
};
var popup_fixup = function (element, x, y) {
    css(element, {
        position: 'absolute',
    });
    popup_as_single(element);
    var left = "left", top = 'top';
    if (y + element.offsetHeight > window.innerHeight && y << 1 > window.innerHeight) {
        top = "bottom";
        y = window.innerHeight - y;
    }
    if (x + element.offsetWidth > window.innerWidth && x << 1 > window.innerWidth) {
        left = "right";
        x = window.innerWidth - x;
    }
    css(element, {
        [left]: fromOffset(x),
        [top]: fromOffset(y)
    });

};
var popup_to_event = function (element, { clientX, clientY }) {
    popup_fixup(element, clientX, clientY);
};
var global = function (element, issingle) {
    once("remove")(element, cleanup);
    rootElements.push(element);
    popup.global &&
        issingle !== false ? popup.global(element, true) : appendChild(document.body, element);
};
var popup_as_yextra = _as_yextra.bind(null, global, innerWidth, innerHeight);
var popup_as_xextra = _as_xextra.bind(null, global, innerHeight, innerWidth);
var cleanup = new Cleanup(rootElements);<commit_msg>修复一些问题<commit_after>/**
 * 弹出层
 */
onkeydown(document, function (e) {
    if (e.which === 27 && rootElements.length) {
        var r = rootElements.pop();
        if (r) {
            r.blur();
            remove(r);
        }
    }
});
var animationStyle = "opacity:0;transform:scale(1.2);transition:.1s opacity ease-out,.2s transform ease-out;";
var setInitialStyle = function (element) {
    if (!element.initialStyle) element.initialStyle = animationStyle;
};
var windowFactory = function (window) {
    css(window, `min-height:10px;min-width:10px;position:absolute;`);
    return window;
};
var loadingFactory = function (element) {
    css(element, `position:absolute;`);
    return element;
}
/**
 * 弹出子窗口的函数
 * @param {string} path 窗口路径的唯一索引
 * @param {any} parameters 给窗口的作域预先赋值
 * @param {object} style 自定义样式，主要是width,height等位置参数
 * @returns {Element} 给调用弹窗的命令暴露的可选方法
 */
var popup = function (path) {
    if (isString(path)) {
        return popup_path.apply(null, arguments);
    }
    if (isNode(path)) {
        return popup_view.apply(null, arguments);
    }
    throw new Error(`path isn't valid:${path}`);
};
var popup_path = function (path = "", parameters, target) {
    if (!popup.go || !popup.prepare) throw new Error("当前环境无法使用");
    // 3 has mask has view control
    var element;
    if (/^[#\+]/.test(path)) {
        // mask
        path = path.replace(/^[#\+]/, "");
        var load = function () {
            windowFactory(element);
            setInitialStyle(element);
            popup_with_mask(element, target);
            if (element.dragHandle) drag.on(element);
        };
    }
    // 2 has view control has no mask
    else if (/^@/.test(path)) {
        path = path.replace(/^@/, "");
        var load = function () {
            windowFactory(element);
            setInitialStyle(element);
            popup_as_single(element);
            if (element.dragHandle) drag.on(element);
        };
    }
    // 1 has mask has no control
    else if (/^!/.test(path)) {
        path = path.replace(/^!/, "");
        var load = function () {
            loadingFactory(element);
            setInitialStyle(element);
            popup_with_mask(element);
        };
    }
    // 0 has no mask no control
    else {
        var load = function () {
            loadingFactory(element);
            if (isNode(target)) {
                popup_as_extra(element, target);
            }
            else if (target instanceof Event) {
                popup_to_event(element, target);
            } else if (target instanceof Array) {
                popup_to_point(element, target);
            } else if (target) {
                popup_with_mask(element);
            } else {
                if (parameters !== false && target !== false) setInitialStyle(element);
                popup_as_single(element);
            }
        };
    }
    var fullfill = function () {
        remove(element);
        remove(element && element.mask);
        element = popup.create(path, parameters);
        if (!element) return;
        load();
        element.$reload = fullfill;
        if (!target && target !== false && parameters !== false) {
            element.style.opacity = 0;
            if (element.parentNode) move.bindPosition(element, [.5, .5]), element.style.opacity = 1;
            else once('append')(element, function () {
                move.bindPosition(element, [.5, .5]);
                element.style.opacity = 1;
            });
        }
        callbacks.forEach(f => f(element));
    };
    var callbacks = [];
    popup.prepare(path, fullfill);
    return element || {
        then(ok) {
            if (element) return ok(element);
            else callbacks.push(ok);
        }, fullfill
    };
};

var popup_view = function (element, target, style) {
    if (isNode(target)) {
        if (target.isMask) {
            popup_with_mask(element, target);
            return element;
        }
        return popup_as_extra(element, target, style);
    }
    if (target instanceof Event) {
        popup_to_event(element, target);
    } else if (target instanceof Array) {
        popup_to_point(element, target);
    } else if (target) {
        popup_with_mask(element);
    } else {
        popup_as_single(element);
    }
    return element;
};

css(".mask", `position:absolute;position:fixed;left:0;right:0;bottom:0;top:0;width:auto;height:auto;background:#000;opacity:0.2;transform:scale(1);display:block`);
var createMask = function (element) {
    var masks = element.with;
    if (masks) for (var cx = 0, dx = masks.length; cx < dx; cx++) {
        var m = masks[cx];
        if (m.isMask) return m;
    }
    var mask = document.createElement("mask");
    mask.initialStyle = animationStyle;
    css(mask, `z-index:${zIndex()};`);
    mask.className = "mask";
    mask.isMask = true;
    return mask;
};
var popup_with_mask = function (element, mask = createMask(element)) {
    css(element, `z-index:${zIndex()};`);
    if (mask.parentNode) {
        global(element, false);
    }
    if (!element.with) {
        element.with = [mask];
    } else if (element.with instanceof Array) {
        if (!~element.with.indexOf(element)) element.with.push(mask);
    } else {
        if (element.with !== element) element.with = [element.with, mask];
    }
    if (!mask.clean) {
        mask.clean = new Cleanup(element.with);
    }
    onremove(element, mask.clean);
    if (!element.parentNode) global(element, false);
    return element;
};
var isypop = function (target) {
    if (!target) return false;
    var { offsetParent, nextSibling, previousSibling } = target;
    if (
        nextSibling && nextSibling.tagName === target.tagName
        && (
            nextSibling.offsetLeft - target.offsetLeft >= target.offsetWidth / 2
            || target.offsetLeft - nextSibling.offsetLeft >= nextSibling.offsetWidth / 2
        )
        || previousSibling && previousSibling.tagName === target.tagName
        && (
            previousSibling.offsetLeft - target.offsetLeft >= target.offsetWidth / 2
            || target.offsetLeft - previousSibling.offsetLeft >= previousSibling.offsetWidth / 2
        )
    ) return true;
    var padding = parseFloat(getComputedStyle(offsetParent).paddingTop) + parseFloat(getComputedStyle(offsetParent).paddingBottom);
    if (offsetParent && target.offsetTop / target.offsetHeight < .2 && (offsetParent.clientWidth - padding) / target.offsetWidth > 1.5) return true;

};
var isxpop = arriswise(isypop, arguments);
var popup_as_extra = function (element, target, style) {
    element.target = target;
    if (style) {
        if (/^[vy]/i.test(style)) {
            popup_as_yextra(element, target, style);
            return;
        }
        if (/^[hx]/i.test(style)) {
            popup_as_xextra(element, target, style);
            return;
        }

    }
    if (isypop(target)) {
        popup_as_yextra(element, target, style);
    } else if (isxpop(target)) {
        popup_as_xextra(element, target, style);
    } else if (isypop(target.offsetParent)) {
        popup_as_yextra(element, target, style);
    } else if (isxpop(target.offsetParent)) {
        popup_as_xextra(element, target, style);
    } else {
        if (/inline|cell/i.test(getComputedStyle(target).display)) {
            popup_as_yextra(element, target, style);
        } else {
            popup_as_xextra(element, target, style);
        }
    }

};
var _as_yextra = function (global, innerWidth, innerHeight, element, target, pointer) {
    var withRhomb = pointer && /rhomb|rhombus|diamond|lozenge|triangle|[drlt]$/i.test(pointer);
    if (withRhomb) {
        var _rhomb = rhomb();
    }
    if (!element.origin) {
        element.origin = {
            height: element.style.height,
            width: element.style.width,
            minWidth: element.style.minWidth,
            display: element.style.display
        };
    }
    var zindex = zIndex();
    css(element, `position:absolute;z-index:${zindex}`);
    css(_rhomb, { zIndex: zindex });
    var release1 = onremove(target, function () {
        remove(element);
    });
    var release2 = onremove(element, function () {
        release1();
        release2();
        remove(_rhomb);
        if (document.removeEventListener) {
            document.removeEventListener("scroll", reshape, true);
            window.removeEventListener("resize", reshape);
        }
    });
    global(element, false);
    var reshape = function () {
        extend(element.style, element.origin);
        var position = getScreenPosition(target);
        var viewrect = getScreenPosition(element.offsetParent);
        var documentbody = document.body;
        if (element.offsetParent === documentbody && !/^(absolute|relative|fixed)$/i.test(getComputedStyle(documentbody).position)) {
            viewrect.left = 0;
            viewrect.top = 0;
            viewrect.right += innerWidth - viewrect.right;
            viewrect.bottom += innerHeight - viewrect.bottom;
            viewrect.width = viewrect.right - viewrect.left;
            viewrect.height = viewrect.bottom - viewrect.top;
        } else {
            viewrect.top += documentbody.clientTop;
            viewrect.left += documentbody.clientLeft;
            viewrect.height = documentbody.clientHeight;
            viewrect.width = documentbody.clientWidth;
            viewrect.right = viewrect.left + viewrect.width;
            viewrect.bottom = viewrect.top + viewrect.height;
        }
        var maxHeight = Math.max(position.top, innerHeight - position.top - position.height) | 0;
        var maxWidth = Math.max(position.left + position.width, innerWidth - position.left);
        var height = element.offsetHeight;
        //如果高度超出可视区，调整高度
        if (height > maxHeight) {
            css(element, { height: fromOffset(maxHeight), maxHeight: fromOffset(maxHeight) });
        }

        css(element, `min-width:auto;`);
        var aimedWidth = getScreenPosition(element).width;
        //如果宽度不足其附着元素的宽度
        if (aimedWidth < position.width) {
            aimedWidth = position.width;
        }

        //如果宽度超出可视区，调整宽度
        if (aimedWidth > maxWidth) {
            aimedWidth = maxWidth;
        }
        var side;
        if (aimedWidth !== element.offsetWidth) {
            css(element, { width: fromOffset(aimedWidth) });
        }
        if (position.top + element.offsetHeight + position.height > innerHeight) {
            side = 'bottom';
            var temp = `bottom:${fromOffset(viewrect.height - position.top + viewrect.top)};top:auto;`;
        } else {
            side = 'top';
            var temp = `top:${fromOffset(position.top - viewrect.top + position.height)};bottom:auto;`
        }
        css(element, temp);
        if (_rhomb) {
            css(_rhomb, temp);
            _rhomb.setSide(side);
        }
        if (_rhomb) {
            var targetX = position.left + (position.width - element.offsetWidth) / 2;
            if (targetX < 0) {
                css(element, `left:0;right:auto`);
                css(_rhomb, `left:${fromOffset(position.left + position.width / 2)};right:auto`);
            }
            else if (targetX + element.offsetWidth > innerWidth) {
                css(element, `right:0;left:auto`);
                css(_rhomb, `right:${fromOffset(innerWidth - position.left - position.width / 2)};left:auto`);
            }
            else {
                css(element, `left:${fromOffset(targetX)};right:auto`);
                css(_rhomb, `left:${fromOffset(position.left + position.width / 2)};right:auto`);

            }
        } else {
            if (position.left + element.offsetWidth > innerWidth) {
                css(element, `right:${fromOffset(viewrect.width + viewrect.left - position.left - position.width)};left:auto;`);
            }
            else {
                css(element, `left:${fromOffset(position.left - viewrect.left)};right:auto;`);
            }
        }

        var offsetParent = target.offsetParent;
        if (offsetParent) {
            if (overlap(target, offsetParent) > 0) {
                element.style.display = element.origin.display;
                if (_rhomb && !_rhomb.parentNode) {
                    appendChild.before(element, _rhomb)
                }
            } else {
                element.style.display = "none";
                remove(_rhomb);
            };
        } else if (_rhomb && !_rhomb.parentNode) {
            appendChild.before(element, _rhomb)
        }
    }
    if (document.addEventListener) {
        document.addEventListener("scroll", reshape, true);
        window.addEventListener("resize", reshape);
    }
    reshape();
    lazy(reshape)();
};
var _as_xextra = arriswise(_as_yextra, arguments);
var popup_as_single = function (element) {
    css(element, `z-index:${zIndex()};`);
    global(element, false);
};
var popup_to_point = function (element, [x, y]) {
    if (x <= 1 && y <= 1 && x >= 0 && y >= 0) {
        popup_as_single(element);
        move.bindPosition(element, [x, y]);
    } else {
        x = calcPixel(x), y = calcPixel(y);
        popup_fixup(element, x, y);
    }
};
var popup_fixup = function (element, x, y) {
    css(element, {
        position: 'absolute',
    });
    popup_as_single(element);
    var left = "left", top = 'top';
    if (y + element.offsetHeight > window.innerHeight && y << 1 > window.innerHeight) {
        top = "bottom";
        y = window.innerHeight - y;
    }
    if (x + element.offsetWidth > window.innerWidth && x << 1 > window.innerWidth) {
        left = "right";
        x = window.innerWidth - x;
    }
    css(element, {
        [left]: fromOffset(x),
        [top]: fromOffset(y)
    });

};
var popup_to_event = function (element, { clientX, clientY }) {
    popup_fixup(element, clientX, clientY);
};
var global = function (element, issingle) {
    once("remove")(element, cleanup);
    rootElements.push(element);
    popup.global &&
        issingle !== false ? popup.global(element, true) : appendChild(document.body, element);
};
var popup_as_yextra = _as_yextra.bind(null, global, innerWidth, innerHeight);
var popup_as_xextra = _as_xextra.bind(null, global, innerHeight, innerWidth);
var cleanup = new Cleanup(rootElements);<|endoftext|>


<commit_before>/**
 * Created by Kyle on 1/10/2016.
 */
import React from 'react';
import { render } from 'react-dom';
import App from './Containers/App';

'use strict';

const actionEvents = {
  "left": {
    className: "action-work",
    actionColor: "#004070",
    text: "Work"
  },
  "right": {
    className: "action-delete",
    actionColor: "#CC0000",
    text: "Delete"
  }
};

const listItems = [{
  text: "Text"
}, {
  text: "Random"
}];

render(<App
  actionEvents={actionEvents}
  listItems={listItems}
/>, document.getElementById("app"));
<commit_msg>Fixed example webpack; app runs but errors still in package<commit_after>/**
 * Created by Kyle on 1/10/2016.
 */
import React from 'react';
import { render } from 'react-dom';
import App from './Containers/App';

'use strict';

const actionEvents = {
  "left": {
    className: "action-work",
    actionColor: "#004070",
    text: "Work"
  },
  "right": {
    className: "action-delete",
    actionColor: "#CC0000",
    text: "Delete"
  }
};

const listItems = [{
  text: "Text"
}, {
  text: "Random"
}];

render(<App
  actionEvents={actionEvents}
  listItems={listItems}
/>, document.getElementById("root"));
<|endoftext|>


<commit_before>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           ______     ______     ______   __  __     __     ______
          /\  == \   /\  __ \   /\__  _\ /\ \/ /    /\ \   /\__  _\
          \ \  __<   \ \ \/\ \  \/_/\ \/ \ \  _"-.  \ \ \  \/_/\ \/
           \ \_____\  \ \_____\    \ \_\  \ \_\ \_\  \ \_\    \ \_\
            \/_____/   \/_____/     \/_/   \/_/\/_/   \/_/     \/_/

This is a sample Slack Button application that adds a bot to one or many slack teams.

# RUN THE APP:
  Create a Slack app. Make sure to configure the bot user!
    -> https://api.slack.com/applications/new
  Run your bot from the command line:
    clientId=<my client id> clientSecret=<my client secret> port=3000 node slackbutton_bot.js
# USE THE APP
  Add the app to your Slack by visiting the login page:
    -> http://localhost:3000/login
  After you've added the app, try talking to your bot!
# EXTEND THE APP:
  Botkit is has many features for building cool and useful bots!
  Read all about it here:
    -> http://howdy.ai/botkit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/* Uses the slack button feature to offer a real time bot to multiple teams */
var Botkit = require('../lib/Botkit.js');

if (!process.env.clientId || !process.env.clientSecret || !process.env.port) {
  console.log('Error: Specify clientId clientSecret and port in environment');
  process.exit(1);
}

var controller = Botkit.slackbot({
  json_file_store: './db_slackbutton_bot/',
}).configureSlackApp(
  {
    clientId: process.env.clientId,
    clientSecret: process.env.clientSecret,
    scopes: ['bot'],
  }
);

controller.setupWebserver(process.env.port,function(err,webserver) {
  controller.createWebhookEndpoints(controller.webserver);

  controller.createOauthEndpoints(controller.webserver,function(err,req,res) {
    if (err) {
      res.status(500).send('ERROR: ' + err);
    } else {
      res.send('Success!');
    }
  });
});

// just a simple way to make sure we don't
// connect to the RTM twice for the same team
var _bots = {};
function trackBot(bot) {
  _bots[bot.config.token] = bot;
}

controller.on('create_bot',function(bot,config) {

  if (_bots[bot.config.token]) {
    // already online! do nothing.
  } else {
    bot.startRTM(function(err) {

      if (!err) {
        trackBot(bot);
      }

      bot.startPrivateConversation({user: config.createdBy},function(err,convo) {
        if (err) {
          console.log(err);
        } else {
          convo.say('I am a bot that has just joined your team');
          convo.say('You must now /invite me to a channel so that I can be of use!');
        }
      });

    });
  }

});

// Handle events related to the websocket connection to Slack
controller.on('rtm_open',function(bot) {
  console.log('** The RTM api just connected!');
});

controller.on('rtm_close',function(bot) {
  console.log('** The RTM api just closed');
  // you may want to attempt to re-open
});

controller.hears('hello','direct_message',function(bot,message) {
  bot.reply(message,'Hello!');
});

controller.hears('^stop','direct_message',function(bot,message) {
  bot.reply(message,'Goodbye');
  bot.rtm.close();
});

controller.on(['direct_message','mention','direct_mention'],function(bot,message) {
  bot.api.reactions.add({
    timestamp: message.ts,
    channel: message.channel,
    name: 'robot_face',
  },function(err) {
    if (err) { console.log(err) }
    bot.reply(message,'I heard you loud and clear boss.');
  });
});

controller.storage.teams.all(function(err,teams) {

  if (err) {
    throw new Error(err);
  }

  // connect all teams with bots up to slack!
  for (var t  in teams) {
    if (teams[t].bot) {
      controller.spawn(teams[t]).startRTM(function(err, bot) {
        if (err) {
          console.log('Error connecting bot to Slack:',err);
        } else {
          trackBot(bot);
        }
      });
    }
  }

});
<commit_msg>Update slackbutton_bot.js<commit_after>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           ______     ______     ______   __  __     __     ______
          /\  == \   /\  __ \   /\__  _\ /\ \/ /    /\ \   /\__  _\
          \ \  __<   \ \ \/\ \  \/_/\ \/ \ \  _"-.  \ \ \  \/_/\ \/
           \ \_____\  \ \_____\    \ \_\  \ \_\ \_\  \ \_\    \ \_\
            \/_____/   \/_____/     \/_/   \/_/\/_/   \/_/     \/_/

This is a sample Slack Button application that adds a bot to one or many slack teams.

# RUN THE APP:
  Create a Slack app. Make sure to configure the bot user!
    -> https://api.slack.com/applications/new
    -> Add the Redirect URI: http://localhost:3000/oauth
  Run your bot from the command line:
    clientId=<my client id> clientSecret=<my client secret> port=3000 node slackbutton_bot.js
# USE THE APP
  Add the app to your Slack by visiting the login page:
    -> http://localhost:3000/login
  After you've added the app, try talking to your bot!
# EXTEND THE APP:
  Botkit is has many features for building cool and useful bots!
  Read all about it here:
    -> http://howdy.ai/botkit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/* Uses the slack button feature to offer a real time bot to multiple teams */
var Botkit = require('../lib/Botkit.js');

if (!process.env.clientId || !process.env.clientSecret || !process.env.port) {
  console.log('Error: Specify clientId clientSecret and port in environment');
  process.exit(1);
}

var controller = Botkit.slackbot({
  json_file_store: './db_slackbutton_bot/',
}).configureSlackApp(
  {
    clientId: process.env.clientId,
    clientSecret: process.env.clientSecret,
    scopes: ['bot'],
  }
);

controller.setupWebserver(process.env.port,function(err,webserver) {
  controller.createWebhookEndpoints(controller.webserver);

  controller.createOauthEndpoints(controller.webserver,function(err,req,res) {
    if (err) {
      res.status(500).send('ERROR: ' + err);
    } else {
      res.send('Success!');
    }
  });
});

// just a simple way to make sure we don't
// connect to the RTM twice for the same team
var _bots = {};
function trackBot(bot) {
  _bots[bot.config.token] = bot;
}

controller.on('create_bot',function(bot,config) {

  if (_bots[bot.config.token]) {
    // already online! do nothing.
  } else {
    bot.startRTM(function(err) {

      if (!err) {
        trackBot(bot);
      }

      bot.startPrivateConversation({user: config.createdBy},function(err,convo) {
        if (err) {
          console.log(err);
        } else {
          convo.say('I am a bot that has just joined your team');
          convo.say('You must now /invite me to a channel so that I can be of use!');
        }
      });

    });
  }

});

// Handle events related to the websocket connection to Slack
controller.on('rtm_open',function(bot) {
  console.log('** The RTM api just connected!');
});

controller.on('rtm_close',function(bot) {
  console.log('** The RTM api just closed');
  // you may want to attempt to re-open
});

controller.hears('hello','direct_message',function(bot,message) {
  bot.reply(message,'Hello!');
});

controller.hears('^stop','direct_message',function(bot,message) {
  bot.reply(message,'Goodbye');
  bot.rtm.close();
});

controller.on(['direct_message','mention','direct_mention'],function(bot,message) {
  bot.api.reactions.add({
    timestamp: message.ts,
    channel: message.channel,
    name: 'robot_face',
  },function(err) {
    if (err) { console.log(err) }
    bot.reply(message,'I heard you loud and clear boss.');
  });
});

controller.storage.teams.all(function(err,teams) {

  if (err) {
    throw new Error(err);
  }

  // connect all teams with bots up to slack!
  for (var t  in teams) {
    if (teams[t].bot) {
      controller.spawn(teams[t]).startRTM(function(err, bot) {
        if (err) {
          console.log('Error connecting bot to Slack:',err);
        } else {
          trackBot(bot);
        }
      });
    }
  }

});
<|endoftext|>