<commit_before>var redis = require('redis');

/**
 * redisCacheModule constructor
 * @constructor
 * @param config: {
 *    type:                           {string | 'redis'}
 *    verbose:                        {boolean | false},
 *    expiration:                     {integer | 900},
 *    readOnly:                       {boolean | false},
 *    checkOnPreviousEmpty            {boolean | true},
 *    backgroundRefreshIntervalCheck  {boolean | true},
 *    backgroundRefreshInterval       {integer | 60000},
 *    backgroundRefreshMinTtl         {integer | 70000},
 *    redisData:                      {object},
 *    redisUrl:                       {string},
 *    redisEnv:                       {string}
 * }
 */
function redisCacheModule(config){
  var self = this;
  config = config || {};
  self.verbose = config.verbose || false;
  self.defaultExpiration = config.defaultExpiration || 900;
  self.readOnly = (typeof config.readOnly === 'boolean') ? config.readOnly : false;
  self.checkOnPreviousEmpty = (typeof config.checkOnPreviousEmpty === 'boolean') ? config.checkOnPreviousEmpty : true;
  self.backgroundRefreshIntervalCheck = (typeof config.backgroundRefreshIntervalCheck === 'boolean') ? config.backgroundRefreshIntervalCheck : true;
  self.backgroundRefreshInterval = config.backgroundRefreshInterval || 60000;
  self.backgroundRefreshMinTtl = config.backgroundRefreshMinTtl || 70000;
  var refreshKeys = {};
  var backgroundRefreshEnabled = false;

  var noop = function(){};

  /**
   * Instantates an Exception to be thrown
   * @param {string} name
   * @param {string} message
   * @return {Exception}
   */
  function Exception(name, message){
    this.name = name;
    this.message = message;
  }

  /**
   * Error logging logic
   * @param {boolean} isError
   * @param {string} message
   * @param {object} data
   */
  function log(isError, message, data){
    var indentifier = 'redisCacheModule: ';
    if(self.verbose || isError){
      if(data) {
        console.log(indentifier + message, data);
      } else {
        console.log(indentifier + message);
      }
    }
  }

  /**
   * Refreshes all keys that were set with a refresh function
   */
  function backgroundRefresh(){
    for(var key in refreshKeys){
      if(refreshKeys.hasOwnProperty(key)){
        var data = refreshKeys[key];
        if(data.expiration - Date.now() < self.backgroundRefreshMinTtl){
          data.refresh(key, function (err, response) {
            if(!err){
              self.set(key, response, data.lifeSpan, data.refresh, noop);
            }
          });
        }
      }
    }
  }

  /**
   * Initialize background refresh
   */
  function backgroundRefreshInit(){
    if(!backgroundRefreshEnabled){
      backgroundRefreshEnabled = true;
      if(self.backgroundRefreshIntervalCheck){
        if(self.backgroundRefreshInterval > self.backgroundRefreshMinTtl){
          throw new Exception('BACKGROUND_REFRESH_INTERVAL_EXCEPTION', 'backgroundRefreshInterval cannot be greater than backgroundRefreshMinTtl.');
        }
      }
      setInterval(function(){
        backgroundRefresh();
      }, self.backgroundRefreshInterval);
    }
  }

  /**
   ******************************************* PUBLIC FUNCTIONS *******************************************
   */

  /**
   * Get the value associated with a given key
   * @param {string} key
   * @param {function} cb
   * @param {string} cleanKey
   */
  self.get = function(key, cb, cleanKey){
    if(arguments.length < 2){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.get() requires 2 arguments.');
    }
    log(false, 'get() called:', {key: key});
    try {
      var cacheKey = (cleanKey) ? cleanKey : key;
      log(false, 'Attempting to get key:', {key: cacheKey});
      self.db.get(cacheKey, function(err, result){
        try {
          result = JSON.parse(result);
        } catch (err) {
          //Do nothing
        }
        cb(err, result);
      });
    } catch (err) {
      cb({name: 'GetException', message: err}, null);
    }
  };

  /**
   * Get multiple values given multiple keys
   * @param {array} keys
   * @param {function} cb
   * @param {integer} index
   */
  self.mget = function(keys, cb, index){
    if(arguments.length < 2){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.mget() requires 2 arguments.');
    }
    log(false, '.mget() called:', {keys: keys});
    self.db.mget(keys, function (err, response){
      var obj = {};
      for(var i = 0; i < response.length; i++){
        if(response[i] !== null){
          try {
            response[i] = JSON.parse(response[i]);
          } catch (err) {
            //Do nothing
          }
          obj[keys[i]] = response[i];
        }
      }
      cb(err, obj, index);
    });
  };

  /**
   * Associate a key and value and optionally set an expiration
   * @param {string} key
   * @param {string | object} value
   * @param {integer} expiration
   * @param {function} refresh
   * @param {function} cb
   */
  self.set = function(){
    if(arguments.length < 2){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.set() requires a minimum of 2 arguments.');
    }
    var key = arguments[0];
    var value = arguments[1];
    var expiration = arguments[2] || null;
    var refresh = (arguments.length === 5) ? arguments[3] : null;
    var cb = (arguments.length === 5) ? arguments[4] : arguments[3];
    cb = cb || noop;
    log(false, '.set() called:', {key: key, value: value});
    try {
      if(!self.readOnly){
        expiration = expiration || self.defaultExpiration;
        var exp = (expiration * 1000) + Date.now();
        if(typeof value === 'object'){
          try {
            value = JSON.stringify(value);
          } catch (err) {
            //Do nothing
          }
        }
        if(refresh){
          self.db.set(key, value, 'nx', 'ex', expiration, function (err, response){

            refreshKeys[key] = {expiration: exp, lifeSpan: expiration, refresh: refresh};

            if(!err && response){
              cb(err, response);
              backgroundRefreshInit();
            }
            else{
              self.db.setex(key, expiration, value, cb);
            }
          });
        }
        else{
          self.db.setex(key, expiration, value, cb);
        }
      }
    }catch (err) {
      log(true, '.set() failed for cache of type ' + self.type, {name: 'RedisSetException', message: err});
    }
  };

  /**
   * Associate multiple keys with multiple values and optionally set expirations per function and/or key
   * @param {object} obj
   * @param {integer} expiration
   * @param {function} cb
   */
  self.mset = function(obj, expiration, cb){
    if(arguments.length < 1){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.mset() requires a minimum of 1 argument.');
    }
    log(false, '.mset() called:', {data: obj});
    var multi = self.db.multi();
    for(var key in obj){
      if(obj.hasOwnProperty(key)){
        var tempExpiration = expiration || self.defaultExpiration;
        var value = obj[key];
        if(typeof value === 'object' && value.cacheValue){
          tempExpiration = value.expiration || tempExpiration;
          value = value.cacheValue;
        }
        try {
          value = JSON.stringify(value);
        } catch (err) {
          //Do nothing
        }
        multi.setex(key, tempExpiration, value);
      }
    }
    multi.exec(function (err, replies){
      if(cb) {
        cb(err, replies);
      }
    });
  };

  /**
   * Delete the provided keys and their associated values
   * @param {array} keys
   * @param {function} cb
   */
  self.del = function(keys, cb){
    if(arguments.length < 1){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.del() requires a minimum of 1 argument.');
    }
    log(false, '.del() called:', {keys: keys});
    try {
      self.db.del(keys, function (err, count){
        if(cb){
          cb(err, count);
        }
      });
      if(typeof keys === 'object'){
        for(var i = 0; i < keys.length; i++){
          var key = keys[i];
          delete refreshKeys[key];
        }
      }
      else{
        delete refreshKeys[keys];
      }
    } catch (err) {
      log(true, '.del() failed for cache of type ' + self.type, err);
    }
  };

  /**
   * Flush all keys and values from all configured caches in cacheCollection
   * @param {function} cb
   */
  self.flush = function(cb){
    log(false, '.flush() called');
    try {
      self.db.flushall();
      refreshKeys = {};
    } catch (err) {
      log(true, '.flush() failed for cache of type ' + self.type, err);
    }
    if(cb) {
      cb();
    }
  };

  /**
   ******************************************* PRIVATE FUNCTIONS *******************************************
   */

  /**
   * Initialize redisCacheModule given the provided constructor params
   */
  function init(){
    self.type = config.type || 'redis';
    if(config.redisMock){
      self.db = config.redisMock;
    }
    else{
      if(config.redisUrl){
        self.redisData = config.redisUrl || null;
      }
      else if(config.redisEnv){
        self.redisData = process.env[config.redisEnv] || null;
      }
      else if(config.redisData){
        self.redisData = config.redisData;
      }
      self.readOnly = (typeof config.readOnly === 'boolean') ? config.readOnly : false;
      try {
        if (self.redisData) {
          if(typeof self.redisData === 'string'){
            var redisURL = require('url').parse(self.redisData);
            self.db = redis.createClient(redisURL.port, redisURL.hostname,
              {'no_ready_check': true, 'max_attempts': 5});
            if (redisURL.auth !== null) {
              self.db.auth(redisURL.auth.split(':')[1]);
            }
          } else {
            self.db = redis.createClient(self.redisData.port,
              self.redisData.hostname, {'no_ready_check': true, 'max_attempts': 5});
            self.db.auth(self.redisData.auth);
          }
          self.db.on('error', function(err) {
            console.log('Error ' + err);
          });
          process.on('SIGTERM', function() {
            self.db.quit();
          });
          log(false, 'Redis client created with the following defaults:', {expiration: self.defaultExpiration, verbose: self.verbose, readOnly: self.readOnly});
        } else {
          self.db = false;
          log(false, 'Redis client not created: no redis config provided');
        }
      } catch (err) {
        self.db = false;
        log(true, 'Redis client not created:', err);
      }
    }
  }

  init();
}

module.exports = redisCacheModule;
<commit_msg>Fix the issue with multiple cache refreshes. Fixes #7<commit_after>var redis = require('redis');
var Promise = require('bluebird');

/**
 * redisCacheModule constructor
 * @constructor
 * @param config: {
 *    type:                           {string | 'redis'}
 *    verbose:                        {boolean | false},
 *    expiration:                     {integer | 900},
 *    readOnly:                       {boolean | false},
 *    checkOnPreviousEmpty            {boolean | true},
 *    backgroundRefreshIntervalCheck  {boolean | true},
 *    backgroundRefreshInterval       {integer | 60000},
 *    backgroundRefreshMinTtl         {integer | 70000},
 *    redisData:                      {object},
 *    redisUrl:                       {string},
 *    redisEnv:                       {string}
 * }
 */
function redisCacheModule(config){
  var self = this;
  config = config || {};
  self.verbose = config.verbose || false;
  self.defaultExpiration = config.defaultExpiration || 900;
  self.readOnly = (typeof config.readOnly === 'boolean') ? config.readOnly : false;
  self.checkOnPreviousEmpty = (typeof config.checkOnPreviousEmpty === 'boolean') ? config.checkOnPreviousEmpty : true;
  self.backgroundRefreshIntervalCheck = (typeof config.backgroundRefreshIntervalCheck === 'boolean') ? config.backgroundRefreshIntervalCheck : true;
  self.backgroundRefreshInterval = config.backgroundRefreshInterval || 60000;
  self.backgroundRefreshMinTtl = config.backgroundRefreshMinTtl || 70000;
  var refreshKeys = {};
  var backgroundRefreshEnabled = false;

  var noop = function(){};

  /**
   * Instantates an Exception to be thrown
   * @param {string} name
   * @param {string} message
   * @return {Exception}
   */
  function Exception(name, message){
    this.name = name;
    this.message = message;
  }

  /**
   * Error logging logic
   * @param {boolean} isError
   * @param {string} message
   * @param {object} data
   */
  function log(isError, message, data){
    var indentifier = 'redisCacheModule: ';
    if(self.verbose || isError){
      if(data) {
        console.log(indentifier + message, data);
      } else {
        console.log(indentifier + message);
      }
    }
  }

  /**
   * Refreshes all keys that were set with a refresh function
   */
  function backgroundRefresh() {
    var keys = Object.keys(refreshKeys);
    Promise.resolve(keys)
      .map(function(key) {
        var data = refreshKeys[key];
        if(data.expiration - Date.now() < self.backgroundRefreshMinTtl){
          data.refresh(key, function (err, response) {
            if(!err) {
              self.set(key, response, data.lifeSpan, data.refresh, noop);
            }
          });
        }
      });
  }

  /**
   * Initialize background refresh
   */
  function backgroundRefreshInit(){
    if(!backgroundRefreshEnabled){
      backgroundRefreshEnabled = true;
      if(self.backgroundRefreshIntervalCheck){
        if(self.backgroundRefreshInterval > self.backgroundRefreshMinTtl){
          throw new Exception('BACKGROUND_REFRESH_INTERVAL_EXCEPTION', 'backgroundRefreshInterval cannot be greater than backgroundRefreshMinTtl.');
        }
      }
      setInterval(function(){
        backgroundRefresh();
      }, self.backgroundRefreshInterval);
    }
  }

  /**
   ******************************************* PUBLIC FUNCTIONS *******************************************
   */

  /**
   * Get the value associated with a given key
   * @param {string} key
   * @param {function} cb
   * @param {string} cleanKey
   */
  self.get = function(key, cb, cleanKey){
    if(arguments.length < 2){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.get() requires 2 arguments.');
    }
    log(false, 'get() called:', {key: key});
    try {
      var cacheKey = (cleanKey) ? cleanKey : key;
      log(false, 'Attempting to get key:', {key: cacheKey});
      self.db.get(cacheKey, function(err, result){
        try {
          result = JSON.parse(result);
        } catch (err) {
          //Do nothing
        }
        cb(err, result);
      });
    } catch (err) {
      cb({name: 'GetException', message: err}, null);
    }
  };

  /**
   * Get multiple values given multiple keys
   * @param {array} keys
   * @param {function} cb
   * @param {integer} index
   */
  self.mget = function(keys, cb, index){
    if(arguments.length < 2){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.mget() requires 2 arguments.');
    }
    log(false, '.mget() called:', {keys: keys});
    self.db.mget(keys, function (err, response){
      var obj = {};
      for(var i = 0; i < response.length; i++){
        if(response[i] !== null){
          try {
            response[i] = JSON.parse(response[i]);
          } catch (err) {
            //Do nothing
          }
          obj[keys[i]] = response[i];
        }
      }
      cb(err, obj, index);
    });
  };

  /**
   * Associate a key and value and optionally set an expiration
   * @param {string} key
   * @param {string | object} value
   * @param {integer} expiration
   * @param {function} refresh
   * @param {function} cb
   */
  self.set = function(){
    if(arguments.length < 2){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.set() requires a minimum of 2 arguments.');
    }
    var key = arguments[0];
    var value = arguments[1];
    var expiration = arguments[2] || null;
    var refresh = (arguments.length === 5) ? arguments[3] : null;
    var cb = (arguments.length === 5) ? arguments[4] : arguments[3];
    cb = cb || noop;
    log(false, '.set() called:', {key: key, value: value});
    try {
      if(!self.readOnly){
        expiration = expiration || self.defaultExpiration;
        var exp = (expiration * 1000) + Date.now();
        if(typeof value === 'object'){
          try {
            value = JSON.stringify(value);
          } catch (err) {
            //Do nothing
          }
        }
        if(refresh){
          self.db.set(key, value, 'nx', 'ex', expiration, function (err, response){

            refreshKeys[key] = {expiration: exp, lifeSpan: expiration, refresh: refresh};

            if(!err && response){
              cb(err, response);
              backgroundRefreshInit();
            }
            else{
              self.db.setex(key, expiration, value, cb);
            }
          });
        }
        else{
          self.db.setex(key, expiration, value, cb);
        }
      }
    }catch (err) {
      log(true, '.set() failed for cache of type ' + self.type, {name: 'RedisSetException', message: err});
    }
  };

  /**
   * Associate multiple keys with multiple values and optionally set expirations per function and/or key
   * @param {object} obj
   * @param {integer} expiration
   * @param {function} cb
   */
  self.mset = function(obj, expiration, cb){
    if(arguments.length < 1){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.mset() requires a minimum of 1 argument.');
    }
    log(false, '.mset() called:', {data: obj});
    var multi = self.db.multi();
    for(var key in obj){
      if(obj.hasOwnProperty(key)){
        var tempExpiration = expiration || self.defaultExpiration;
        var value = obj[key];
        if(typeof value === 'object' && value.cacheValue){
          tempExpiration = value.expiration || tempExpiration;
          value = value.cacheValue;
        }
        try {
          value = JSON.stringify(value);
        } catch (err) {
          //Do nothing
        }
        multi.setex(key, tempExpiration, value);
      }
    }
    multi.exec(function (err, replies){
      if(cb) {
        cb(err, replies);
      }
    });
  };

  /**
   * Delete the provided keys and their associated values
   * @param {array} keys
   * @param {function} cb
   */
  self.del = function(keys, cb){
    if(arguments.length < 1){
      throw new Exception('INCORRECT_ARGUMENT_EXCEPTION', '.del() requires a minimum of 1 argument.');
    }
    log(false, '.del() called:', {keys: keys});
    try {
      self.db.del(keys, function (err, count){
        if(cb){
          cb(err, count);
        }
      });
      if(typeof keys === 'object'){
        for(var i = 0; i < keys.length; i++){
          var key = keys[i];
          delete refreshKeys[key];
        }
      }
      else{
        delete refreshKeys[keys];
      }
    } catch (err) {
      log(true, '.del() failed for cache of type ' + self.type, err);
    }
  };

  /**
   * Flush all keys and values from all configured caches in cacheCollection
   * @param {function} cb
   */
  self.flush = function(cb){
    log(false, '.flush() called');
    try {
      self.db.flushall();
      refreshKeys = {};
    } catch (err) {
      log(true, '.flush() failed for cache of type ' + self.type, err);
    }
    if(cb) {
      cb();
    }
  };

  /**
   ******************************************* PRIVATE FUNCTIONS *******************************************
   */

  /**
   * Initialize redisCacheModule given the provided constructor params
   */
  function init(){
    self.type = config.type || 'redis';
    if(config.redisMock){
      self.db = config.redisMock;
    }
    else{
      if(config.redisUrl){
        self.redisData = config.redisUrl || null;
      }
      else if(config.redisEnv){
        self.redisData = process.env[config.redisEnv] || null;
      }
      else if(config.redisData){
        self.redisData = config.redisData;
      }
      self.readOnly = (typeof config.readOnly === 'boolean') ? config.readOnly : false;
      try {
        if (self.redisData) {
          if(typeof self.redisData === 'string'){
            var redisURL = require('url').parse(self.redisData);
            self.db = redis.createClient(redisURL.port, redisURL.hostname,
              {'no_ready_check': true, 'max_attempts': 5});
            if (redisURL.auth !== null) {
              self.db.auth(redisURL.auth.split(':')[1]);
            }
          } else {
            self.db = redis.createClient(self.redisData.port,
              self.redisData.hostname, {'no_ready_check': true, 'max_attempts': 5});
            self.db.auth(self.redisData.auth);
          }
          self.db.on('error', function(err) {
            console.log('Error ' + err);
          });
          process.on('SIGTERM', function() {
            self.db.quit();
          });
          log(false, 'Redis client created with the following defaults:', {expiration: self.defaultExpiration, verbose: self.verbose, readOnly: self.readOnly});
        } else {
          self.db = false;
          log(false, 'Redis client not created: no redis config provided');
        }
      } catch (err) {
        self.db = false;
        log(true, 'Redis client not created:', err);
      }
    }
  }

  init();
}

module.exports = redisCacheModule;
<|endoftext|>


<commit_before>/**
 * @file TipBody component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';
import PropTypes from 'prop-types';
import _ from 'lodash';

import Paper from '../Paper';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import PopupCalculation from '../_vendors/PopupCalculation';

import Position from '../_statics/Position';

export default class TipBody extends Component {

    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.hasMounted = false;
        this.prepareCloseTimeout = null;
        this.requestCloseTimeout = null;

        this.state = {
            visible: false
        };

        this.triggerMouseEnterHandler = ::this.triggerMouseEnterHandler;
        this.triggerMouseLeaveHandler = ::this.triggerMouseLeaveHandler;
        this.resizeHandler = ::this.resizeHandler;
        this.debounceResizeHandle = _.debounce(::this.debounceResizeHandle, 150);
        this.initializeAnimation = ::this.initializeAnimation;
        this.animate = ::this.animate;

    }

    triggerMouseEnterHandler() {
        this.prepareCloseTimeout && clearTimeout(this.prepareCloseTimeout);
    }

    triggerMouseLeaveHandler() {
        this.prepareCloseTimeout && clearTimeout(this.prepareCloseTimeout);
        this.prepareCloseTimeout = setTimeout(() => {
            this.setState({
                visible: false
            }, () => {
                this.requestCloseTimeout && clearTimeout(this.requestCloseTimeout);
                this.requestCloseTimeout = setTimeout(() => {
                    const {onRequestClose} = this.props;
                    this.hasMounted && onRequestClose && onRequestClose();
                }, 250);
            });
        }, 100);
    }

    resizeHandler() {
        this.debounceResizeHandle();
    }

    debounceResizeHandle() {
        this.forceUpdate();
    }

    initializeAnimation(callback) {
        setTimeout(() => {
            this.hasMounted && callback();
        }, 0);
    }

    animate() {
        this.setState({
            visible: true
        });
    }

    componentDidMount() {

        this.hasMounted = true;
        this.tipEl = findDOMNode(this.refs.tip);

        Event.addEvent(this.props.triggerEl, 'mouseenter', this.triggerMouseEnterHandler);
        Event.addEvent(this.props.triggerEl, 'mouseleave', this.triggerMouseLeaveHandler);
        Event.addEvent(window, 'resize', this.resizeHandler);

    }

    componentWillAppear(callback) {
        this.initializeAnimation(callback);
    }

    componentDidAppear() {
        this.animate();
    }

    componentDidUpdate() {
        const {onRender} = this.props,
            {visible} = this.state;
        visible && onRender && onRender(this.tipEl, this.props.triggerEl);
    }

    componentWillUnmount() {

        this.hasMounted = false;
        this.prepareCloseTimeout && clearTimeout(this.prepareCloseTimeout);
        this.requestCloseTimeout && clearTimeout(this.requestCloseTimeout);

        Event.removeEvent(this.props.triggerEl, 'mouseenter', this.triggerMouseEnterHandler);
        Event.removeEvent(this.props.triggerEl, 'mouseleave', this.triggerMouseLeaveHandler);
        Event.removeEvent(window, 'resize', this.resizeHandler);

    }

    render() {

        const {
                children, className, style, theme, hasTriangle, triangle, position, isAnimated, depth,
                triggerEl, isTriggerPositionFixed
            } = this.props,
            {visible} = this.state,

            tipClassName = (visible ? '' : ' hidden') + (hasTriangle ? ' tip-has-triangle' : '')
                + (theme ? ` theme-${theme}` : '') + (position ? ` tip-position-${position}` : '')
                + (isAnimated ? ' tip-animated' : '') + (className ? ' ' + className : ''),
            tipStyle = {
                ...PopupCalculation.getStyle(triggerEl, this.tipEl, position, isTriggerPositionFixed),
                ...style
            };

        return (
            <Paper ref="tip"
                   className={'tip' + tipClassName}
                   style={tipStyle}
                   depth={depth}
                   onWheel={e => {
                       Event.wheelHandler(e, this.props);
                   }}>

                {
                    hasTriangle ?

                            {triangle}

                        :
                        null
                }

 {
                         Event.wheelHandler(e, this.props);
                     }}>
                    {children}

            </Paper>
        );

    }
};

TipBody.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * This is the DOM element that will be used to set the position of the popover.
     */
    triggerEl: PropTypes.object,

    /**
     * If true,the popover is visible.
     */
    visible: PropTypes.bool,

    /**
     * If true,the popover will have a triangle on the top of the DOM element.
     */
    hasTriangle: PropTypes.bool,

    triangle: PropTypes.element,

    /**
     * The popover theme.Can be primary,highlight,success,warning,error.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The popover alignment.The value can be Menu.Position.LEFT or Menu.Position.RIGHT.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true, menu will have animation effects.
     */
    isAnimated: PropTypes.bool,

    shouldPreventContainerScroll: PropTypes.bool,

    /**
     * The depth of Paper component.
     */
    depth: PropTypes.number,

    isTriggerPositionFixed: PropTypes.bool,

    /**
     * The function of menu render.
     */
    onRender: PropTypes.func,

    /**
     * Callback function fired when the popover is requested to be closed.
     */
    onRequestClose: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func

};

TipBody.defaultProps = {

    className: '',
    style: null,
    theme: Theme.DEFAULT,

    triggerEl: null,
    visible: false,
    hasTriangle: true,
    triangle:

,
    position: Position.BOTTOM,
    isAnimated: true,
    depth: 6,
    shouldPreventContainerScroll: true,
    isTriggerPositionFixed: false

};<commit_msg>optimize TipBody<commit_after>/**
 * @file TipBody component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import {findDOMNode} from 'react-dom';
import PropTypes from 'prop-types';
import _ from 'lodash';

import Paper from '../Paper';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Event from '../_vendors/Event';
import PopupCalculation from '../_vendors/PopupCalculation';

import Position from '../_statics/Position';

export default class TipBody extends Component {

    static Position = Position;
    static Theme = Theme;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.hasMounted = false;
        this.prepareCloseTimeout = null;
        this.requestCloseTimeout = null;

        this.state = {
            visible: false
        };

        this.triggerMouseEnterHandler = ::this.triggerMouseEnterHandler;
        this.triggerMouseLeaveHandler = ::this.triggerMouseLeaveHandler;
        this.resizeHandler = ::this.resizeHandler;
        this.debounceResizeHandle = _.debounce(::this.debounceResizeHandle, 150);
        this.initializeAnimation = ::this.initializeAnimation;
        this.animate = ::this.animate;

    }

    triggerMouseEnterHandler() {
        this.prepareCloseTimeout && clearTimeout(this.prepareCloseTimeout);
    }

    triggerMouseLeaveHandler() {
        this.prepareCloseTimeout && clearTimeout(this.prepareCloseTimeout);
        this.prepareCloseTimeout = setTimeout(() => {
            this.setState({
                visible: false
            }, () => {
                this.requestCloseTimeout && clearTimeout(this.requestCloseTimeout);
                this.requestCloseTimeout = setTimeout(() => {
                    const {onRequestClose} = this.props;
                    this.hasMounted && onRequestClose && onRequestClose();
                }, 250);
            });
        }, 100);
    }

    resizeHandler() {
        this.debounceResizeHandle();
    }

    debounceResizeHandle() {
        this.forceUpdate();
    }

    initializeAnimation(callback) {
        setTimeout(() => {
            this.hasMounted && callback();
        }, 0);
    }

    animate() {
        this.setState({
            visible: true
        });
    }

    componentDidMount() {

        this.hasMounted = true;
        this.tipEl = findDOMNode(this.refs.tip);

        Event.addEvent(this.props.triggerEl, 'mouseenter', this.triggerMouseEnterHandler);
        Event.addEvent(this.props.triggerEl, 'mouseleave', this.triggerMouseLeaveHandler);
        Event.addEvent(window, 'resize', this.resizeHandler);

    }

    componentWillAppear(callback) {
        this.initializeAnimation(callback);
    }

    componentDidAppear() {
        this.animate();
    }

    componentDidUpdate() {
        const {onRender} = this.props,
            {visible} = this.state;
        visible && onRender && onRender(this.tipEl, this.props.triggerEl);
    }

    componentWillUnmount() {

        this.hasMounted = false;
        this.prepareCloseTimeout && clearTimeout(this.prepareCloseTimeout);
        this.requestCloseTimeout && clearTimeout(this.requestCloseTimeout);

        Event.removeEvent(this.props.triggerEl, 'mouseenter', this.triggerMouseEnterHandler);
        Event.removeEvent(this.props.triggerEl, 'mouseleave', this.triggerMouseLeaveHandler);
        Event.removeEvent(window, 'resize', this.resizeHandler);

    }

    render() {

        const {
                children, className, style, theme, hasTriangle, triangle, position, isAnimated, depth,
                triggerEl, isTriggerPositionFixed
            } = this.props,
            {visible} = this.state,

            tipClassName = (visible ? '' : ' hidden') + (hasTriangle ? ' tip-has-triangle' : '')
                + (theme ? ` theme-${theme}` : '') + (position ? ` tip-position-${position}` : '')
                + (isAnimated ? ' tip-animated' : '') + (className ? ' ' + className : ''),
            tipStyle = {
                ...PopupCalculation.getStyle(triggerEl, this.tipEl, position, isTriggerPositionFixed),
                ...style
            };

        return (
            <Paper ref="tip"
                   className={'tip' + tipClassName}
                   style={tipStyle}
                   depth={depth}
                   onWheel={e => {
                       Event.wheelHandler(e, this.props);
                   }}>

                {
                    hasTriangle ?

                            {triangle}

                        :
                        null
                }

 {
                         Event.wheelHandler(e, this.props);
                     }}>
                    {children}

            </Paper>
        );

    }
};

TipBody.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * This is the DOM element that will be used to set the position of the popover.
     */
    triggerEl: PropTypes.object,

    /**
     * If true,the popover is visible.
     */
    visible: PropTypes.bool,

    /**
     * If true,the popover will have a triangle on the top of the DOM element.
     */
    hasTriangle: PropTypes.bool,

    triangle: PropTypes.element,

    /**
     * The popover theme.Can be primary,highlight,success,warning,error.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The popover alignment.The value can be Menu.Position.LEFT or Menu.Position.RIGHT.
     */
    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * If true, menu will have animation effects.
     */
    isAnimated: PropTypes.bool,

    shouldPreventContainerScroll: PropTypes.bool,

    /**
     * The depth of Paper component.
     */
    depth: PropTypes.number,

    isTriggerPositionFixed: PropTypes.bool,

    /**
     * The function of menu render.
     */
    onRender: PropTypes.func,

    /**
     * Callback function fired when the popover is requested to be closed.
     */
    onRequestClose: PropTypes.func,

    /**
     * Callback function fired when wrapper wheeled.
     */
    onWheel: PropTypes.func

};

TipBody.defaultProps = {

    className: '',
    style: null,
    theme: Theme.DEFAULT,

    triggerEl: null,
    visible: false,
    hasTriangle: true,
    triangle:

,
    position: Position.BOTTOM,
    isAnimated: true,
    depth: 6,
    shouldPreventContainerScroll: true,
    isTriggerPositionFixed: false

};<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var CableType = mongoose.model('CableType');

var auth = require('../lib/auth');

var util = require('../lib/util');

module.exports = function (app) {
  app.get('/cabletypes', auth.ensureAuthenticated, function (req, res) {
    res.render('cabletype', {
      roles: req.session.roles
    });
  });

  app.get('/cabletypes/manage', auth.ensureAuthenticated, function (req, res) {
    if (req.session.roles.indexOf('admin') !== -1) {
      return res.render('cabletypemgmt');
    }
    return res.send(403, 'You are not authorized to access this resource');
  });

  app.get('/cabletypes/json', auth.ensureAuthenticated, function (req, res) {
    CableType.find(function (err, docs) {
      if (err) {
        return res.send(500, err.message);
      }
      res.json(docs);
    });
  });

  app.post('/cabletypes', auth.ensureAuthenticated, function (req, res) {
    if (req.session.roles.length === 0 || req.session.roles.indexOf('manage') === -1) {
      return res.send(403, "You are not authorized to access this resource. ");
    }
    var newType = {
      service: req.body.service || '',
      conductorNumber: req.conductorNumber || '',
      conductorSize: req.conductorSize || '',
      fribType: req.fribType || 'Unknown',
      pairing: req.pairing || '',
      shielding: req.shielding || '',
      outerDiameter: req.outerDiameter || '',
      voltageRating: req.voltageRating || '',
      raceway: req.raceway || '',
      tunnelHotcell: req.tunnelHotcell || '',
      otherRequirements: req.otherRequirements || '',
      createBy: req.session.userid,
      createdOn: Date.now()
    };
    // generate the type name here
    newType.name = newType(new CableType(newType)).save(function (err, type) {
      if (err) {
        console.dir(err);
        if (err.code && err.code === 11000) {
          console.error(err.msg || err.err);
          return res.send(400, 'please update the cable type named ' + newType.name);
        }
        console.error(err.msg || err.err);
        return res.send(500, err.msg || err.err);
      }
      var url = req.protocol + '://' + req.get('host') + '/cabletypes/' + type._id;
      res.set('Location', url);
      return res.json(201, type);
    });
  });

  app.put('/cabletypes/:id', auth.ensureAuthenticated, function (req, res) {
    if (req.session.roles.length === 0 || req.session.roles.indexOf('manage') === -1) {
      return res.send(403, "You are not authorized to access this resource. ");
    }
    var conditions = {
      _id: req.params.id
    };
    conditions[req.body.target] = req.body.original;
    var update = {};
    update[req.body.target] = req.body.update;
    update.updatedOn = Date.now();
    update.updatedBy = req.session.userid;
    CableType.findOneAndUpdate(conditions, update, function (err, type) {
      // the err is not a mongoose error
      if (err) {
        if (err.errmsg) {
          console.dir(err.errmsg);
        }
        if (err.lastErrorObject && err.lastErrorObject.code === 11001) {
          return res.send(400, req.body.update + ' is already taken');
        }
        return res.send(500, err.msg || err.errmsg);
      }
      if (type) {
        return res.send(204);
      }
      return res.send(410, 'cannot find type ' + req.params.id);
    });
  });
};
<commit_msg>undefined field will be handled by mongo no need for ''<commit_after>var mongoose = require('mongoose');
var CableType = mongoose.model('CableType');

var auth = require('../lib/auth');

var util = require('../lib/util');

module.exports = function (app) {
  app.get('/cabletypes', auth.ensureAuthenticated, function (req, res) {
    res.render('cabletype', {
      roles: req.session.roles
    });
  });

  app.get('/cabletypes/manage', auth.ensureAuthenticated, function (req, res) {
    if (req.session.roles.indexOf('admin') !== -1) {
      return res.render('cabletypemgmt');
    }
    return res.send(403, 'You are not authorized to access this resource');
  });

  app.get('/cabletypes/json', auth.ensureAuthenticated, function (req, res) {
    CableType.find(function (err, docs) {
      if (err) {
        return res.send(500, err.message);
      }
      res.json(docs);
    });
  });

  app.post('/cabletypes', auth.ensureAuthenticated, util.filterBody(['conductorNumber', 'conductorSize', 'fribType', 'typeNumber']), function (req, res) {
    if (req.session.roles.length === 0 || req.session.roles.indexOf('manage') === -1) {
      return res.send(403, "You are not authorized to access this resource. ");
    }
    var newType = {
      service: req.body.service,
      conductorNumber: req.conductorNumber,
      conductorSize: req.conductorSize,
      fribType: req.fribType,
      typeNumber: req.typeNumber,
      pairing: req.pairing,
      shielding: req.shielding,
      outerDiameter: req.outerDiameter,
      voltageRating: req.voltageRating,
      raceway: req.raceway,
      tunnelHotcell: req.tunnelHotcell,
      otherRequirements: req.otherRequirements,
      createBy: req.session.userid,
      createdOn: Date.now()
    };

    // generate the type name here
    newType.name = newType.conductorNumber + 'C_' + newType.conductorSize + '_' + newType.fribType + '_' + newType.typeNumber;

    (new CableType(newType)).save(function (err, type) {
      if (err) {
        console.dir(err);
        if (err.code && err.code === 11000) {
          console.error(err.msg || err.err);
          return res.send(400, 'The type name ' + newType.name + ' was already used.');
        }
        console.error(err.msg || err.err);
        return res.send(500, err.msg || err.err);
      }
      var url = req.protocol + '://' + req.get('host') + '/cabletypes/' + type._id;
      res.set('Location', url);
      return res.send(201, 'A new cable type is created at ' + url + '');
    });
  });

  app.put('/cabletypes/:id', auth.ensureAuthenticated, function (req, res) {
    if (req.session.roles.length === 0 || req.session.roles.indexOf('manage') === -1) {
      return res.send(403, "You are not authorized to access this resource. ");
    }
    var conditions = {
      _id: req.params.id
    };
    conditions[req.body.target] = req.body.original;
    var update = {};
    update[req.body.target] = req.body.update;
    update.updatedOn = Date.now();
    update.updatedBy = req.session.userid;
    CableType.findOneAndUpdate(conditions, update, function (err, type) {
      // the err is not a mongoose error
      if (err) {
        if (err.errmsg) {
          console.dir(err.errmsg);
        }
        if (err.lastErrorObject && err.lastErrorObject.code === 11001) {
          return res.send(400, req.body.update + ' is already taken');
        }
        return res.send(500, err.msg || err.errmsg);
      }
      if (type) {
        return res.send(204);
      }
      return res.send(410, 'cannot find type ' + req.params.id);
    });
  });
};
<|endoftext|>


<commit_before>/* eslint-disable max-lines */
import _ from 'lodash';
import FbMessenger from 'fb-messenger';
import promisify from 'es6-promisify';
import actions from '../data/actions';
import { sequentialPromises } from './utils';

const createCard = ({ title, image }) => ({
    attachment: {
        type: 'template',
        payload: {
            template_type: 'generic',
            elements: [
                {
                    title,
                    image_url: image,
                },
            ],
        },
    },
});

const createCarousel = cards => ({
    attachment: {
        type: 'template',
        payload: {
            template_type: 'generic',
            elements: _.map(cards, ({ title, image }) => ({
                title,
                image_url: image,
                buttons: [
                    {
                        type: 'postback',
                        title: 'Pick',
                        payload: 'pick',
                    },
                ],
            })),
        },
    },
});

const createList = (cards, style = 'compact') => ({
    attachment: {
        type: 'template',
        payload: {
            template_type: 'list',
            top_element_style: style,
            elements: _.map(cards, ({ title, subtitle, image, buttons }) => ({
                title,
                subtitle: subtitle || null,
                image_url: image || null,
                buttons: buttons || null,
            })),
        },
    },
});

const createHeaderList = cards => createList(cards, 'large');

export default ({ verifytoken }) => ({
    verifyToken: (query) => {
        if (query['hub.mode'] !== 'subscribe'
            || query['hub.verify_token'] !== verifytoken) {
            throw new Error('Failed validation. Make sure the validation tokens match.');
        }
    },
    extractAction: ({ raw }) => {
        if (_.has(raw, 'entry[0].messaging[0].message.quick_reply.payload')) {
            return raw.entry[0].messaging[0].message.quick_reply.payload;
        }
        if (_.has(raw, 'entry[0].messaging[0].message.text')) return 'text';
        if (_.has(raw, 'entry[0].messaging[0].postback.payload')) {
            return raw.entry[0].messaging[0].postback.payload;
        }
        return 'unknown';
    },
    extractSender: ({ raw }) => raw.entry[0].messaging[0].sender.id,
    sendMessage: (token, recipient, message) => {
        const messenger = new FbMessenger(token);
        const promiseMessage = promisify(messenger.sendMessage, messenger);
        const promiseQuickReplies = promisify(messenger.sendQuickRepliesMessage, messenger);

        const send = (msg) => {
            switch (msg.type) {
                case 'text':
                    return promiseQuickReplies(recipient, msg.payload.text, actions);
                case 'card':
                    return promiseMessage(recipient, createCard(msg.payload));
                case 'carousel':
                    return promiseMessage(recipient, createCarousel(msg.payload));
                case 'header-list':
                    return promiseMessage(recipient, createHeaderList(msg.payload));
                case 'list':
                    return promiseMessage(recipient, createList(msg.payload));
                default:
                    return promiseQuickReplies(recipient, JSON.stringify(msg), actions);
            }
        };

        if (!_.isArray(message)) return send(message).then();

        const messagePromises = message.map(msg => () => send(msg));
        return sequentialPromises(messagePromises).then();
    },
});
<commit_msg>Removed the special quick reply call.<commit_after>/* eslint-disable max-lines */
import _ from 'lodash';
import FbMessenger from 'fb-messenger';
import promisify from 'es6-promisify';
import actions from '../data/actions';
import { sequentialPromises } from './utils';

const createQuickReplies = ({ text }) => ({
    text,
    quick_replies: actions,
});

const createCard = ({ title, image }) => ({
    attachment: {
        type: 'template',
        payload: {
            template_type: 'generic',
            elements: [
                {
                    title,
                    image_url: image,
                },
            ],
        },
    },
});

const createCarousel = cards => ({
    attachment: {
        type: 'template',
        payload: {
            template_type: 'generic',
            elements: _.map(cards, ({ title, image }) => ({
                title,
                image_url: image,
                buttons: [
                    {
                        type: 'postback',
                        title: 'Pick',
                        payload: 'pick',
                    },
                ],
            })),
        },
    },
});

const createList = (cards, style = 'compact') => ({
    attachment: {
        type: 'template',
        payload: {
            template_type: 'list',
            top_element_style: style,
            elements: _.map(cards, ({ title, subtitle, image, buttons }) => ({
                title,
                subtitle: subtitle || null,
                image_url: image || null,
                buttons: buttons || null,
            })),
        },
    },
});

const createHeaderList = cards => createList(cards, 'large');

export default ({ verifytoken }) => ({
    verifyToken: (query) => {
        if (query['hub.mode'] !== 'subscribe'
            || query['hub.verify_token'] !== verifytoken) {
            throw new Error('Failed validation. Make sure the validation tokens match.');
        }
    },
    extractAction: ({ raw }) => {
        if (_.has(raw, 'entry[0].messaging[0].message.quick_reply.payload')) {
            return raw.entry[0].messaging[0].message.quick_reply.payload;
        }
        if (_.has(raw, 'entry[0].messaging[0].message.text')) return 'text';
        if (_.has(raw, 'entry[0].messaging[0].postback.payload')) {
            return raw.entry[0].messaging[0].postback.payload;
        }
        return 'unknown';
    },
    extractSender: ({ raw }) => raw.entry[0].messaging[0].sender.id,
    sendMessage: (token, recipient, message) => {
        const messenger = new FbMessenger(token);
        const promiseMessage = promisify(messenger.sendMessage, messenger);

        const send = (msg) => {
            switch (msg.type) {
                case 'text':
                    return promiseMessage(recipient, createQuickReplies({
                        text: msg.payload.text,
                    }));
                case 'card':
                    return promiseMessage(recipient, createCard(msg.payload));
                case 'carousel':
                    return promiseMessage(recipient, createCarousel(msg.payload));
                case 'header-list':
                    return promiseMessage(recipient, createHeaderList(msg.payload));
                case 'list':
                    return promiseMessage(recipient, createList(msg.payload));
                default:
                    return promiseMessage(recipient, createQuickReplies({
                        text: JSON.stringify(msg),
                    }));
            }
        };

        if (!_.isArray(message)) return send(message).then();

        const messagePromises = message.map(msg => () => send(msg));
        return sequentialPromises(messagePromises).then();
    },
});
<|endoftext|>


<commit_before>(function( angular ) {
  'use strict';

  angular.module('angular-humanize', []).
    filter('humanizeFilesize', function () {
      return function () {
        var args = Array.prototype.slice.call(arguments);
        args[0] = parseInt(args[0])
        if ( isNaN(args[0]) ) { return args[0]; }
        return humanize.filesize.apply(null, args);
      };
    }).
    filter('humanizeOrdinal', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.ordinal(input);
      };
    }).
    filter('humanizeNaturalDay', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.naturalDay(input);
      };
    }).
    filter('humanizeRelativeTime', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.relativeTime(input);
      };
    });

}( angular ));
<commit_msg>feat: add humanizeNumberFormat filter<commit_after>(function( angular ) {
  'use strict';

  angular.module('angular-humanize', []).
    filter('humanizeFilesize', function () {
      return function () {
        var args = Array.prototype.slice.call(arguments);
        args[0] = parseInt(args[0])
        if ( isNaN(args[0]) ) { return args[0]; }
        return humanize.filesize.apply(null, args);
      };
    }).
    filter('humanizeNumberFormat', function () {
      return function () {
        var args = Array.prototype.slice.call(arguments);
        args[0] = parseInt(args[0])
        if ( isNaN(args[0]) ) { return args[0]; }
        return humanize.numberFormat.apply(null, args);
      };
    }).
    filter('humanizeOrdinal', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.ordinal(input);
      };
    }).
    filter('humanizeNaturalDay', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.naturalDay(input);
      };
    }).
    filter('humanizeRelativeTime', function () {
      return function ( input ) {
        if ( parseInt(input) !== input ) { return input; }
        return humanize.relativeTime(input);
      };
    });

}( angular ));
<|endoftext|>


<commit_before>import declare from 'dojo/_base/declare';
import _WidgetBase from 'dijit/_WidgetBase';
import _TemplatedMixin from 'dijit/_TemplatedMixin';
import template from './templates/StyleChooser.html'; // Rollup string plugin
import teamColors from './resources/teams';
import baseStyleFile from './resources/baseStyle';
import strings from 'dojo/i18n!./nls/strings';
import domConstruct from 'dojo/dom-construct';
import on from 'dojo/on';

export default declare([_WidgetBase, _TemplatedMixin], {

  baseClass: 'style-chooser',
  nls: strings,
  templateString: template,

  // set panel header title
  _setTitleAttr: {
    node: 'titleNode',
    type: 'innerHTML'
  },

  postCreate() {
    this.inherited(arguments);
    this.populateSelect(this.styleSelect, teamColors);
    on(this.styleSelect, 'change', (evt) => {
      if (evt.target.value !== -1) {
        this.tileLayer.loadStyle(
          this.getNewStyle(
            baseStyleFile,
            teamColors[evt.target.value].colors.hex
          )
        );
      }
    });
  },

  populateSelect(select, teamColorsArray) {
    // set an initial version for now,
    // until we can get the layer loaded event.
    const opt = domConstruct.create('option', {
      innerHTML: `⇩ ${this.nls.ChangeMe} ⇩`,
      value: -1
    });
    this.styleSelect.add(opt);
    teamColorsArray.forEach((team, index) => {
      this.styleSelect.add(domConstruct.create('option', {
        innerHTML: team.name,
        value: index
      }));
    });
  },

  getNewStyle(baseStyle, colorArray) {
    var retStyle = Object.assign({}, baseStyle);
    if (retStyle && retStyle.hasOwnProperty('layers')) {

      if (colorArray.length > 0) {
        // do background
        const backgroundLayers = retStyle.layers.filter((layer) => {
          if (layer.id.indexOf('background') > -1 || layer.id.indexOf('Water area') > -1) {
            return true;
          }
          return false;
        });

        backgroundLayers.forEach((backgroundLayer) => {
          if (backgroundLayer.paint.hasOwnProperty('background-color')) {
            backgroundLayer.paint['background-color'] = `#${colorArray[0]}`;
          }
          if (backgroundLayer.paint.hasOwnProperty('fill-color')) {
            backgroundLayer.paint['fill-color'] = `#${colorArray[0]}`;
          }
        });
      }

      if (colorArray.length > 1) {
        // do land
        const landLayers = retStyle.layers.filter((layer) => {
          if (layer.id === 'Land') {
            return true;
          }
          return false;
        });

        landLayers.forEach((landLayer) => {
          if (landLayer.paint.hasOwnProperty('fill-color')) {
            landLayer.paint['fill-color'] = `#${colorArray[1]}`;
          }
        });
      }

      if (colorArray.length > 2) {
        // do other
        const otherLayers = retStyle.layers.filter((layer) => {
          if (layer.id.indexOf('Building/General') > -1 || layer.id.indexOf('Railroad/2') > -1 || layer.id.indexOf('Railroad/1') > -1 || layer.id.indexOf('Urban area') > -1) {
            return true;
          }
          return false;
        });

        otherLayers.forEach((otherLayer) => {
          if (otherLayer.paint.hasOwnProperty('background-color')) {
            otherLayer.paint['background-color'] = `#${colorArray[2]}`;
          }
          if (otherLayer.paint.hasOwnProperty('fill-color')) {
            otherLayer.paint['fill-color'] = `#${colorArray[2]}`;
          }
        });
      }

    }
    return retStyle;
  }
});
<commit_msg>first color include marine area<commit_after>import declare from 'dojo/_base/declare';
import _WidgetBase from 'dijit/_WidgetBase';
import _TemplatedMixin from 'dijit/_TemplatedMixin';
import template from './templates/StyleChooser.html'; // Rollup string plugin
import teamColors from './resources/teams';
import baseStyleFile from './resources/baseStyle';
import strings from 'dojo/i18n!./nls/strings';
import domConstruct from 'dojo/dom-construct';
import on from 'dojo/on';

export default declare([_WidgetBase, _TemplatedMixin], {

  baseClass: 'style-chooser',
  nls: strings,
  templateString: template,

  // set panel header title
  _setTitleAttr: {
    node: 'titleNode',
    type: 'innerHTML'
  },

  postCreate() {
    this.inherited(arguments);
    this.populateSelect(this.styleSelect, teamColors);
    on(this.styleSelect, 'change', (evt) => {
      if (evt.target.value !== -1) {
        this.tileLayer.loadStyle(
          this.getNewStyle(
            baseStyleFile,
            teamColors[evt.target.value].colors.hex
          )
        );
      }
    });
  },

  populateSelect(select, teamColorsArray) {
    // set an initial version for now,
    // until we can get the layer loaded event.
    const opt = domConstruct.create('option', {
      innerHTML: `⇩ ${this.nls.ChangeMe} ⇩`,
      value: -1
    });
    this.styleSelect.add(opt);
    teamColorsArray.forEach((team, index) => {
      this.styleSelect.add(domConstruct.create('option', {
        innerHTML: team.name,
        value: index
      }));
    });
  },

  getNewStyle(baseStyle, colorArray) {
    var retStyle = Object.assign({}, baseStyle);
    if (retStyle && retStyle.hasOwnProperty('layers')) {

      if (colorArray.length > 0) {
        // do background
        const backgroundLayers = retStyle.layers.filter((layer) => {
          if (layer.id.indexOf('background') > -1 ||
            layer.id.indexOf('Water area') > -1 ||
            layer.id.indexOf('Marine area') > -1) {
            return true;
          }
          return false;
        });

        backgroundLayers.forEach((backgroundLayer) => {
          if (backgroundLayer.paint.hasOwnProperty('background-color')) {
            backgroundLayer.paint['background-color'] = `#${colorArray[0]}`;
          }
          if (backgroundLayer.paint.hasOwnProperty('fill-color')) {
            backgroundLayer.paint['fill-color'] = `#${colorArray[0]}`;
          }
        });
      }

      if (colorArray.length > 1) {
        // do land
        const landLayers = retStyle.layers.filter((layer) => {
          if (layer.id === 'Land') {
            return true;
          }
          return false;
        });

        landLayers.forEach((landLayer) => {
          if (landLayer.paint.hasOwnProperty('fill-color')) {
            landLayer.paint['fill-color'] = `#${colorArray[1]}`;
          }
        });
      }

      if (colorArray.length > 2) {
        // do other
        const otherLayers = retStyle.layers.filter((layer) => {
          if (layer.id.indexOf('Building/General') > -1 || layer.id.indexOf('Railroad/2') > -1 || layer.id.indexOf('Railroad/1') > -1 || layer.id.indexOf('Urban area') > -1) {
            return true;
          }
          return false;
        });

        otherLayers.forEach((otherLayer) => {
          if (otherLayer.paint.hasOwnProperty('background-color')) {
            otherLayer.paint['background-color'] = `#${colorArray[2]}`;
          }
          if (otherLayer.paint.hasOwnProperty('fill-color')) {
            otherLayer.paint['fill-color'] = `#${colorArray[2]}`;
          }
        });
      }

    }
    return retStyle;
  }
});
<|endoftext|>


<commit_before>function handleSubmit () {
  document.location += 'memento/*/' + document.getElementById('url').value
}

function shortestFirst (a, b) {
  if (a.length < b.length) { return -1 }
  if (a.length > b.length) { return 1 }
  return 0
}

function showURIs () {
  let ul = document.getElementById('uriList')
  if (ul.childNodes.length > 0) {
    return // Prevent multiple adds of the URI list to the DOM
  }

  let htmlPages = 0
  const uriKeys = Object.keys(uris).sort(shortestFirst)
  for (let uri of uriKeys) {
    for (let datetimesI = 0; datetimesI < uris[uri]['datetimes'].length; datetimesI++) {
      let datetime = uris[uri]['datetimes'][datetimesI]

      let li = document.createElement('li')
      let a = document.createElement('a')
      a.href = datetime + '/' + uri
      a.appendChild(document.createTextNode(uri))
      dt = document.createTextNode(' (' + datetime + ')')

      li.appendChild(a)
      li.appendChild(dt)
      li.setAttribute('data-mime', uris[uri]['mime'])
      ul.appendChild(li)
    }
    uris[uri]['mime'] === 'text/html' ? ++htmlPages : ''
  }
  document.getElementById('htmlPages').innerHTML = htmlPages
  document.getElementById('memCountListLink').className = ['activated']
  document.getElementById('uris').classList.remove('hidden')
  setPlurality()
  setShowAllButtonStatus()

  setUIExpandedState(uris)
  // Maintain visible state of URI display for future retrieval
  window.localStorage.setItem('showURIs', true)
}

function setUIExpandedState (urisObj) {
  const urisHash = calculateURIsHash(urisObj)
  setURIsHash(urisHash)
}

function calculateURIsHash (urisObj) {
  return JSON.stringify(urisObj).hashCode()
}

function getURIsHash () {
  return window.localStorage.getItem('urisHash')
}

function setURIsHash (hashIn) {
  return window.localStorage.setItem('urisHash', hashIn)
}

String.prototype.hashCode = function () {
  let hash = 0
  let i
  let chr
  if (this.length === 0) {
    return hash
  }
  for (i = 0; i < this.length; i++) {
    chr = this.charCodeAt(i)
    hash = ((hash << 5) - hash) + chr
    hash |= 0 // Convert to 32bit integer
  }
  return hash
}

function addEventListeners () {
  let target = document.getElementById('memCountListLink')
  target.addEventListener('click', showURIs, false)

  let showAllInListingButton = document.getElementById('showEmbeddedURI')
  showAllInListingButton.onclick = function showAllURIs () {
    document.getElementById('uriList').classList.add('forceDisplay')
  }

  getIPFSWebUIAddress()
  updateServiceWorkerVersionUI()

  let reinstallServiceWorkerButton = document.getElementById('reinstallServiceWorker')
  reinstallServiceWorkerButton.onclick = reinstallServiceWorker

  setShowURIsVisibility()
}

function setShowURIsVisibility () {
  const previousHash = getURIsHash() + ''
  const newHash = calculateURIsHash(uris) + ''

  if (window.localStorage.getItem('showURIs') && previousHash === newHash) {
    showURIs()
  }
}

function setPlurality () {
  const urimCount = document.getElementById('memCountInt').innerHTML
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML

  if (urimCount === '1') {
    document.getElementById('plural').classList.add('hidden')
  }
  if (htmlFilesPlurality === '1') {
    document.getElementById('htmlPagesPlurality').classList.add('hidden')
  }
}

function setShowAllButtonStatus () {
  const urimCount = document.getElementById('memCountInt').innerHTML
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML
  if (urimCount === htmlFilesPlurality) {
    document.getElementById('showEmbeddedURI').setAttribute('disabled', 'disabled')
  }
}

function assignStatusButtonHandlers () {
  let button = document.getElementsByTagName('button')[0]
  if (button.innerHTML === 'Start') {
    button.addEventListener('click', startIPFSDaemon)
  } else {
    button.addEventListener('click', stopIPFSDaemon)
  }
}

function startIPFSDaemon () {
  sendCommandToIPFSDaemon('start')
  this.innerHTML = 'Starting...'
  this.setAttribute('disabled', 'disabled')
}

function stopIPFSDaemon () {
  sendCommandToIPFSDaemon('stop')
  this.innerHTML = 'Stopping...'
  this.setAttribute('disabled', 'disabled')
}

function getIPFSWebUIAddress () {
  const setIPFSWebUILink = function (resp) {
    document.getElementById('webui').setAttribute('href', 'http://' + resp)
  }
  const fail = function () { console.log('fail') }
  const err = function () { console.log('err') }
  makeAnAJAXRequest('/config/openEndedPlaceHolder', setIPFSWebUILink, fail, err)
}

function updateIPFSDaemonButtonUI () {
  window.setTimeout(function () {
    document.location.reload(true)
  }, 4000)
}

function sendCommandToIPFSDaemon (cmd) {
  const failFunction = function () { console.log('Comm w/ ipfs daemon failed.') }
  const errFunction = function () { console.log('Error talking to ipfs daemon.') }
  makeAnAJAXRequest('/daemon/' + cmd, updateIPFSDaemonButtonUI,
    failFunction, errFunction)
}

function makeAnAJAXRequest (address, successFunction, failFunction, errorFunction) {
  let xmlhttp = new XMLHttpRequest()

  xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState === XMLHttpRequest.DONE) {
      if (xmlhttp.status === 200) {
        successFunction(xmlhttp.responseText)
      } else if (xmlhttp.status === 400) {
        failFunction()
      } else {
        errorFunction()
      }
    }
  }

  xmlhttp.open('GET', address, true)
  xmlhttp.send()
}

function injectIPWBJS () {
  registerServiceWorker()
  // TODO: Add ipwb replay banner
}

function getServiceWorkerVersion () {
  return fetch(self.location.href)
    .then(function (resp) {
      return Promise.resolve(resp.headers.get('Server').split('/')[1])
    })
}

function reinstallServiceWorker () {
  console.log('Deleting old serviceWorker')
  deleteServiceWorker()
  document.getElementById('serviceWorkerVersion').innerHTML = 'Updating...'
  installServiceWorker()
  updateServiceWorkerVersionUI()
}

function deleteServiceWorker () {
  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    for (let registration of registrations) {
      registration.unregister()
    }
  })
}

function updateServiceWorkerVersionUI () {
  getServiceWorkerVersion().then(function (resp) {
    console.log('updating to ...' + resp)
    document.getElementById('serviceWorkerVersion').innerHTML = 'ver. ' + resp
  })
}

function installServiceWorker () {
  let newInstallation = false

  if (navigator.serviceWorker.controller === null) { // Ideally we would use serviceWorker.getRegistration
    newInstallation = true
  }

  navigator.serviceWorker.register('/serviceWorker.js').then(
    function (registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope)
    }).catch(function (err) {
    console.log('ServiceWorker registration failed: ', err)
  }).then(function (rr) {
    const dt = document.location.href.split('/')[3]
    const viewingMemento = dt.length === 14 && parseInt(dt, 10) + '' === dt

    // Reload the page with processing by the newly installed Service Worker
    if (newInstallation && viewingMemento) {
      document.location.reload()
    }
  })
}

function registerServiceWorker () {
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', installServiceWorker)
  } else {
    console.log('Browser does not support Service Worker.')
  }
}

function serviceWorkerUpToDate () {

}

function updateServiceWorker () {

}

function reloadPageFromServiceWorker () {
  console.log('reloading page from serviceWorker!')
}
<commit_msg>Rm obsolete comment in web.js. Banner is added via reconstructive.<commit_after>function handleSubmit () {
  document.location += 'memento/*/' + document.getElementById('url').value
}

function shortestFirst (a, b) {
  if (a.length < b.length) { return -1 }
  if (a.length > b.length) { return 1 }
  return 0
}

function showURIs () {
  let ul = document.getElementById('uriList')
  if (ul.childNodes.length > 0) {
    return // Prevent multiple adds of the URI list to the DOM
  }

  let htmlPages = 0
  const uriKeys = Object.keys(uris).sort(shortestFirst)
  for (let uri of uriKeys) {
    for (let datetimesI = 0; datetimesI < uris[uri]['datetimes'].length; datetimesI++) {
      let datetime = uris[uri]['datetimes'][datetimesI]

      let li = document.createElement('li')
      let a = document.createElement('a')
      a.href = datetime + '/' + uri
      a.appendChild(document.createTextNode(uri))
      dt = document.createTextNode(' (' + datetime + ')')

      li.appendChild(a)
      li.appendChild(dt)
      li.setAttribute('data-mime', uris[uri]['mime'])
      ul.appendChild(li)
    }
    uris[uri]['mime'] === 'text/html' ? ++htmlPages : ''
  }
  document.getElementById('htmlPages').innerHTML = htmlPages
  document.getElementById('memCountListLink').className = ['activated']
  document.getElementById('uris').classList.remove('hidden')
  setPlurality()
  setShowAllButtonStatus()

  setUIExpandedState(uris)
  // Maintain visible state of URI display for future retrieval
  window.localStorage.setItem('showURIs', true)
}

function setUIExpandedState (urisObj) {
  const urisHash = calculateURIsHash(urisObj)
  setURIsHash(urisHash)
}

function calculateURIsHash (urisObj) {
  return JSON.stringify(urisObj).hashCode()
}

function getURIsHash () {
  return window.localStorage.getItem('urisHash')
}

function setURIsHash (hashIn) {
  return window.localStorage.setItem('urisHash', hashIn)
}

String.prototype.hashCode = function () {
  let hash = 0
  let i
  let chr
  if (this.length === 0) {
    return hash
  }
  for (i = 0; i < this.length; i++) {
    chr = this.charCodeAt(i)
    hash = ((hash << 5) - hash) + chr
    hash |= 0 // Convert to 32bit integer
  }
  return hash
}

function addEventListeners () {
  let target = document.getElementById('memCountListLink')
  target.addEventListener('click', showURIs, false)

  let showAllInListingButton = document.getElementById('showEmbeddedURI')
  showAllInListingButton.onclick = function showAllURIs () {
    document.getElementById('uriList').classList.add('forceDisplay')
  }

  getIPFSWebUIAddress()
  updateServiceWorkerVersionUI()

  let reinstallServiceWorkerButton = document.getElementById('reinstallServiceWorker')
  reinstallServiceWorkerButton.onclick = reinstallServiceWorker

  setShowURIsVisibility()
}

function setShowURIsVisibility () {
  const previousHash = getURIsHash() + ''
  const newHash = calculateURIsHash(uris) + ''

  if (window.localStorage.getItem('showURIs') && previousHash === newHash) {
    showURIs()
  }
}

function setPlurality () {
  const urimCount = document.getElementById('memCountInt').innerHTML
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML

  if (urimCount === '1') {
    document.getElementById('plural').classList.add('hidden')
  }
  if (htmlFilesPlurality === '1') {
    document.getElementById('htmlPagesPlurality').classList.add('hidden')
  }
}

function setShowAllButtonStatus () {
  const urimCount = document.getElementById('memCountInt').innerHTML
  const htmlFilesPlurality = document.getElementById('htmlPages').innerHTML
  if (urimCount === htmlFilesPlurality) {
    document.getElementById('showEmbeddedURI').setAttribute('disabled', 'disabled')
  }
}

function assignStatusButtonHandlers () {
  let button = document.getElementsByTagName('button')[0]
  if (button.innerHTML === 'Start') {
    button.addEventListener('click', startIPFSDaemon)
  } else {
    button.addEventListener('click', stopIPFSDaemon)
  }
}

function startIPFSDaemon () {
  sendCommandToIPFSDaemon('start')
  this.innerHTML = 'Starting...'
  this.setAttribute('disabled', 'disabled')
}

function stopIPFSDaemon () {
  sendCommandToIPFSDaemon('stop')
  this.innerHTML = 'Stopping...'
  this.setAttribute('disabled', 'disabled')
}

function getIPFSWebUIAddress () {
  const setIPFSWebUILink = function (resp) {
    document.getElementById('webui').setAttribute('href', 'http://' + resp)
  }
  const fail = function () { console.log('fail') }
  const err = function () { console.log('err') }
  makeAnAJAXRequest('/config/openEndedPlaceHolder', setIPFSWebUILink, fail, err)
}

function updateIPFSDaemonButtonUI () {
  window.setTimeout(function () {
    document.location.reload(true)
  }, 4000)
}

function sendCommandToIPFSDaemon (cmd) {
  const failFunction = function () { console.log('Comm w/ ipfs daemon failed.') }
  const errFunction = function () { console.log('Error talking to ipfs daemon.') }
  makeAnAJAXRequest('/daemon/' + cmd, updateIPFSDaemonButtonUI,
    failFunction, errFunction)
}

function makeAnAJAXRequest (address, successFunction, failFunction, errorFunction) {
  let xmlhttp = new XMLHttpRequest()

  xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState === XMLHttpRequest.DONE) {
      if (xmlhttp.status === 200) {
        successFunction(xmlhttp.responseText)
      } else if (xmlhttp.status === 400) {
        failFunction()
      } else {
        errorFunction()
      }
    }
  }

  xmlhttp.open('GET', address, true)
  xmlhttp.send()
}

function injectIPWBJS () {
  registerServiceWorker()
}

function getServiceWorkerVersion () {
  return fetch(self.location.href)
    .then(function (resp) {
      return Promise.resolve(resp.headers.get('Server').split('/')[1])
    })
}

function reinstallServiceWorker () {
  console.log('Deleting old serviceWorker')
  deleteServiceWorker()
  document.getElementById('serviceWorkerVersion').innerHTML = 'Updating...'
  installServiceWorker()
  updateServiceWorkerVersionUI()
}

function deleteServiceWorker () {
  navigator.serviceWorker.getRegistrations().then(function (registrations) {
    for (let registration of registrations) {
      registration.unregister()
    }
  })
}

function updateServiceWorkerVersionUI () {
  getServiceWorkerVersion().then(function (resp) {
    console.log('updating to ...' + resp)
    document.getElementById('serviceWorkerVersion').innerHTML = 'ver. ' + resp
  })
}

function installServiceWorker () {
  let newInstallation = false

  if (navigator.serviceWorker.controller === null) { // Ideally we would use serviceWorker.getRegistration
    newInstallation = true
  }

  navigator.serviceWorker.register('/serviceWorker.js').then(
    function (registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope)
    }).catch(function (err) {
    console.log('ServiceWorker registration failed: ', err)
  }).then(function (rr) {
    const dt = document.location.href.split('/')[3]
    const viewingMemento = dt.length === 14 && parseInt(dt, 10) + '' === dt

    // Reload the page with processing by the newly installed Service Worker
    if (newInstallation && viewingMemento) {
      document.location.reload()
    }
  })
}

function registerServiceWorker () {
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', installServiceWorker)
  } else {
    console.log('Browser does not support Service Worker.')
  }
}

function serviceWorkerUpToDate () {

}

function updateServiceWorker () {

}

function reloadPageFromServiceWorker () {
  console.log('reloading page from serviceWorker!')
}
<|endoftext|>


<commit_before>export default function Collapsible($control) {
  const $region = document.getElementById($control.getAttribute('aria-controls'));

  if ($control && $region) {
    const handleClick = event => {
      event.preventDefault();

      handleToggle();
    };

    const handleToggle = () => {
      const value = $control.getAttribute('aria-expanded') !== 'true';

      $control.setAttribute('aria-expanded', value);

      if (value) {
        $region.removeAttribute('aria-hidden');
        $region.focus();
      } else {
        $region.setAttribute('aria-hidden', true);
      }
    };

    return {
      setup: () => {
        $control.setAttribute('aria-expanded', false);
        $control.removeAttribute('aria-hidden');

        $region.setAttribute('aria-hidden', true);
        $region.setAttribute('tabindex', -1);

        $control.addEventListener('click', handleClick);

        this.toggle = handleToggle;
      },

      teardown: () => {
        $control.setAttribute('aria-expanded', true);
        $control.setAttribute('aria-hidden', true);

        $region.removeAttribute('aria-hidden');
        $region.removeAttribute('tabindex');

        $control.removeEventListener('click', handleClick);
      }
    };
  }
}
<commit_msg>Rewrite source code<commit_after>const removeAttribute = (node, attr) => node.removeAttribute(attr);
const setAttribute = (node, attr, value) => node.setAttribute(attr, value);

export default class Collapsible {
  constructor(control) {
    const region = document.getElementById(control.getAttribute('aria-controls'));

    if (control && region) {
      this.control = control;
      this.region = region;

      this.setup = this.#setup;
      this.teardown = this.#teardown;
    }
  }

  #handleClick = (event) => {
    event.preventDefault();

    this.#handleToggle();
  };

  #handleToggle = (control = this.control, region = this.region) => {
    const value = control.getAttribute('aria-expanded') !== 'true';

    setAttribute(control, 'aria-expanded', value);

    if (value) {
      removeAttribute(region, 'aria-hidden');
      region.focus();
    } else {
      setAttribute(region, 'aria-hidden', true);
    }
  };

  #setup = (control = this.control, region = this.region) => {
    setAttribute(control, 'aria-expanded', false);
    removeAttribute(control, 'aria-hidden');

    setAttribute(region, 'aria-hidden', true);
    setAttribute(region, 'tabindex', -1);

    control.addEventListener('click', this.#handleClick);

    this.toggle = this.#handleToggle;
  };

  #teardown = (control = this.control, region = this.region) => {
    setAttribute(control, 'aria-expanded', true);
    setAttribute(control, 'aria-hidden', true);

    removeAttribute(region, 'aria-hidden');
    removeAttribute(region, 'tabindex');

    control.removeEventListener('click', this.#handleClick);

    this.toggle = undefined;
  };
}
<|endoftext|>


<commit_before>//Imports
import React from "react";
import { Container, Row, Col } from "reactstrap";
import i18n from "../../../../both/i18n/en";
import DCSBalloon from '/imports/client/ui/components/DCSBalloon/index.js'

const Content = (props) => {
  return (
    <React.Fragment>
      <Container className="mt-5">

Looking for answers?

          Take a look at frequently asked questions

      </Container>
      {i18n.Faq.faq.map((item, index) => {
        return (
          <Col key={index} className="ml-5 pl-5 mt-5" xs={11}>

{item.heading}

{item.text}

            <DCSBalloon title=" " subtitle=" " balloonId="bal1" display="inline" dcsTags={props.dcsTags} />
          </Col>
        );
      })}
    </React.Fragment>
  );
};

export default Content;
<commit_msg>moved balloon<commit_after>//Imports
import React from "react";
import { Container, Row, Col } from "reactstrap";
import i18n from "../../../../both/i18n/en";
import DCSBalloon from '/imports/client/ui/components/DCSBalloon/index.js'

const Content = (props) => {
  return (
    <React.Fragment>
      <Container className="mt-5">

Looking for answers?

          Take a look at frequently asked questions

      </Container>
      {i18n.Faq.faq.map((item, index) => {
        return (
          <Col key={index} className="ml-5 pl-5 mt-5" xs={11}>

{item.heading}

            <DCSBalloon title=" " subtitle=" " balloonId="bal1" display="inline" dcsTags={props.dcsTags} />

{item.text}

          </Col>
        );
      })}
    </React.Fragment>
  );
};

export default Content;
<|endoftext|>


<commit_before>import _ from 'lodash';
import * as TextFormatting from 'src/helpers/TextFormatting';
import state from './state';

let nextId = 0;

export default class Message {
    constructor(message, user) {
        this.id = nextId++;
        this.time = message.time || Date.now();
        this.nick = message.nick;
        this.message = message.message;
        this.type = message.type || 'message';
        this.type_extra = message.type_extra;
        this.ignore = false;
        this.mentioned_urls = [];
        this.html = '';

        // We don't want the user object to be enumerable
        Object.defineProperty(this, 'user', {
            value: user,
        });
    }

    parseHtml(messageList) {
        if (this.html) {
            return this.html;
        }

        let words = this.message.split(' ');
        words = words.map((word, wordIdx) => {
            let parsed;

            let linkified = TextFormatting.linkifyUrls(word, {
                addHandle: true,
                handleClass: 'fa fa-chevron-right kiwi-messagelist-message-linkhandle',
            });
            if (linkified.urls.length > 0) {
                this.mentioned_urls = this.mentioned_urls.concat(linkified.urls);
            }
            if (linkified.html !== word) return linkified.html;

            parsed = TextFormatting.linkifyChannels(word);
            if (parsed !== word) return parsed;

            parsed = TextFormatting.linkifyUsers(word, messageList.buffer.users);
            if (parsed !== word) return parsed;

            if (state.setting('buffers.show_emoticons')) {
                parsed = TextFormatting.addEmojis(
                    { word, words, wordIdx },
                    state.setting('emojis'),
                    state.setting('emojiLocation')
                );
                if (parsed !== word) return parsed;
            }

            return _.escape(word);
        });

        let parsed = words.join(' ');
        let useExtraFormatting = messageList.useExtraFormatting && this.type === 'privmsg';

        parsed = TextFormatting.ircCodesToHtml(parsed, useExtraFormatting);

        this.html = parsed;
        return this.html;
    }

}
<commit_msg>Don't do any character replacing transformations such as emojis in *raw and other special buffers<commit_after>import _ from 'lodash';
import * as TextFormatting from 'src/helpers/TextFormatting';
import state from './state';

let nextId = 0;

export default class Message {
    constructor(message, user) {
        this.id = nextId++;
        this.time = message.time || Date.now();
        this.nick = message.nick;
        this.message = message.message;
        this.type = message.type || 'message';
        this.type_extra = message.type_extra;
        this.ignore = false;
        this.mentioned_urls = [];
        this.html = '';

        // We don't want the user object to be enumerable
        Object.defineProperty(this, 'user', {
            value: user,
        });
    }

    parseHtml(messageList) {
        if (this.html) {
            return this.html;
        }

        // We only want to format emojis + extra formatting for actual message buffers. Other
        // buffers such as *raw shouldnt have highlights or emojis
        let allowCharacterReplacements = messageList.buffer.isQuery() ||
            messageList.buffer.isChannel();

        let words = this.message.split(' ');
        words = words.map((word, wordIdx) => {
            let parsed;

            let linkified = TextFormatting.linkifyUrls(word, {
                addHandle: true,
                handleClass: 'fa fa-chevron-right kiwi-messagelist-message-linkhandle',
            });
            if (linkified.urls.length > 0) {
                this.mentioned_urls = this.mentioned_urls.concat(linkified.urls);
            }
            if (linkified.html !== word) return linkified.html;

            parsed = TextFormatting.linkifyChannels(word);
            if (parsed !== word) return parsed;

            parsed = TextFormatting.linkifyUsers(word, messageList.buffer.users);
            if (parsed !== word) return parsed;

            if (allowCharacterReplacements && state.setting('buffers.show_emoticons')) {
                parsed = TextFormatting.addEmojis(
                    { word, words, wordIdx },
                    state.setting('emojis'),
                    state.setting('emojiLocation')
                );
                if (parsed !== word) return parsed;
            }

            return _.escape(word);
        });

        let parsed = words.join(' ');
        let useExtraFormatting = allowCharacterReplacements &&
            messageList.useExtraFormatting &&
            this.type === 'privmsg';

        parsed = TextFormatting.ircCodesToHtml(parsed, useExtraFormatting);

        this.html = parsed;
        return this.html;
    }

}
<|endoftext|>


<commit_before>/**
 * @method isEventSupported
 * @param {String} eventName
 * @param {HTMLElement} element optional
 * @return {Boolean} true if event is supported
 *
 * Note that `isEventSupported` can give false positives when passed augmented host objects, e.g.:
 *
 *     someElement.onfoo = function(){ };
 *     isEventSupported('foo', someElement); // true (even if "foo" is not supported)
 *
 * Also note that in Gecko clients (those that utilize `setAttribute` -based detection) -
 *
 *     `isEventSupported('foo', someElement)`;
 *
 * - might create `someElement.foo` property (if "foo" event is supported) which apparently can not be deleted
 * `isEventSupported` sets such property to `undefined` value, but can not fully remove it
 *
 */
var isEventSupported = (function(){

  var TAGNAMES = {
    'select':'input','change':'input',
    'submit':'form','reset':'form',
    'error':'img','load':'img','abort':'img'
  }

  function isEventSupported(eventName, element) {

    element = element || document.createElement(TAGNAMES[eventName] || 'div');
    eventName = 'on' + eventName;

    // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
    var isSupported = (eventName in element);

    if (!isSupported) {
      // if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
      if (!element.setAttribute) {
        element = document.createElement('div');
      }
      if (element.setAttribute && element.removeAttribute) {
        element.setAttribute(eventName, '');
        isSupported = typeof element[eventName] == 'function';

        // if property was created, "remove it" (by setting value to `undefined`)
        if (typeof element[eventName] != 'undefined') {
          element[eventName] = void 0;
        }
        element.removeAttribute(eventName);
      }
    }

    element = null;
    return isSupported;
  }
  return isEventSupported;
})();

var isEventSupportedWithCache = (function(){

  var TAGNAMES = {
    'select':'input','change':'input',
    'submit':'form','reset':'form',
    'error':'img','load':'img','abort':'img'
  },
  cache = { };

  function isEventSupported(eventName, element) {
    var canCache = (arguments.length == 1);

    // only return cached result when no element is given
    if (canCache && cache[eventName]) {
      return cache[eventName];
    }

    element = element || document.createElement(TAGNAMES[eventName] || 'div');
    eventName = 'on' + eventName;

    // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
    var isSupported = (eventName in element);

    if (!isSupported) {
      // if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
      if (!element.setAttribute) {
        element = document.createElement('div');
      }
      if (element.setAttribute && element.removeAttribute) {
        element.setAttribute(eventName, '');
        isSupported = typeof element[eventName] == 'function';

        // if property was created, "remove it" (by setting value to `undefined`)
        if (typeof element[eventName] != 'undefined') {
          element[eventName] = void 0;
        }
        element.removeAttribute(eventName);
      }
    }

    element = null;
    return canCache ? (cache[eventName] = isSupported) : isSupported;
  }
  return isEventSupported;
})();<commit_msg>Add missing semicolon and replace `void 0` with `undef` (having `undefined` value) — making JSLint happy.<commit_after>/**
 * @method isEventSupported
 * @param {String} eventName
 * @param {HTMLElement} element optional
 * @return {Boolean} true if event is supported
 *
 * Note that `isEventSupported` can give false positives when passed augmented host objects, e.g.:
 *
 *     someElement.onfoo = function(){ };
 *     isEventSupported('foo', someElement); // true (even if "foo" is not supported)
 *
 * Also note that in Gecko clients (those that utilize `setAttribute` -based detection) -
 *
 *     `isEventSupported('foo', someElement)`;
 *
 * - might create `someElement.foo` property (if "foo" event is supported) which apparently can not be deleted
 * `isEventSupported` sets such property to `undefined` value, but can not fully remove it
 *
 */
var isEventSupported = (function(undef) {

  var TAGNAMES = {
    'select':'input','change':'input',
    'submit':'form','reset':'form',
    'error':'img','load':'img','abort':'img'
  };

  function isEventSupported(eventName, element) {

    element = element || document.createElement(TAGNAMES[eventName] || 'div');
    eventName = 'on' + eventName;

    var isSupported = (eventName in element);

    if (!isSupported) {
      // if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
      if (!element.setAttribute) {
        element = document.createElement('div');
      }
      if (element.setAttribute && element.removeAttribute) {
        element.setAttribute(eventName, '');
        isSupported = typeof element[eventName] == 'function';

        // if property was created, "remove it" (by setting value to `undefined`)
        if (typeof element[eventName] != 'undefined') {
          element[eventName] = undef;
        }
        element.removeAttribute(eventName);
      }
    }

    element = null;
    return isSupported;
  }
  return isEventSupported;
})();

var isEventSupportedWithCache = (function(undef) {

  var TAGNAMES = {
    'select':'input','change':'input',
    'submit':'form','reset':'form',
    'error':'img','load':'img','abort':'img'
  },
  cache = { };

  function isEventSupported(eventName, element) {
    var canCache = (arguments.length == 1);

    // only return cached result when no element is given
    if (canCache && cache[eventName]) {
      return cache[eventName];
    }

    element = element || document.createElement(TAGNAMES[eventName] || 'div');
    eventName = 'on' + eventName;

    // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
    var isSupported = (eventName in element);

    if (!isSupported) {
      // if it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
      if (!element.setAttribute) {
        element = document.createElement('div');
      }
      if (element.setAttribute && element.removeAttribute) {
        element.setAttribute(eventName, '');
        isSupported = typeof element[eventName] == 'function';

        // if property was created, "remove it" (by setting value to `undefined`)
        if (typeof element[eventName] != 'undefined') {
          element[eventName] = undef;
        }
        element.removeAttribute(eventName);
      }
    }

    element = null;
    return canCache ? (cache[eventName] = isSupported) : isSupported;
  }
  return isEventSupported;
})();<|endoftext|>