<commit_before>const EventEmitter = require('events');
const BrowserName = require('../util/browsername.js');
const ElementsByRecursion = require('../api/element-commands/_elementsByRecursion.js');
const SingleElementByRecursion = require('../api/element-commands/_elementByRecursion.js');
const HttpRequest = require('../http/request.js');
const Actions = require('./actions.js');
const Utils = require('../util/utils.js');
const Element = require('../page-object/element.js');
const Logger = require('../util/logger.js');

class Transport extends EventEmitter {
  static get DO_NOT_LOG_ERRORS() {
    return [
      'Unable to locate element',
      '{"errorMessage":"Unable to find element',
      'no such element'
    ];
  }

  static get MAX_CONCURRENT_PROMISES() {
    return 8;
  }

  /**
   * @param {Array<Promise>} promises
   */
  static runPromises(promises) {
    let allResults = [];
    function handleResult(result) {
      allResults.push(result);
    }

    return Utils.processAsyncQueue(Transport.MAX_CONCURRENT_PROMISES, promises, function(promise, index, next) {
      promise.then(handleResult).catch(handleResult).then(function () {
        next(index);
      });
    }).then(function() {
      return allResults;
    });
  }

  constructor(nightwatchInstance) {
    super();

    this.nightwatchInstance = nightwatchInstance;
    this.actionsInstance = new Actions(this);
    this.actionsInstance.loadActions(this.MethodMappings);
  }

  get Actions() {
    return this.actionsInstance.actions;
  }

  get MethodMappings() {
    return require('./jsonwire/actions.js');
  }

  get reporter() {
    return this.nightwatchInstance.reporter;
  }

  get api() {
    return this.nightwatchInstance.api;
  }

  get settings() {
    return this.nightwatchInstance.settings;
  }

  get desiredCapabilities() {
    return this.nightwatchInstance.session.desiredCapabilities;
  }

  get defaultPathPrefix() {
    return '';
  }

  get defaultPort() {
    return 4444;
  }

  get Errors() {
    return {
      StatusCode: {},
      findErrorById: function() {}
    };
  }

  formatCommandResponseData() {}
  isResultSuccess() {}

  ////////////////////////////////////////////////////////////////////
  // Session related
  ////////////////////////////////////////////////////////////////////
  parseSessionResponse(data = {}) {
    const sessionData = data.value || {};

    return {
      sessionId: sessionData.sessionId,
      capabilities: sessionData.capabilities || {}
    };
  }

  getErrorMessage(result) {
    return result.value.message;
  }

  staleElementReference(result) {
    return result.errorStatus === this.Errors.StatusCode.STALE_ELEMENT_REFERENCE;
  }

  invalidSessionError(result) {
    return result.errorStatus === this.Errors.StatusCode.NO_SUCH_SESSION;
  }

  handleErrorResponse(data = null) {
    let err = new Error('An error occurred while retrieving a new session');
    let addtMsg = '';

    if (data instanceof Error) {
      switch (data.code) {
        case 'ECONNREFUSED':
          err.sessionConnectionRefused = true;
          addtMsg = `Connection refused to ${data.address}:${data.port}`;
          break;
        default:
          addtMsg = data.message;
      }

    } else if (Utils.isObject(data) && Object.keys(data).length > 0) {
      err.data = JSON.stringify(data.value || data);

      // legacy errors
      if (data.value.message) {
        addtMsg = data.value.message;
      }
    }

    if (addtMsg) {
      err.message = err.message + `: "${addtMsg}"`;
    }

    if (data.code) {
      err.code = data.code;
      if (err.sessionConnectionRefused) {
        err.message += '. If the Webdriver/Selenium service is managed by Nightwatch, check if "start_process" is set to "true".';
      }
    }

    this.emit('transport:session.error', err);

    return this;
  }

  createSession() {
    const body = {};
    if (this.settings.capabilities) {
      body.capabilities = this.settings.capabilities;
    }

    if (this.desiredCapabilities) {
      body.desiredCapabilities = this.desiredCapabilities;
    }

    const request = this.createProtocolAction({
      path : '/session',
      data : body
    });

    request
      .on('error', err => {
        this.handleErrorResponse(err);
      })
      .on('success', (data, response, isRedirect) => {
        let sessionData = this.parseSessionResponse(data);

        if (sessionData.sessionId) {
          this.emit('transport:session.create', sessionData, request, response);
        } else if (isRedirect) {
          this.followRedirect(request, response);
        } else {
          this.handleErrorResponse(data);
        }
      })
      .post();

    return this;
  }

  closeSession() {
    return new Promise((resolve, reject) => {
      this.api.end(result => {
        resolve(result);
      });
    });
  }

  createProtocolAction(requestOptions) {
    const request = new HttpRequest(requestOptions);
    request.on('response', this.formatCommandResponseData.bind(this));

    return request;
  }

  sendProtocolAction(request, promiseFn) {
    return new Promise((resolve, reject) => {
      promiseFn.call(this, resolve, reject);
      request.send();
    });
  }

  ////////////////////////////////////////////////////////////////////
  // Element locating
  ////////////////////////////////////////////////////////////////////
  getElementId(value) {
    return value;
  }

  mapWebElementIds(result) {
    if (result.value) {
      result.value = result.value.reduce((prev, item) => {
        prev.push(this.getElementId(item));

        return prev;
      }, []);
    }

    return result;
  }

  resolveElement(result, element, multipleElements) {
    if (!this.isResultSuccess(result)) {
      return null;
    }

    let value = result.value;

    if (multipleElements && Array.isArray(value) && value.length > 0) {
      if (value.length > 1) {
        let message = `More than one element (${value.length}) found for <${element.toString()}> with selector: "${element.selector}".`;

        if (this.settings.globals.throwOnMultipleElementsReturned) {
          throw new Error(message);
        }

        if (this.settings.output) {
          console.warn(Logger.colors.green(`  Warning: ${message} Only the first one will be used.`));
        }
      }
      value = value[0];
    } else if (Array.isArray(value) && value.length === 0) {
      value = null;
    }

    let parsedValue = value && this.getElementId(value);

    return {
      status: 0,
      // for recursive lookups, the value is already parsed
      value: typeof parsedValue == 'undefined' ? value : parsedValue
    };
  }

  /**
   * Selects a subset of elements if the result requires filtering.
   *
   * @param {Element} element
   * @param {object} result
   * @return {*}
   */
  filterElements(element, result) {
    let filtered = Element.applyFiltering(element, result.value);

    if (filtered) {
      result.value = filtered;

      return result;
    }

    result = this.getElementNotFoundResult(result);

    throw result;
  }

  getElementNotFoundResult(result) {
    result.status = -1;
    result.value = [];

    let errorId = this.Errors.StatusCode && this.Errors.StatusCode.NO_SUCH_ELEMENT;
    let errorInfo = this.Errors.findErrorById(errorId);

    if (errorInfo) {
      result.message = errorInfo.message;
      result.errorStatus = errorInfo.status;
    }

    return result;
  }

  /**
   * Used by waitForElement commands
   *
   * @param {Element} element
   * @return {Promise}
   */
  locateMultipleElements(element) {
    if (element.usingRecursion) {
      return this.locateElementsUsingRecursion(element);
    }

    return this.executeProtocolAction('locateMultipleElements', [element.locateStrategy, element.selector])
      .then(result => {
        if (this.isResultSuccess(result) && Element.requiresFiltering(element)) {
          return this.filterElements(element, result);
        }

        return result;
      })
      .catch(result => {
        if (this.invalidSessionError(result)) {
          return new Error(`An error occurred while running ".locateMultipleElements()": ${this.getErrorMessage(result)}.`);
        }

        return [];
      });
  }

  /**
   * @param {Element} element
   * @return {Promise}
   */
  locateElementsUsingRecursion(element) {
    let recursion = new ElementsByRecursion(this.nightwatchInstance);

    return recursion.locateElements(element.selector);
  }

  locateSingleElementUsingRecursion(element) {
    let recursion = new SingleElementByRecursion(this.nightwatchInstance);

    return recursion.locateElement(element.selector);
  }

  /**
   * Used by expect element assertions
   *
   * @param {Element} element
   * @return {Promise}
   */
  locateElement(element) {
    if (element.usingRecursion) {
      return Element.requiresFiltering(element) ?
        this.locateElementsUsingRecursion(element):
        this.locateSingleElementUsingRecursion(element);
    }

    let elementAction = Transport.getElementAction(element);

    return this.callElementLocateAction(element, elementAction, [element.locateStrategy, element.selector]);
  }

  /**
   * Used by recursive lookup command for multi elements (in page objects)
   *
   * @param {Object} result
   * @param {Element} element
   * @return {Promise}
   */
  locateMultipleElementsFromParent(result, element) {
    let promises = [];

    result.value.forEach(elementId => {
      promises.push(this.locateElementFromParent(elementId, element));
    });

    return Transport.runPromises(promises).then(results => {
      if (results.length === 1 && results[0] instanceof Error) {
        throw results[0];
      }

      let failed = 0;
      let elementResult = results.reduce((prev, item) => {
        // In case we have multiple matches on the same element, only add once
        if (this.isResultSuccess(item) && prev.value.indexOf(item.value) < 0) {
          prev.value.push(item.value);
        } else {
          if (item instanceof Error) {
            Logger.error(item.stack);
          }

          failed++;
        }

        return prev;
      }, {value: [], status: 0});

      if (failed === results.length) {
        elementResult = this.getElementNotFoundResult(elementResult);
      }

      return elementResult;
    });
  }

  /**
   * Used by recursive lookup command for a single element
   *
   * @param {string} parentElementId
   * @param {Element} element
   * @return {Promise}
   */
  locateElementFromParent(parentElementId, element) {
    return this.callElementLocateAction(element, 'locateMultipleElementsByElementId', [parentElementId, element.locateStrategy, element.selector], true);
  }

  /**
   * Helper method
   *
   * @param {Element} element
   * @param {String} elementAction
   * @param {Array} args
   * @param {Boolean} multipleElements
   */
  callElementLocateAction(element, elementAction, args, multipleElements = false) {
    return this.executeProtocolAction(elementAction, args)
      .then(result => {
        if (this.isResultSuccess(result) && Element.requiresFiltering(element)) {
          return this.filterElements(element, result);
        }

        return result;
      })
      .then(result => {
        let elementResult = this.resolveElement(result, element, Element.requiresFiltering(element) || multipleElements);
        if (elementResult) {
          return elementResult;
        }

        throw result;
      });
  }

  /**
   * Helper method
   *
   * @param {String} protocolAction
   * @param {Array} args
   * @return {Promise}
   */
  executeProtocolAction(protocolAction, args) {
    return this.Actions.session[protocolAction]({
      args: args,
      sessionId: this.api.sessionId,
      sessionRequired: true
    });
  }

  shouldRegisterError(errorResult) {
    let errorMessage = typeof errorResult == 'string' ? errorResult : (errorResult.error || errorResult.message);

    return !Transport.DO_NOT_LOG_ERRORS.some(function(item) {
      return errorMessage.indexOf(item) === 0;
    });
  }

  static adaptWebdriverSettings(settings, usingSeleniumServer = false) {
    const browserName = settings.desiredCapabilities.browserName.toLowerCase();

    if (usingSeleniumServer && [BrowserName.CHROME, BrowserName.EDGE].includes(browserName)) {
      settings.selenium.version2 = true;

      return;
    }

    switch (browserName) {
      case BrowserName.SAFARI:
        if (settings.webdriver.start_process && settings.webdriver.use_legacy_jsonwire === undefined) {
          const SafariDriver = require('../runner/wd-instances/safaridriver.js');
          settings.webdriver.use_legacy_jsonwire = SafariDriver.useLegacyDriver;
        }
        break;

      case BrowserName.FIREFOX:
        settings.webdriver.use_legacy_jsonwire = false;
        break;
    }

    if (settings.webdriver.use_legacy_jsonwire === undefined) {
      settings.webdriver.use_legacy_jsonwire = true;
    }

    if (!settings.webdriver.use_legacy_jsonwire && !usingSeleniumServer) {
      settings.capabilities = settings.desiredCapabilities;
    }
  }

  static create(nightwatchInstance) {
    const settings = nightwatchInstance.settings;
    const usingSeleniumServer = settings.selenium && (
      settings.selenium.start_process ||
      !settings.webdriver.start_process && (settings.selenium_host || settings.selenium.host || settings.seleniumHost)
    );

    Transport.adaptWebdriverSettings(settings, usingSeleniumServer);

    // Legacy Selenium Server 2
    if (usingSeleniumServer && settings.selenium.version2) {
      const Selenium2 = require('./selenium2.js');

      return new Selenium2(nightwatchInstance);
    }

    // Selenium Server 3
    if (usingSeleniumServer) {
      const SeleniumProtocol = require('./selenium3.js');

      return new SeleniumProtocol(nightwatchInstance);
    }

    // drivers using the legacy JSONWire protocol
    if (settings.webdriver.use_legacy_jsonwire) {
      const JsonWireProtocol = require('./jsonwire.js');

      return new JsonWireProtocol(nightwatchInstance);
    }

    const WebdriverProtocol = require('./webdriver.js');

    return new WebdriverProtocol(nightwatchInstance);
  }

  /**
   *
   * @param {Element} element
   * @param {Boolean} usingParent
   * @return {*}
   */
  static getElementAction(element, usingParent = false) {
    let multipleElements = Element.requiresFiltering(element);

    return multipleElements ? (usingParent ? 'locateMultipleElementsByElementId' : 'locateMultipleElements') :
      (usingParent ? 'locateSingleElementByElementId' : 'locateSingleElement');
  }
}

module.exports = Transport;
<commit_msg>feature:  Hide "waitForElement" warnings when "detailed_output:" is set to "false" (#2062)<commit_after>const EventEmitter = require('events');
const BrowserName = require('../util/browsername.js');
const ElementsByRecursion = require('../api/element-commands/_elementsByRecursion.js');
const SingleElementByRecursion = require('../api/element-commands/_elementByRecursion.js');
const HttpRequest = require('../http/request.js');
const Actions = require('./actions.js');
const Utils = require('../util/utils.js');
const Element = require('../page-object/element.js');
const Logger = require('../util/logger.js');

class Transport extends EventEmitter {
  static get DO_NOT_LOG_ERRORS() {
    return [
      'Unable to locate element',
      '{"errorMessage":"Unable to find element',
      'no such element'
    ];
  }

  static get MAX_CONCURRENT_PROMISES() {
    return 8;
  }

  /**
   * @param {Array<Promise>} promises
   */
  static runPromises(promises) {
    let allResults = [];
    function handleResult(result) {
      allResults.push(result);
    }

    return Utils.processAsyncQueue(Transport.MAX_CONCURRENT_PROMISES, promises, function(promise, index, next) {
      promise.then(handleResult).catch(handleResult).then(function () {
        next(index);
      });
    }).then(function() {
      return allResults;
    });
  }

  constructor(nightwatchInstance) {
    super();

    this.nightwatchInstance = nightwatchInstance;
    this.actionsInstance = new Actions(this);
    this.actionsInstance.loadActions(this.MethodMappings);
  }

  get Actions() {
    return this.actionsInstance.actions;
  }

  get MethodMappings() {
    return require('./jsonwire/actions.js');
  }

  get reporter() {
    return this.nightwatchInstance.reporter;
  }

  get api() {
    return this.nightwatchInstance.api;
  }

  get settings() {
    return this.nightwatchInstance.settings;
  }

  get desiredCapabilities() {
    return this.nightwatchInstance.session.desiredCapabilities;
  }

  get defaultPathPrefix() {
    return '';
  }

  get defaultPort() {
    return 4444;
  }

  get Errors() {
    return {
      StatusCode: {},
      findErrorById: function() {}
    };
  }

  formatCommandResponseData() {}
  isResultSuccess() {}

  ////////////////////////////////////////////////////////////////////
  // Session related
  ////////////////////////////////////////////////////////////////////
  parseSessionResponse(data = {}) {
    const sessionData = data.value || {};

    return {
      sessionId: sessionData.sessionId,
      capabilities: sessionData.capabilities || {}
    };
  }

  getErrorMessage(result) {
    return result.value.message;
  }

  staleElementReference(result) {
    return result.errorStatus === this.Errors.StatusCode.STALE_ELEMENT_REFERENCE;
  }

  invalidSessionError(result) {
    return result.errorStatus === this.Errors.StatusCode.NO_SUCH_SESSION;
  }

  handleErrorResponse(data = null) {
    let err = new Error('An error occurred while retrieving a new session');
    let addtMsg = '';

    if (data instanceof Error) {
      switch (data.code) {
        case 'ECONNREFUSED':
          err.sessionConnectionRefused = true;
          addtMsg = `Connection refused to ${data.address}:${data.port}`;
          break;
        default:
          addtMsg = data.message;
      }

    } else if (Utils.isObject(data) && Object.keys(data).length > 0) {
      err.data = JSON.stringify(data.value || data);

      // legacy errors
      if (data.value.message) {
        addtMsg = data.value.message;
      }
    }

    if (addtMsg) {
      err.message = err.message + `: "${addtMsg}"`;
    }

    if (data.code) {
      err.code = data.code;
      if (err.sessionConnectionRefused) {
        err.message += '. If the Webdriver/Selenium service is managed by Nightwatch, check if "start_process" is set to "true".';
      }
    }

    this.emit('transport:session.error', err);

    return this;
  }

  createSession() {
    const body = {};
    if (this.settings.capabilities) {
      body.capabilities = this.settings.capabilities;
    }

    if (this.desiredCapabilities) {
      body.desiredCapabilities = this.desiredCapabilities;
    }

    const request = this.createProtocolAction({
      path : '/session',
      data : body
    });

    request
      .on('error', err => {
        this.handleErrorResponse(err);
      })
      .on('success', (data, response, isRedirect) => {
        let sessionData = this.parseSessionResponse(data);

        if (sessionData.sessionId) {
          this.emit('transport:session.create', sessionData, request, response);
        } else if (isRedirect) {
          this.followRedirect(request, response);
        } else {
          this.handleErrorResponse(data);
        }
      })
      .post();

    return this;
  }

  closeSession() {
    return new Promise((resolve, reject) => {
      this.api.end(result => {
        resolve(result);
      });
    });
  }

  createProtocolAction(requestOptions) {
    const request = new HttpRequest(requestOptions);
    request.on('response', this.formatCommandResponseData.bind(this));

    return request;
  }

  sendProtocolAction(request, promiseFn) {
    return new Promise((resolve, reject) => {
      promiseFn.call(this, resolve, reject);
      request.send();
    });
  }

  ////////////////////////////////////////////////////////////////////
  // Element locating
  ////////////////////////////////////////////////////////////////////
  getElementId(value) {
    return value;
  }

  mapWebElementIds(result) {
    if (result.value) {
      result.value = result.value.reduce((prev, item) => {
        prev.push(this.getElementId(item));

        return prev;
      }, []);
    }

    return result;
  }

  resolveElement(result, element, multipleElements) {
    if (!this.isResultSuccess(result)) {
      return null;
    }

    let value = result.value;

    if (multipleElements && Array.isArray(value) && value.length > 0) {
      if (value.length > 1) {
        let message = `More than one element (${value.length}) found for <${element.toString()}> with selector: "${element.selector}".`;

        if (this.settings.globals.throwOnMultipleElementsReturned) {
          throw new Error(message);
        }

        if (this.settings.output && this.settings.detailed_output) {
          console.warn(Logger.colors.green(`  Warning: ${message} Only the first one will be used.`));
        }
      }
      value = value[0];
    } else if (Array.isArray(value) && value.length === 0) {
      value = null;
    }

    let parsedValue = value && this.getElementId(value);

    return {
      status: 0,
      // for recursive lookups, the value is already parsed
      value: typeof parsedValue == 'undefined' ? value : parsedValue
    };
  }

  /**
   * Selects a subset of elements if the result requires filtering.
   *
   * @param {Element} element
   * @param {object} result
   * @return {*}
   */
  filterElements(element, result) {
    let filtered = Element.applyFiltering(element, result.value);

    if (filtered) {
      result.value = filtered;

      return result;
    }

    result = this.getElementNotFoundResult(result);

    throw result;
  }

  getElementNotFoundResult(result) {
    result.status = -1;
    result.value = [];

    let errorId = this.Errors.StatusCode && this.Errors.StatusCode.NO_SUCH_ELEMENT;
    let errorInfo = this.Errors.findErrorById(errorId);

    if (errorInfo) {
      result.message = errorInfo.message;
      result.errorStatus = errorInfo.status;
    }

    return result;
  }

  /**
   * Used by waitForElement commands
   *
   * @param {Element} element
   * @return {Promise}
   */
  locateMultipleElements(element) {
    if (element.usingRecursion) {
      return this.locateElementsUsingRecursion(element);
    }

    return this.executeProtocolAction('locateMultipleElements', [element.locateStrategy, element.selector])
      .then(result => {
        if (this.isResultSuccess(result) && Element.requiresFiltering(element)) {
          return this.filterElements(element, result);
        }

        return result;
      })
      .catch(result => {
        if (this.invalidSessionError(result)) {
          return new Error(`An error occurred while running ".locateMultipleElements()": ${this.getErrorMessage(result)}.`);
        }

        return [];
      });
  }

  /**
   * @param {Element} element
   * @return {Promise}
   */
  locateElementsUsingRecursion(element) {
    let recursion = new ElementsByRecursion(this.nightwatchInstance);

    return recursion.locateElements(element.selector);
  }

  locateSingleElementUsingRecursion(element) {
    let recursion = new SingleElementByRecursion(this.nightwatchInstance);

    return recursion.locateElement(element.selector);
  }

  /**
   * Used by expect element assertions
   *
   * @param {Element} element
   * @return {Promise}
   */
  locateElement(element) {
    if (element.usingRecursion) {
      return Element.requiresFiltering(element) ?
        this.locateElementsUsingRecursion(element):
        this.locateSingleElementUsingRecursion(element);
    }

    let elementAction = Transport.getElementAction(element);

    return this.callElementLocateAction(element, elementAction, [element.locateStrategy, element.selector]);
  }

  /**
   * Used by recursive lookup command for multi elements (in page objects)
   *
   * @param {Object} result
   * @param {Element} element
   * @return {Promise}
   */
  locateMultipleElementsFromParent(result, element) {
    let promises = [];

    result.value.forEach(elementId => {
      promises.push(this.locateElementFromParent(elementId, element));
    });

    return Transport.runPromises(promises).then(results => {
      if (results.length === 1 && results[0] instanceof Error) {
        throw results[0];
      }

      let failed = 0;
      let elementResult = results.reduce((prev, item) => {
        // In case we have multiple matches on the same element, only add once
        if (this.isResultSuccess(item) && prev.value.indexOf(item.value) < 0) {
          prev.value.push(item.value);
        } else {
          if (item instanceof Error) {
            Logger.error(item.stack);
          }

          failed++;
        }

        return prev;
      }, {value: [], status: 0});

      if (failed === results.length) {
        elementResult = this.getElementNotFoundResult(elementResult);
      }

      return elementResult;
    });
  }

  /**
   * Used by recursive lookup command for a single element
   *
   * @param {string} parentElementId
   * @param {Element} element
   * @return {Promise}
   */
  locateElementFromParent(parentElementId, element) {
    return this.callElementLocateAction(element, 'locateMultipleElementsByElementId', [parentElementId, element.locateStrategy, element.selector], true);
  }

  /**
   * Helper method
   *
   * @param {Element} element
   * @param {String} elementAction
   * @param {Array} args
   * @param {Boolean} multipleElements
   */
  callElementLocateAction(element, elementAction, args, multipleElements = false) {
    return this.executeProtocolAction(elementAction, args)
      .then(result => {
        if (this.isResultSuccess(result) && Element.requiresFiltering(element)) {
          return this.filterElements(element, result);
        }

        return result;
      })
      .then(result => {
        let elementResult = this.resolveElement(result, element, Element.requiresFiltering(element) || multipleElements);
        if (elementResult) {
          return elementResult;
        }

        throw result;
      });
  }

  /**
   * Helper method
   *
   * @param {String} protocolAction
   * @param {Array} args
   * @return {Promise}
   */
  executeProtocolAction(protocolAction, args) {
    return this.Actions.session[protocolAction]({
      args: args,
      sessionId: this.api.sessionId,
      sessionRequired: true
    });
  }

  shouldRegisterError(errorResult) {
    let errorMessage = typeof errorResult == 'string' ? errorResult : (errorResult.error || errorResult.message);

    return !Transport.DO_NOT_LOG_ERRORS.some(function(item) {
      return errorMessage.indexOf(item) === 0;
    });
  }

  static adaptWebdriverSettings(settings, usingSeleniumServer = false) {
    const browserName = settings.desiredCapabilities.browserName.toLowerCase();

    if (usingSeleniumServer && [BrowserName.CHROME, BrowserName.EDGE].includes(browserName)) {
      settings.selenium.version2 = true;

      return;
    }

    switch (browserName) {
      case BrowserName.SAFARI:
        if (settings.webdriver.start_process && settings.webdriver.use_legacy_jsonwire === undefined) {
          const SafariDriver = require('../runner/wd-instances/safaridriver.js');
          settings.webdriver.use_legacy_jsonwire = SafariDriver.useLegacyDriver;
        }
        break;

      case BrowserName.FIREFOX:
        settings.webdriver.use_legacy_jsonwire = false;
        break;
    }

    if (settings.webdriver.use_legacy_jsonwire === undefined) {
      settings.webdriver.use_legacy_jsonwire = true;
    }

    if (!settings.webdriver.use_legacy_jsonwire && !usingSeleniumServer) {
      settings.capabilities = settings.desiredCapabilities;
    }
  }

  static create(nightwatchInstance) {
    const settings = nightwatchInstance.settings;
    const usingSeleniumServer = settings.selenium && (
      settings.selenium.start_process ||
      !settings.webdriver.start_process && (settings.selenium_host || settings.selenium.host || settings.seleniumHost)
    );

    Transport.adaptWebdriverSettings(settings, usingSeleniumServer);

    // Legacy Selenium Server 2
    if (usingSeleniumServer && settings.selenium.version2) {
      const Selenium2 = require('./selenium2.js');

      return new Selenium2(nightwatchInstance);
    }

    // Selenium Server 3
    if (usingSeleniumServer) {
      const SeleniumProtocol = require('./selenium3.js');

      return new SeleniumProtocol(nightwatchInstance);
    }

    // drivers using the legacy JSONWire protocol
    if (settings.webdriver.use_legacy_jsonwire) {
      const JsonWireProtocol = require('./jsonwire.js');

      return new JsonWireProtocol(nightwatchInstance);
    }

    const WebdriverProtocol = require('./webdriver.js');

    return new WebdriverProtocol(nightwatchInstance);
  }

  /**
   *
   * @param {Element} element
   * @param {Boolean} usingParent
   * @return {*}
   */
  static getElementAction(element, usingParent = false) {
    let multipleElements = Element.requiresFiltering(element);

    return multipleElements ? (usingParent ? 'locateMultipleElementsByElementId' : 'locateMultipleElements') :
      (usingParent ? 'locateSingleElementByElementId' : 'locateSingleElement');
  }
}

module.exports = Transport;
<|endoftext|>


<commit_before>
/*!
 * socket.io-node
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module requirements.
 */

var HTTPTransport = require('./http');

/**
 * Export the constructor.
 */

exports = module.exports = HTMLFile;

/**
 * HTMLFile transport constructor.
 *
 * @api public
 */

function HTMLFile (mng, data) {
  HTTPTransport.call(this, mng, data);
};

/**
 * Inherits from Transport.
 */

HTMLFile.prototype.__proto__ = HTTPTransport.prototype;

/**
 * Handles the request.
 *
 * @api private
 */

HTMLFile.prototype.handleRequest = function (req) {
  HTTPTransport.prototype.handleRequest.call(this, req);

  if (req.method == 'GET') {
    req.res.writeHead(200, {
        'Content-Type': 'text/html'
      , 'Connection': 'keep-alive'
      , 'Transfer-Encoding': 'chunked'
    });

    req.res.write(
        '<html><body>'
      + '<script>var _ = function (msg) { parent.s._(msg, document); };</script>'
      + new Array(174).join(' ')
    );
  }
};

/**
 * Performs the write.
 *
 * @api private
 */

HTMLFile.prototype.write = function (data) {
  data = '<script>_(' + JSON.stringify(data) + ');</script>';

  this.response.write(data);
  this.log.debug('htmlfile writing', data);
};
<commit_msg>Make sure to set drain to false upon htmlfile transport `write`.<commit_after>
/*!
 * socket.io-node
 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module requirements.
 */

var HTTPTransport = require('./http');

/**
 * Export the constructor.
 */

exports = module.exports = HTMLFile;

/**
 * HTMLFile transport constructor.
 *
 * @api public
 */

function HTMLFile (mng, data) {
  HTTPTransport.call(this, mng, data);
};

/**
 * Inherits from Transport.
 */

HTMLFile.prototype.__proto__ = HTTPTransport.prototype;

/**
 * Handles the request.
 *
 * @api private
 */

HTMLFile.prototype.handleRequest = function (req) {
  HTTPTransport.prototype.handleRequest.call(this, req);

  if (req.method == 'GET') {
    req.res.writeHead(200, {
        'Content-Type': 'text/html'
      , 'Connection': 'keep-alive'
      , 'Transfer-Encoding': 'chunked'
    });

    req.res.write(
        '<html><body>'
      + '<script>var _ = function (msg) { parent.s._(msg, document); };</script>'
      + new Array(174).join(' ')
    );
  }
};

/**
 * Performs the write.
 *
 * @api private
 */

HTMLFile.prototype.write = function (data) {
  data = '<script>_(' + JSON.stringify(data) + ');</script>';

  this.drain = false;
  this.response.write(data);
  this.log.debug('htmlfile writing', data);
};
<|endoftext|>


<commit_before>/**
 * @module echarts/chart/helper/EffectLine
 */
define(function (require) {

    var graphic = require('../../util/graphic');
    var Line = require('./Line');
    var zrUtil = require('zrender/core/util');
    var symbolUtil = require('../../util/symbol');

    var curveUtil = require('zrender/core/curve');

    /**
     * @constructor
     * @extends {module:zrender/graphic/Group}
     * @alias {module:echarts/chart/helper/Line}
     */
    function EffectLine(lineData, idx) {
        graphic.Group.call(this);

        var line = new Line(lineData, idx);
        this.add(line);

        this._updateEffectSymbol(lineData, idx);
    }

    var effectLineProto = EffectLine.prototype;

    function setAnimationPoints(symbol, points) {
        symbol.__p1 = points[0];
        symbol.__p2 = points[1];
        symbol.__cp1 = points[2] || [
            (points[0][0] + points[1][0]) / 2,
            (points[0][1] + points[1][1]) / 2
        ];
    }

    function updateSymbolPosition() {
        var p1 = this.__p1;
        var p2 = this.__p2;
        var cp1 = this.__cp1;
        var t = this.__t;
        var pos = this.position;
        var quadraticAt = curveUtil.quadraticAt;
        var quadraticDerivativeAt = curveUtil.quadraticDerivativeAt;
        pos[0] = quadraticAt(p1[0], cp1[0], p2[0], t);
        pos[1] = quadraticAt(p1[1], cp1[1], p2[1], t);

        // Tangent
        var tx = quadraticDerivativeAt(p1[0], cp1[0], p2[0], t);
        var ty = quadraticDerivativeAt(p1[1], cp1[1], p2[1], t);

        this.rotation = -Math.atan2(ty, tx) - Math.PI / 2;

        this.ignore = false;
    }

    effectLineProto._updateEffectSymbol = function (lineData, idx) {
        var itemModel = lineData.getItemModel(idx);
        var effectModel = itemModel.getModel('effect');
        var size = effectModel.get('symbolSize');
        var symbolType = effectModel.get('symbol');
        if (!zrUtil.isArray(size)) {
            size = [size, size];
        }
        var color = effectModel.get('color') || lineData.getItemVisual(idx, 'color');
        var symbol = this.childAt(1);
        var period = effectModel.get('period') * 1000;
        var loop = effectModel.get('loop');
        if (
            this._symbolType !== symbolType
            || period !== this._period
            || loop !== this._loop
        ) {
            symbol = symbolUtil.createSymbol(
                symbolType, -0.5, -0.5, 1, 1, color
            );
            symbol.ignore = true;
            symbol.z2 = 100;
            this._symbolType = symbolType;
            this._period = period;
            this._loop = loop;

            this.add(symbol);

            symbol.__t = 0;
            var animator = symbol.animate('', loop)
                .when(period, {
                    __t: 1
                })
                .delay(idx / lineData.count() * period / 2)
                .during(zrUtil.bind(updateSymbolPosition, symbol));
            if (!loop) {
                var self = this;
                animator.done(function () {
                    self.remove(symbol);
                });
            }
            animator.start();
        }
        // Shadow color is same with color in default
        symbol.setStyle('shadowColor', color);
        symbol.setStyle(effectModel.getItemStyle(['color']));

        symbol.attr('scale', size);
        var points = lineData.getItemLayout(idx);
        setAnimationPoints(symbol, points);

        symbol.setColor(color);
        symbol.attr('scale', size);
    };

    effectLineProto.updateData = function (lineData, idx) {
        this.childAt(0).updateData(lineData, idx);
        this._updateEffectSymbol(lineData, idx);
    };

    effectLineProto.updateLayout = function (lineData, idx) {
        this.childAt(0).updateLayout(lineData, idx);
        var symbol = this.childAt(1);
        var points = lineData.getItemLayout(idx);
        setAnimationPoints(symbol, points);
    };

    zrUtil.inherits(EffectLine, graphic.Group);

    return EffectLine;
});<commit_msg>Improve oneshot line effect<commit_after>/**
 * @module echarts/chart/helper/EffectLine
 */
define(function (require) {

    var graphic = require('../../util/graphic');
    var Line = require('./Line');
    var zrUtil = require('zrender/core/util');
    var symbolUtil = require('../../util/symbol');

    var curveUtil = require('zrender/core/curve');

    /**
     * @constructor
     * @extends {module:zrender/graphic/Group}
     * @alias {module:echarts/chart/helper/Line}
     */
    function EffectLine(lineData, idx) {
        graphic.Group.call(this);

        var line = new Line(lineData, idx);
        this.add(line);

        this._updateEffectSymbol(lineData, idx);
    }

    var effectLineProto = EffectLine.prototype;

    function setAnimationPoints(symbol, points) {
        symbol.__p1 = points[0];
        symbol.__p2 = points[1];
        symbol.__cp1 = points[2] || [
            (points[0][0] + points[1][0]) / 2,
            (points[0][1] + points[1][1]) / 2
        ];
    }

    function updateSymbolPosition() {
        var p1 = this.__p1;
        var p2 = this.__p2;
        var cp1 = this.__cp1;
        var t = this.__t;
        var pos = this.position;
        var quadraticAt = curveUtil.quadraticAt;
        var quadraticDerivativeAt = curveUtil.quadraticDerivativeAt;
        pos[0] = quadraticAt(p1[0], cp1[0], p2[0], t);
        pos[1] = quadraticAt(p1[1], cp1[1], p2[1], t);

        // Tangent
        var tx = quadraticDerivativeAt(p1[0], cp1[0], p2[0], t);
        var ty = quadraticDerivativeAt(p1[1], cp1[1], p2[1], t);

        this.rotation = -Math.atan2(ty, tx) - Math.PI / 2;

        this.ignore = false;
    }

    effectLineProto._updateEffectSymbol = function (lineData, idx) {
        var itemModel = lineData.getItemModel(idx);
        var effectModel = itemModel.getModel('effect');
        var size = effectModel.get('symbolSize');
        var symbolType = effectModel.get('symbol');
        if (!zrUtil.isArray(size)) {
            size = [size, size];
        }
        var color = effectModel.get('color') || lineData.getItemVisual(idx, 'color');
        var symbol = this.childAt(1);
        var period = effectModel.get('period') * 1000;
        var loop = effectModel.get('loop');
        if (
            this._symbolType !== symbolType
            || period !== this._period
            || loop !== this._loop
        ) {
            symbol = symbolUtil.createSymbol(
                symbolType, -0.5, -0.5, 1, 1, color
            );
            symbol.ignore = true;
            symbol.z2 = 100;
            this._symbolType = symbolType;
            this._period = period;
            this._loop = loop;

            this.add(symbol);

            symbol.__t = 0;
            var animator = symbol.animate('', loop)
                .when(period, {
                    __t: 1
                })
                .delay(idx / lineData.count() * period / 2)
                .during(zrUtil.bind(updateSymbolPosition, symbol));
            if (!loop) {
                var self = this;
                animator.done(function () {
                    self.remove(symbol);
                });
            }
            animator.start();
        }
        // Shadow color is same with color in default
        symbol.setStyle('shadowColor', color);
        symbol.setStyle(effectModel.getItemStyle(['color']));

        symbol.attr('scale', size);
        var points = lineData.getItemLayout(idx);
        setAnimationPoints(symbol, points);

        symbol.setColor(color);
        symbol.attr('scale', size);
    };

    effectLineProto.updateData = function (lineData, idx) {
        this.childAt(0).updateData(lineData, idx);
        this._updateEffectSymbol(lineData, idx);
    };

    effectLineProto.updateLayout = function (lineData, idx) {
        this.childAt(0).updateLayout(lineData, idx);
        var symbol = this.childAt(1);
        if (symbol) {
            var points = lineData.getItemLayout(idx);
            setAnimationPoints(symbol, points);
        }
    };

    zrUtil.inherits(EffectLine, graphic.Group);

    return EffectLine;
});<|endoftext|>


<commit_before>/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import * as graphic from '../../util/graphic';
import * as echarts from '../../echarts';
import * as zrUtil from 'zrender/src/core/util';

var nodeOpacityPath = ['itemStyle', 'opacity'];
var lineOpacityPath = ['lineStyle', 'opacity'];

function getItemOpacity(item, opacityPath) {
    return item.getVisual('opacity') || item.getModel().get(opacityPath);
}

function fadeOutItem(item, opacityPath, opacityRatio) {
    var el = item.getGraphicEl();

    var opacity = getItemOpacity(item, opacityPath);
    if (opacityRatio != null) {
        opacity == null && (opacity = 1);
        opacity *= opacityRatio;
    }

    el.downplay && el.downplay();
    el.traverse(function (child) {
        if (child.type !== 'group') {
            child.setStyle('opacity', opacity);
        }
    });
}

function fadeInItem(item, opacityPath) {
    var opacity = getItemOpacity(item, opacityPath);
    var el = item.getGraphicEl();

    el.highlight && el.highlight();
    el.traverse(function (child) {
        if (child.type !== 'group') {
            child.setStyle('opacity', opacity);
        }
    });
}

var SankeyShape = graphic.extendShape({
    shape: {
        x1: 0, y1: 0,
        x2: 0, y2: 0,
        cpx1: 0, cpy1: 0,
        cpx2: 0, cpy2: 0,
        extent: 0,
        orient: ''
    },

    buildPath: function (ctx, shape) {
        var extent = shape.extent;
        ctx.moveTo(shape.x1, shape.y1);
        ctx.bezierCurveTo(
            shape.cpx1, shape.cpy1,
            shape.cpx2, shape.cpy2,
            shape.x2, shape.y2
        );
        if (shape.orient === 'vertical') {
            ctx.lineTo(shape.x2 + extent, shape.y2);
            ctx.bezierCurveTo(
                shape.cpx2 + extent, shape.cpy2,
                shape.cpx1 + extent, shape.cpy1,
                shape.x1 + extent, shape.y1
            );
        }
        else {
            ctx.lineTo(shape.x2, shape.y2 + extent);
            ctx.bezierCurveTo(
                shape.cpx2, shape.cpy2 + extent,
                shape.cpx1, shape.cpy1 + extent,
                shape.x1, shape.y1 + extent
            );
        }
        ctx.closePath();
    }
});

export default echarts.extendChartView({

    type: 'sankey',

    /**
     * @private
     * @type {module:echarts/chart/sankey/SankeySeries}
     */
    _model: null,

    /**
     * @private
     * @type {boolean}
     */
    _focusAdjacencyDisabled: false,

    _focusState: false,

    render: function (seriesModel, ecModel, api) {
        var sankeyView = this;
        var graph = seriesModel.getGraph();
        var group = this.group;
        var layoutInfo = seriesModel.layoutInfo;
        // view width
        var width = layoutInfo.width;
        // view height
        var height = layoutInfo.height;
        var nodeData = seriesModel.getData();
        var edgeData = seriesModel.getData('edge');
        var orient = seriesModel.get('orient');

        this._model = seriesModel;

        group.removeAll();

        group.attr('position', [layoutInfo.x, layoutInfo.y]);

        // generate a bezire Curve for each edge
        graph.eachEdge(function (edge) {
            var curve = new SankeyShape();
            curve.dataIndex = edge.dataIndex;
            curve.seriesIndex = seriesModel.seriesIndex;
            curve.dataType = 'edge';
            var lineStyleModel = edge.getModel('lineStyle');
            var curvature = lineStyleModel.get('curveness');
            var n1Layout = edge.node1.getLayout();
            var node1Model = edge.node1.getModel();
            var dragX1 = node1Model.get('localX');
            var dragY1 = node1Model.get('localY');
            var n2Layout = edge.node2.getLayout();
            var node2Model = edge.node2.getModel();
            var dragX2 = node2Model.get('localX');
            var dragY2 = node2Model.get('localY');
            var edgeLayout = edge.getLayout();
            var x1;
            var y1;
            var x2;
            var y2;
            var cpx1;
            var cpy1;
            var cpx2;
            var cpy2;

            curve.shape.extent = Math.max(1, edgeLayout.dy);
            curve.shape.orient = orient;

            if (orient === 'vertical') {
                x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + edgeLayout.sy;
                y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + n1Layout.dy;
                x2 = (dragX2 != null ? dragX2 * width : n2Layout.x) + edgeLayout.ty;
                y2 = dragY2 != null ? dragY2 * height : n2Layout.y;
                cpx1 = x1;
                cpy1 = y1 * (1 - curvature) + y2 * curvature;
                cpx2 = x2;
                cpy2 = y1 * curvature + y2 * (1 - curvature);
            }
            else {
                x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + n1Layout.dx;
                y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + edgeLayout.sy;
                x2 = dragX2 != null ? dragX2 * width : n2Layout.x;
                y2 = (dragY2 != null ? dragY2 * height : n2Layout.y) + edgeLayout.ty;
                cpx1 = x1 * (1 - curvature) + x2 * curvature;
                cpy1 = y1;
                cpx2 = x1 * curvature + x2 * (1 - curvature);
                cpy2 = y2;
            }

            curve.setShape({
                x1: x1,
                y1: y1,
                x2: x2,
                y2: y2,
                cpx1: cpx1,
                cpy1: cpy1,
                cpx2: cpx2,
                cpy2: cpy2
            });

            curve.setStyle(lineStyleModel.getItemStyle());
            // Special color, use source node color or target node color
            switch (curve.style.fill) {
                case 'source':
                    curve.style.fill = edge.node1.getVisual('color');
                    break;
                case 'target':
                    curve.style.fill = edge.node2.getVisual('color');
                    break;
            }

            graphic.setHoverStyle(curve, edge.getModel('emphasis.lineStyle').getItemStyle());

            group.add(curve);

            edgeData.setItemGraphicEl(edge.dataIndex, curve);
        });

        // Generate a rect for each node
        graph.eachNode(function (node) {
            var layout = node.getLayout();
            var itemModel = node.getModel();
            var dragX = itemModel.get('localX');
            var dragY = itemModel.get('localY');
            var labelModel = itemModel.getModel('label');
            var labelHoverModel = itemModel.getModel('emphasis.label');

            var rect = new graphic.Rect({
                shape: {
                    x: dragX != null ? dragX * width : layout.x,
                    y: dragY != null ? dragY * height : layout.y,
                    width: layout.dx,
                    height: layout.dy
                },
                style: itemModel.getModel('itemStyle').getItemStyle()
            });

            var hoverStyle = node.getModel('emphasis.itemStyle').getItemStyle();

            graphic.setLabelStyle(
                rect.style, hoverStyle, labelModel, labelHoverModel,
                {
                    labelFetcher: seriesModel,
                    labelDataIndex: node.dataIndex,
                    defaultText: node.id,
                    isRectText: true
                }
            );

            rect.setStyle('fill', node.getVisual('color'));

            graphic.setHoverStyle(rect, hoverStyle);

            group.add(rect);

            nodeData.setItemGraphicEl(node.dataIndex, rect);

            rect.dataType = 'node';
        });

        nodeData.eachItemGraphicEl(function (el, dataIndex) {
            var itemModel = nodeData.getItemModel(dataIndex);
            if (itemModel.get('draggable')) {
                el.drift = function (dx, dy) {
                    sankeyView._focusAdjacencyDisabled = true;
                    this.shape.x += dx;
                    this.shape.y += dy;
                    this.dirty();
                    api.dispatchAction({
                        type: 'dragNode',
                        seriesId: seriesModel.id,
                        dataIndex: nodeData.getRawIndex(dataIndex),
                        localX: this.shape.x / width,
                        localY: this.shape.y / height
                    });
                };
                el.ondragend = function () {
                    sankeyView._focusAdjacencyDisabled = false;
                };
                el.draggable = true;
                el.cursor = 'move';
            }

            if (itemModel.get('focusNodeAdjacency')) {
                el.off('mouseover').on('mouseover', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        sankeyView._focusState = true;
                        api.dispatchAction({
                            type: 'focusNodeAdjacency',
                            seriesId: seriesModel.id,
                            dataIndex: el.dataIndex
                        });
                    }
                });
                el.off('mouseout').on('mouseout', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        sankeyView._focusState = false;
                        sankeyView._dispatchUnfocus(api, {
                            type: 'unfocusNodeAdjacency',
                            seriesId: seriesModel.id
                        });
                    }
                });
            }
        });

        edgeData.eachItemGraphicEl(function (el, dataIndex) {
            var edgeModel = edgeData.getItemModel(dataIndex);
            if (edgeModel.get('focusNodeAdjacency')) {
                el.off('mouseover').on('mouseover', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        sankeyView._focusState = true;
                        api.dispatchAction({
                            type: 'focusNodeAdjacency',
                            seriesId: seriesModel.id,
                            edgeDataIndex: el.dataIndex
                        });
                    }
                });
                el.off('mouseout').on('mouseout', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        sankeyView._focusState = false;
                        sankeyView._dispatchUnfocus(api, {
                            type: 'unfocusNodeAdjacency',
                            seriesId: seriesModel.id
                        });
                    }
                });
            }
        });

        if (!this._data && seriesModel.get('animation')) {
            group.setClipPath(createGridClipShape(group.getBoundingRect(), seriesModel, function () {
                group.removeClipPath();
            }));
        }

        this._data = seriesModel.getData();

        this._unfocusDelayCache = [];
    },

    dispose: function () {},

    _dispatchUnfocus: function (api, opt) {
        var self = this;
        this._unfocusDelayCache.push(opt);
        if (this._unfocusDelayTimer == null) {
            this._unfocusDelayTimer = setTimeout(function () {
                self._unfocusDelayTimer = null;
                for (var i = 0; i < self._unfocusDelayCache.length; i++) {
                    if (!self._focusState) {
                        api.dispatchAction(self._unfocusDelayCache[i]);
                    }
                }
                self._unfocusDelayCache.length = 0;
            }, 500);
        }
    },

    focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var data = this._model.getData();
        var graph = data.graph;
        var dataIndex = payload.dataIndex;
        var itemModel = data.getItemModel(dataIndex);
        var edgeDataIndex = payload.edgeDataIndex;

        if (dataIndex == null && edgeDataIndex == null) {
            return;
        }
        var node = graph.getNodeByIndex(dataIndex);
        var edge = graph.getEdgeByIndex(edgeDataIndex);

        graph.eachNode(function (node) {
            fadeOutItem(node, nodeOpacityPath, 0.1);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem(edge, lineOpacityPath, 0.1);
        });

        if (node) {
            fadeInItem(node, nodeOpacityPath);
            var focusNodeAdj = itemModel.get('focusNodeAdjacency');
            if (focusNodeAdj === 'outEdges') {
                zrUtil.each(node.outEdges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem(edge, lineOpacityPath);
                    fadeInItem(edge.node2, nodeOpacityPath);
                });
            }
            else if (focusNodeAdj === 'inEdges') {
                zrUtil.each(node.inEdges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem(edge, lineOpacityPath);
                    fadeInItem(edge.node1, nodeOpacityPath);
                });
            }
            else if (focusNodeAdj === 'allEdges') {
                zrUtil.each(node.edges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem(edge, lineOpacityPath);
                    fadeInItem(edge.node1, nodeOpacityPath);
                    fadeInItem(edge.node2, nodeOpacityPath);
                });
            }
        }
        if (edge) {
            fadeInItem(edge, lineOpacityPath);
            fadeInItem(edge.node1, nodeOpacityPath);
            fadeInItem(edge.node2, nodeOpacityPath);
        }
    },

    unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var graph = this._model.getGraph();

        graph.eachNode(function (node) {
            fadeOutItem(node, nodeOpacityPath);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem(edge, lineOpacityPath);
        });
    }
});

// Add animation to the view
function createGridClipShape(rect, seriesModel, cb) {
    var rectEl = new graphic.Rect({
        shape: {
            x: rect.x - 10,
            y: rect.y - 10,
            width: 0,
            height: rect.height + 20
        }
    });
    graphic.initProps(rectEl, {
        shape: {
            width: rect.width + 20,
            height: rect.height + 20
        }
    }, seriesModel, cb);

    return rectEl;
}
<commit_msg>Always clear timer instead of using state when debounce sankey<commit_after>/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import * as graphic from '../../util/graphic';
import * as echarts from '../../echarts';
import * as zrUtil from 'zrender/src/core/util';

var nodeOpacityPath = ['itemStyle', 'opacity'];
var lineOpacityPath = ['lineStyle', 'opacity'];

function getItemOpacity(item, opacityPath) {
    return item.getVisual('opacity') || item.getModel().get(opacityPath);
}

function fadeOutItem(item, opacityPath, opacityRatio) {
    var el = item.getGraphicEl();

    var opacity = getItemOpacity(item, opacityPath);
    if (opacityRatio != null) {
        opacity == null && (opacity = 1);
        opacity *= opacityRatio;
    }

    el.downplay && el.downplay();
    el.traverse(function (child) {
        if (child.type !== 'group') {
            child.setStyle('opacity', opacity);
        }
    });
}

function fadeInItem(item, opacityPath) {
    var opacity = getItemOpacity(item, opacityPath);
    var el = item.getGraphicEl();

    el.highlight && el.highlight();
    el.traverse(function (child) {
        if (child.type !== 'group') {
            child.setStyle('opacity', opacity);
        }
    });
}

var SankeyShape = graphic.extendShape({
    shape: {
        x1: 0, y1: 0,
        x2: 0, y2: 0,
        cpx1: 0, cpy1: 0,
        cpx2: 0, cpy2: 0,
        extent: 0,
        orient: ''
    },

    buildPath: function (ctx, shape) {
        var extent = shape.extent;
        ctx.moveTo(shape.x1, shape.y1);
        ctx.bezierCurveTo(
            shape.cpx1, shape.cpy1,
            shape.cpx2, shape.cpy2,
            shape.x2, shape.y2
        );
        if (shape.orient === 'vertical') {
            ctx.lineTo(shape.x2 + extent, shape.y2);
            ctx.bezierCurveTo(
                shape.cpx2 + extent, shape.cpy2,
                shape.cpx1 + extent, shape.cpy1,
                shape.x1 + extent, shape.y1
            );
        }
        else {
            ctx.lineTo(shape.x2, shape.y2 + extent);
            ctx.bezierCurveTo(
                shape.cpx2, shape.cpy2 + extent,
                shape.cpx1, shape.cpy1 + extent,
                shape.x1, shape.y1 + extent
            );
        }
        ctx.closePath();
    }
});

export default echarts.extendChartView({

    type: 'sankey',

    /**
     * @private
     * @type {module:echarts/chart/sankey/SankeySeries}
     */
    _model: null,

    /**
     * @private
     * @type {boolean}
     */
    _focusAdjacencyDisabled: false,

    render: function (seriesModel, ecModel, api) {
        var sankeyView = this;
        var graph = seriesModel.getGraph();
        var group = this.group;
        var layoutInfo = seriesModel.layoutInfo;
        // view width
        var width = layoutInfo.width;
        // view height
        var height = layoutInfo.height;
        var nodeData = seriesModel.getData();
        var edgeData = seriesModel.getData('edge');
        var orient = seriesModel.get('orient');

        this._model = seriesModel;

        group.removeAll();

        group.attr('position', [layoutInfo.x, layoutInfo.y]);

        // generate a bezire Curve for each edge
        graph.eachEdge(function (edge) {
            var curve = new SankeyShape();
            curve.dataIndex = edge.dataIndex;
            curve.seriesIndex = seriesModel.seriesIndex;
            curve.dataType = 'edge';
            var lineStyleModel = edge.getModel('lineStyle');
            var curvature = lineStyleModel.get('curveness');
            var n1Layout = edge.node1.getLayout();
            var node1Model = edge.node1.getModel();
            var dragX1 = node1Model.get('localX');
            var dragY1 = node1Model.get('localY');
            var n2Layout = edge.node2.getLayout();
            var node2Model = edge.node2.getModel();
            var dragX2 = node2Model.get('localX');
            var dragY2 = node2Model.get('localY');
            var edgeLayout = edge.getLayout();
            var x1;
            var y1;
            var x2;
            var y2;
            var cpx1;
            var cpy1;
            var cpx2;
            var cpy2;

            curve.shape.extent = Math.max(1, edgeLayout.dy);
            curve.shape.orient = orient;

            if (orient === 'vertical') {
                x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + edgeLayout.sy;
                y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + n1Layout.dy;
                x2 = (dragX2 != null ? dragX2 * width : n2Layout.x) + edgeLayout.ty;
                y2 = dragY2 != null ? dragY2 * height : n2Layout.y;
                cpx1 = x1;
                cpy1 = y1 * (1 - curvature) + y2 * curvature;
                cpx2 = x2;
                cpy2 = y1 * curvature + y2 * (1 - curvature);
            }
            else {
                x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + n1Layout.dx;
                y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + edgeLayout.sy;
                x2 = dragX2 != null ? dragX2 * width : n2Layout.x;
                y2 = (dragY2 != null ? dragY2 * height : n2Layout.y) + edgeLayout.ty;
                cpx1 = x1 * (1 - curvature) + x2 * curvature;
                cpy1 = y1;
                cpx2 = x1 * curvature + x2 * (1 - curvature);
                cpy2 = y2;
            }

            curve.setShape({
                x1: x1,
                y1: y1,
                x2: x2,
                y2: y2,
                cpx1: cpx1,
                cpy1: cpy1,
                cpx2: cpx2,
                cpy2: cpy2
            });

            curve.setStyle(lineStyleModel.getItemStyle());
            // Special color, use source node color or target node color
            switch (curve.style.fill) {
                case 'source':
                    curve.style.fill = edge.node1.getVisual('color');
                    break;
                case 'target':
                    curve.style.fill = edge.node2.getVisual('color');
                    break;
            }

            graphic.setHoverStyle(curve, edge.getModel('emphasis.lineStyle').getItemStyle());

            group.add(curve);

            edgeData.setItemGraphicEl(edge.dataIndex, curve);
        });

        // Generate a rect for each node
        graph.eachNode(function (node) {
            var layout = node.getLayout();
            var itemModel = node.getModel();
            var dragX = itemModel.get('localX');
            var dragY = itemModel.get('localY');
            var labelModel = itemModel.getModel('label');
            var labelHoverModel = itemModel.getModel('emphasis.label');

            var rect = new graphic.Rect({
                shape: {
                    x: dragX != null ? dragX * width : layout.x,
                    y: dragY != null ? dragY * height : layout.y,
                    width: layout.dx,
                    height: layout.dy
                },
                style: itemModel.getModel('itemStyle').getItemStyle()
            });

            var hoverStyle = node.getModel('emphasis.itemStyle').getItemStyle();

            graphic.setLabelStyle(
                rect.style, hoverStyle, labelModel, labelHoverModel,
                {
                    labelFetcher: seriesModel,
                    labelDataIndex: node.dataIndex,
                    defaultText: node.id,
                    isRectText: true
                }
            );

            rect.setStyle('fill', node.getVisual('color'));

            graphic.setHoverStyle(rect, hoverStyle);

            group.add(rect);

            nodeData.setItemGraphicEl(node.dataIndex, rect);

            rect.dataType = 'node';
        });

        nodeData.eachItemGraphicEl(function (el, dataIndex) {
            var itemModel = nodeData.getItemModel(dataIndex);
            if (itemModel.get('draggable')) {
                el.drift = function (dx, dy) {
                    sankeyView._focusAdjacencyDisabled = true;
                    this.shape.x += dx;
                    this.shape.y += dy;
                    this.dirty();
                    api.dispatchAction({
                        type: 'dragNode',
                        seriesId: seriesModel.id,
                        dataIndex: nodeData.getRawIndex(dataIndex),
                        localX: this.shape.x / width,
                        localY: this.shape.y / height
                    });
                };
                el.ondragend = function () {
                    sankeyView._focusAdjacencyDisabled = false;
                };
                el.draggable = true;
                el.cursor = 'move';
            }

            if (itemModel.get('focusNodeAdjacency')) {
                el.off('mouseover').on('mouseover', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        clearTimeout(this._unfocusDelayTimer);
                        api.dispatchAction({
                            type: 'focusNodeAdjacency',
                            seriesId: seriesModel.id,
                            dataIndex: el.dataIndex
                        });
                    }
                });
                el.off('mouseout').on('mouseout', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        sankeyView._dispatchUnfocus(api);
                    }
                });
            }
        });

        edgeData.eachItemGraphicEl(function (el, dataIndex) {
            var edgeModel = edgeData.getItemModel(dataIndex);
            if (edgeModel.get('focusNodeAdjacency')) {
                el.off('mouseover').on('mouseover', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        clearTimeout(this._unfocusDelayTimer);
                        api.dispatchAction({
                            type: 'focusNodeAdjacency',
                            seriesId: seriesModel.id,
                            edgeDataIndex: el.dataIndex
                        });
                    }
                });
                el.off('mouseout').on('mouseout', function () {
                    if (!sankeyView._focusAdjacencyDisabled) {
                        sankeyView._dispatchUnfocus(api);
                    }
                });
            }
        });

        if (!this._data && seriesModel.get('animation')) {
            group.setClipPath(createGridClipShape(group.getBoundingRect(), seriesModel, function () {
                group.removeClipPath();
            }));
        }

        this._data = seriesModel.getData();
    },

    dispose: function () {
        if (this._unfocusDelayTimer) {
            clearTimeout(this._unfocusDelayTimer);
        }
    },

    _dispatchUnfocus: function (api) {
        var self = this;
        if (this._unfocusDelayTimer) {
            clearTimeout(this._unfocusDelayTimer);
        }
        this._unfocusDelayTimer = setTimeout(function () {
            self._unfocusDelayTimer = null;
            api.dispatchAction({
                type: 'unfocusNodeAdjacency',
                seriesId: self._model.id
            });
        }, 500);
    },

    focusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var data = this._model.getData();
        var graph = data.graph;
        var dataIndex = payload.dataIndex;
        var itemModel = data.getItemModel(dataIndex);
        var edgeDataIndex = payload.edgeDataIndex;

        if (dataIndex == null && edgeDataIndex == null) {
            return;
        }
        var node = graph.getNodeByIndex(dataIndex);
        var edge = graph.getEdgeByIndex(edgeDataIndex);

        graph.eachNode(function (node) {
            fadeOutItem(node, nodeOpacityPath, 0.1);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem(edge, lineOpacityPath, 0.1);
        });

        if (node) {
            fadeInItem(node, nodeOpacityPath);
            var focusNodeAdj = itemModel.get('focusNodeAdjacency');
            if (focusNodeAdj === 'outEdges') {
                zrUtil.each(node.outEdges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem(edge, lineOpacityPath);
                    fadeInItem(edge.node2, nodeOpacityPath);
                });
            }
            else if (focusNodeAdj === 'inEdges') {
                zrUtil.each(node.inEdges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem(edge, lineOpacityPath);
                    fadeInItem(edge.node1, nodeOpacityPath);
                });
            }
            else if (focusNodeAdj === 'allEdges') {
                zrUtil.each(node.edges, function (edge) {
                    if (edge.dataIndex < 0) {
                        return;
                    }
                    fadeInItem(edge, lineOpacityPath);
                    fadeInItem(edge.node1, nodeOpacityPath);
                    fadeInItem(edge.node2, nodeOpacityPath);
                });
            }
        }
        if (edge) {
            fadeInItem(edge, lineOpacityPath);
            fadeInItem(edge.node1, nodeOpacityPath);
            fadeInItem(edge.node2, nodeOpacityPath);
        }
    },

    unfocusNodeAdjacency: function (seriesModel, ecModel, api, payload) {
        var graph = this._model.getGraph();

        graph.eachNode(function (node) {
            fadeOutItem(node, nodeOpacityPath);
        });
        graph.eachEdge(function (edge) {
            fadeOutItem(edge, lineOpacityPath);
        });
    }
});

// Add animation to the view
function createGridClipShape(rect, seriesModel, cb) {
    var rectEl = new graphic.Rect({
        shape: {
            x: rect.x - 10,
            y: rect.y - 10,
            width: 0,
            height: rect.height + 20
        }
    });
    graphic.initProps(rectEl, {
        shape: {
            width: rect.width + 20,
            height: rect.height + 20
        }
    }, seriesModel, cb);

    return rectEl;
}
<|endoftext|>


<commit_before>import React from 'react';
// import { Link } from 'react-router';

import wedding from '../../../../../config/wedding.js';
import glob from 'styles/app';
import local from './_styles';

/**
  *
  * The footer for visitor layout
  *
  * @param  none
  *
  * @return {ReactComponent}
  */

const numberOfDaysUntil = () => {
  const oneDay = 24 * 60 * 60 * 1000;
  const weddingDate = new Date(wedding.date);
  const today = new Date();
  return Math.round(Math.abs((today.getTime() - weddingDate.getTime()) / (oneDay)));
};

const today = new Date();
const bigDay = new Date(wedding.date);

let countdown = '';
// Todo: past day
if (today.toDateString() === bigDay.toDateString()) {
  countdown = 'TODAY IS THE DAY!';
} else {
  countdown = `${numberOfDaysUntil()}  Days until the wedding!`;
}

export default () => (
  <div className={`${local.footer} ${glob.verticalContainer}`}>
    <h3 className={`${glob.verticallyAligned}`}> {countdown}

);
<commit_msg>Countdown<commit_after>import React from 'react';
// import { Link } from 'react-router';

import wedding from '../../../../../config/wedding.js';
import glob from 'styles/app';
import local from './_styles';

/**
  *
  * The footer for visitor layout
  *
  * @param  none
  *
  * @return {ReactComponent}
  */

const numberOfDaysUntil = () => {
  const oneDay = 24 * 60 * 60 * 1000;
  const weddingDate = new Date(wedding.date);
  const today = new Date();
  return Math.round(Math.abs((today.getTime() - weddingDate.getTime()) / (oneDay)));
};

const today = new Date();
const bigDay = new Date(wedding.date);

let countdown = '';
// Todo: past day
if (today.toDateString() === bigDay.toDateString()) {
  countdown = 'TODAY IS THE DAY!';
} else {
  countdown = `Just ${numberOfDaysUntil()} More Days!`;
}

export default () => (
  <div className={`${local.footer} ${glob.verticalContainer}`}>
    <h3 className={`${glob.verticallyAligned}`}>{countdown}

);
<|endoftext|>


<commit_before>view = Backbone.View.extend();

view.prototype.events = {
    'click a.delete': 'exportDelete'
};

view.prototype.initialize = function(options) {
    Bones.intervals = Bones.intervals || {};
    Bones.intervals.exports = Bones.intervals.exports ||
        setInterval(_(this.collection.fetch).bind(this.collection), 5000);

    _(this).bindAll('render', 'exportDelete');
    this.collection.bind('all', this.render);
    this.render();
};

view.prototype.render = function() {
    this.$('.content').html(templates.Exports(this.collection));
    return this;
};

view.prototype.exportDelete = function(ev) {
    var id = $(ev.currentTarget).attr('href').split('#').pop();
    var model = this.collection.get(id);
    new views.Modal({
        content: 'Are you sure you want to delete "'+ model.get('filename') +'"?',
        callback: function() {
            model.destroy({ error: function(m, e) { new views.Modal(e) }});
        }
    });
    return false;
};
<commit_msg>Stop polling if drawer has be replaced with other content.<commit_after>view = Backbone.View.extend();

view.prototype.events = {
    'click a.delete': 'exportDelete'
};

view.prototype.initialize = function(options) {
    Bones.intervals = Bones.intervals || {};
    Bones.intervals.exports = Bones.intervals.exports ||
        setInterval(_(this.collection.fetch).bind(this.collection), 5000);

    _(this).bindAll('render', 'exportDelete', 'stop');
    this.collection.bind('all', this.render, this.stop);
    this.collection.bind('all', this.stop);
    this.render(true);
};

view.prototype.render = function(force) {
    if (force === true || this.$('ul.exports').size()) {
        this.$('.content').html(templates.Exports(this.collection));
    }
    return this;
};

view.prototype.exportDelete = function(ev) {
    var id = $(ev.currentTarget).attr('href').split('#').pop();
    var model = this.collection.get(id);
    new views.Modal({
        content: 'Are you sure you want to delete "'+ model.get('filename') +'"?',
        callback: function() {
            model.destroy({ error: function(m, e) { new views.Modal(e) }});
        }
    });
    return false;
};

view.prototype.stop = function(ev) {
    // Stop polling if drawer has be replaced with other content.
    if (!this.$('.content ul.exports').size()) {
        clearInterval(Bones.intervals.exports);
        Bones.intervals.exports = null;
    }
}
<|endoftext|>


<commit_before>// Wait https://github.com/facebook/flow/issues/380 to be fixed
/* eslint-disable flowtype/require-valid-file-annotation */

export const black = '#000000';
export const white = '#ffffff';

export const transparent = 'rgba(0, 0, 0, 0)';
export const fullBlack = 'rgba(0, 0, 0, 1)';
export const darkBlack = 'rgba(0, 0, 0, 0.87)';
export const lightBlack = 'rgba(0, 0, 0, 0.54)';
export const minBlack = 'rgba(0, 0, 0, 0.26)';
export const faintBlack = 'rgba(0, 0, 0, 0.12)';
export const fullWhite = 'rgba(255, 255, 255, 1)';
export const darkWhite = 'rgba(255, 255, 255, 0.87)';
export const lightWhite = 'rgba(255, 255, 255, 0.54)';

export const red = {
  50: '#ffebee',
  100: '#ffcdd2',
  200: '#ef9a9a',
  300: '#e57373',
  400: '#ef5350',
  500: '#f44336',
  600: '#e53935',
  700: '#d32f2f',
  800: '#c62828',
  900: '#b71c1c',
  A100: '#ff8a80',
  A200: '#ff5252',
  A400: '#ff1744',
  A700: '#d50000',
  contrastDefaultColor: 'light',
};

export const pink = {
  50: '#fce4ec',
  100: '#f8bbd0',
  200: '#f48fb1',
  300: '#f06292',
  400: '#ec407a',
  500: '#e91e63',
  600: '#d81b60',
  700: '#c2185b',
  800: '#ad1457',
  900: '#880e4f',
  A100: '#ff80ab',
  A200: '#ff4081',
  A400: '#f50057',
  A700: '#c51162',
  contrastDefaultColor: 'light',
};

export const purple = {
  50: '#f3e5f5',
  100: '#e1bee7',
  200: '#ce93d8',
  300: '#ba68c8',
  400: '#ab47bc',
  500: '#9c27b0',
  600: '#8e24aa',
  700: '#7b1fa2',
  800: '#6a1b9a',
  900: '#4a148c',
  A100: '#ea80fc',
  A200: '#e040fb',
  A400: '#d500f9',
  A700: '#aa00ff',
  contrastDefaultColor: 'light',
};

export const deepPurple = {
  50: '#ede7f6',
  100: '#d1c4e9',
  200: '#b39ddb',
  300: '#9575cd',
  400: '#7e57c2',
  500: '#673ab7',
  600: '#5e35b1',
  700: '#512da8',
  800: '#4527a0',
  900: '#311b92',
  A100: '#b388ff',
  A200: '#7c4dff',
  A400: '#651fff',
  A700: '#6200ea',
  contrastDefaultColor: 'light',
};

export const indigo = {
  50: '#e8eaf6',
  100: '#c5cae9',
  200: '#9fa8da',
  300: '#7986cb',
  400: '#5c6bc0',
  500: '#3f51b5',
  600: '#3949ab',
  700: '#303f9f',
  800: '#283593',
  900: '#1a237e',
  A100: '#8c9eff',
  A200: '#536dfe',
  A400: '#3d5afe',
  A700: '#304ffe',
  contrastDefaultColor: 'light',
};

export const blue = {
  50: '#e3f2fd',
  100: '#bbdefb',
  200: '#90caf9',
  300: '#64b5f6',
  400: '#42a5f5',
  500: '#2196f3',
  600: '#1e88e5',
  700: '#1976d2',
  800: '#1565c0',
  900: '#0d47a1',
  A100: '#82b1ff',
  A200: '#448aff',
  A400: '#2979ff',
  A700: '#2962ff',
  contrastDefaultColor: 'light',
};

export const lightBlue = {
  50: '#e1f5fe',
  100: '#b3e5fc',
  200: '#81d4fa',
  300: '#4fc3f7',
  400: '#29b6f6',
  500: '#03a9f4',
  600: '#039be5',
  700: '#0288d1',
  800: '#0277bd',
  900: '#01579b',
  A100: '#80d8ff',
  A200: '#40c4ff',
  A400: '#00b0ff',
  A700: '#0091ea',
  contrastDefaultColor: 'dark',
};

export const cyan = {
  50: '#e0f7fa',
  100: '#b2ebf2',
  200: '#80deea',
  300: '#4dd0e1',
  400: '#26c6da',
  500: '#00bcd4',
  600: '#00acc1',
  700: '#0097a7',
  800: '#00838f',
  900: '#006064',
  A100: '#84ffff',
  A200: '#18ffff',
  A400: '#00e5ff',
  A700: '#00b8d4',
  contrastDefaultColor: 'dark',
};

export const teal = {
  50: '#e0f2f1',
  100: '#b2dfdb',
  200: '#80cbc4',
  300: '#4db6ac',
  400: '#26a69a',
  500: '#009688',
  600: '#00897b',
  700: '#00796b',
  800: '#00695c',
  900: '#004d40',
  A100: '#a7ffeb',
  A200: '#64ffda',
  A400: '#1de9b6',
  A700: '#00bfa5',
  contrastDefaultColor: 'dark',
};

export const green = {
  50: '#e8f5e9',
  100: '#c8e6c9',
  200: '#a5d6a7',
  300: '#81c784',
  400: '#66bb6a',
  500: '#4caf50',
  600: '#43a047',
  700: '#388e3c',
  800: '#2e7d32',
  900: '#1b5e20',
  A100: '#b9f6ca',
  A200: '#69f0ae',
  A400: '#00e676',
  A700: '#00c853',
  contrastDefaultColor: 'dark',
};

export const lightGreen = {
  50: '#f1f8e9',
  100: '#dcedc8',
  200: '#c5e1a5',
  300: '#aed581',
  400: '#9ccc65',
  500: '#8bc34a',
  600: '#7cb342',
  700: '#689f38',
  800: '#558b2f',
  900: '#33691e',
  A100: '#ccff90',
  A200: '#b2ff59',
  A400: '#76ff03',
  A700: '#64dd17',
  contrastDefaultColor: 'dark',
};

export const lime = {
  50: '#f9fbe7',
  100: '#f0f4c3',
  200: '#e6ee9c',
  300: '#dce775',
  400: '#d4e157',
  500: '#cddc39',
  600: '#c0ca33',
  700: '#afb42b',
  800: '#9e9d24',
  900: '#827717',
  A100: '#f4ff81',
  A200: '#eeff41',
  A400: '#c6ff00',
  A700: '#aeea00',
  contrastDefaultColor: 'dark',
};

export const yellow = {
  50: '#fffde7',
  100: '#fff9c4',
  200: '#fff59d',
  300: '#fff176',
  400: '#ffee58',
  500: '#ffeb3b',
  600: '#fdd835',
  700: '#fbc02d',
  800: '#f9a825',
  900: '#f57f17',
  A100: '#ffff8d',
  A200: '#ffff00',
  A400: '#ffea00',
  A700: '#ffd600',
  contrastDefaultColor: 'dark',
};

export const amber = {
  50: '#fff8e1',
  100: '#ffecb3',
  200: '#ffe082',
  300: '#ffd54f',
  400: '#ffca28',
  500: '#ffc107',
  600: '#ffb300',
  700: '#ffa000',
  800: '#ff8f00',
  900: '#ff6f00',
  A100: '#ffe57f',
  A200: '#ffd740',
  A400: '#ffc400',
  A700: '#ffab00',
  contrastDefaultColor: 'dark',
};

export const orange = {
  50: '#fff3e0',
  100: '#ffe0b2',
  200: '#ffcc80',
  300: '#ffb74d',
  400: '#ffa726',
  500: '#ff9800',
  600: '#fb8c00',
  700: '#f57c00',
  800: '#ef6c00',
  900: '#e65100',
  A100: '#ffd180',
  A200: '#ffab40',
  A400: '#ff9100',
  A700: '#ff6d00',
  contrastDefaultColor: 'dark',
};

export const deepOrange = {
  50: '#fbe9e7',
  100: '#ffccbc',
  200: '#ffab91',
  300: '#ff8a65',
  400: '#ff7043',
  500: '#ff5722',
  600: '#f4511e',
  700: '#e64a19',
  800: '#d84315',
  900: '#bf360c',
  A100: '#ff9e80',
  A200: '#ff6e40',
  A400: '#ff3d00',
  A700: '#dd2c00',
  contrastDefaultColor: 'light',
};

export const brown = {
  50: '#efebe9',
  100: '#d7ccc8',
  200: '#bcaaa4',
  300: '#a1887f',
  400: '#8d6e63',
  500: '#795548',
  600: '#6d4c41',
  700: '#5d4037',
  800: '#4e342e',
  900: '#3e2723',
  A100: '#d7ccc8',
  A200: '#bcaaa4',
  A400: '#8d6e63',
  A700: '#5d4037',
  contrastDefaultColor: 'brown',
};

export const grey = {
  50: '#fafafa',
  100: '#f5f5f5',
  200: '#eeeeee',
  300: '#e0e0e0',
  400: '#bdbdbd',
  500: '#9e9e9e',
  600: '#757575',
  700: '#616161',
  800: '#424242',
  900: '#212121',
  A100: '#d5d5d5',
  A200: '#aaaaaa',
  A400: '#303030',
  A700: '#616161',
  contrastDefaultColor: 'dark',
};

export const blueGrey = {
  50: '#eceff1',
  100: '#cfd8dc',
  200: '#b0bec5',
  300: '#90a4ae',
  400: '#78909c',
  500: '#607d8b',
  600: '#546e7a',
  700: '#455a64',
  800: '#37474f',
  900: '#263238',
};
<commit_msg>adds accent colors + a default contrast color to blueGrey (#6548)<commit_after>// Wait https://github.com/facebook/flow/issues/380 to be fixed
/* eslint-disable flowtype/require-valid-file-annotation */

export const black = '#000000';
export const white = '#ffffff';

export const transparent = 'rgba(0, 0, 0, 0)';
export const fullBlack = 'rgba(0, 0, 0, 1)';
export const darkBlack = 'rgba(0, 0, 0, 0.87)';
export const lightBlack = 'rgba(0, 0, 0, 0.54)';
export const minBlack = 'rgba(0, 0, 0, 0.26)';
export const faintBlack = 'rgba(0, 0, 0, 0.12)';
export const fullWhite = 'rgba(255, 255, 255, 1)';
export const darkWhite = 'rgba(255, 255, 255, 0.87)';
export const lightWhite = 'rgba(255, 255, 255, 0.54)';

export const red = {
  50: '#ffebee',
  100: '#ffcdd2',
  200: '#ef9a9a',
  300: '#e57373',
  400: '#ef5350',
  500: '#f44336',
  600: '#e53935',
  700: '#d32f2f',
  800: '#c62828',
  900: '#b71c1c',
  A100: '#ff8a80',
  A200: '#ff5252',
  A400: '#ff1744',
  A700: '#d50000',
  contrastDefaultColor: 'light',
};

export const pink = {
  50: '#fce4ec',
  100: '#f8bbd0',
  200: '#f48fb1',
  300: '#f06292',
  400: '#ec407a',
  500: '#e91e63',
  600: '#d81b60',
  700: '#c2185b',
  800: '#ad1457',
  900: '#880e4f',
  A100: '#ff80ab',
  A200: '#ff4081',
  A400: '#f50057',
  A700: '#c51162',
  contrastDefaultColor: 'light',
};

export const purple = {
  50: '#f3e5f5',
  100: '#e1bee7',
  200: '#ce93d8',
  300: '#ba68c8',
  400: '#ab47bc',
  500: '#9c27b0',
  600: '#8e24aa',
  700: '#7b1fa2',
  800: '#6a1b9a',
  900: '#4a148c',
  A100: '#ea80fc',
  A200: '#e040fb',
  A400: '#d500f9',
  A700: '#aa00ff',
  contrastDefaultColor: 'light',
};

export const deepPurple = {
  50: '#ede7f6',
  100: '#d1c4e9',
  200: '#b39ddb',
  300: '#9575cd',
  400: '#7e57c2',
  500: '#673ab7',
  600: '#5e35b1',
  700: '#512da8',
  800: '#4527a0',
  900: '#311b92',
  A100: '#b388ff',
  A200: '#7c4dff',
  A400: '#651fff',
  A700: '#6200ea',
  contrastDefaultColor: 'light',
};

export const indigo = {
  50: '#e8eaf6',
  100: '#c5cae9',
  200: '#9fa8da',
  300: '#7986cb',
  400: '#5c6bc0',
  500: '#3f51b5',
  600: '#3949ab',
  700: '#303f9f',
  800: '#283593',
  900: '#1a237e',
  A100: '#8c9eff',
  A200: '#536dfe',
  A400: '#3d5afe',
  A700: '#304ffe',
  contrastDefaultColor: 'light',
};

export const blue = {
  50: '#e3f2fd',
  100: '#bbdefb',
  200: '#90caf9',
  300: '#64b5f6',
  400: '#42a5f5',
  500: '#2196f3',
  600: '#1e88e5',
  700: '#1976d2',
  800: '#1565c0',
  900: '#0d47a1',
  A100: '#82b1ff',
  A200: '#448aff',
  A400: '#2979ff',
  A700: '#2962ff',
  contrastDefaultColor: 'light',
};

export const lightBlue = {
  50: '#e1f5fe',
  100: '#b3e5fc',
  200: '#81d4fa',
  300: '#4fc3f7',
  400: '#29b6f6',
  500: '#03a9f4',
  600: '#039be5',
  700: '#0288d1',
  800: '#0277bd',
  900: '#01579b',
  A100: '#80d8ff',
  A200: '#40c4ff',
  A400: '#00b0ff',
  A700: '#0091ea',
  contrastDefaultColor: 'dark',
};

export const cyan = {
  50: '#e0f7fa',
  100: '#b2ebf2',
  200: '#80deea',
  300: '#4dd0e1',
  400: '#26c6da',
  500: '#00bcd4',
  600: '#00acc1',
  700: '#0097a7',
  800: '#00838f',
  900: '#006064',
  A100: '#84ffff',
  A200: '#18ffff',
  A400: '#00e5ff',
  A700: '#00b8d4',
  contrastDefaultColor: 'dark',
};

export const teal = {
  50: '#e0f2f1',
  100: '#b2dfdb',
  200: '#80cbc4',
  300: '#4db6ac',
  400: '#26a69a',
  500: '#009688',
  600: '#00897b',
  700: '#00796b',
  800: '#00695c',
  900: '#004d40',
  A100: '#a7ffeb',
  A200: '#64ffda',
  A400: '#1de9b6',
  A700: '#00bfa5',
  contrastDefaultColor: 'dark',
};

export const green = {
  50: '#e8f5e9',
  100: '#c8e6c9',
  200: '#a5d6a7',
  300: '#81c784',
  400: '#66bb6a',
  500: '#4caf50',
  600: '#43a047',
  700: '#388e3c',
  800: '#2e7d32',
  900: '#1b5e20',
  A100: '#b9f6ca',
  A200: '#69f0ae',
  A400: '#00e676',
  A700: '#00c853',
  contrastDefaultColor: 'dark',
};

export const lightGreen = {
  50: '#f1f8e9',
  100: '#dcedc8',
  200: '#c5e1a5',
  300: '#aed581',
  400: '#9ccc65',
  500: '#8bc34a',
  600: '#7cb342',
  700: '#689f38',
  800: '#558b2f',
  900: '#33691e',
  A100: '#ccff90',
  A200: '#b2ff59',
  A400: '#76ff03',
  A700: '#64dd17',
  contrastDefaultColor: 'dark',
};

export const lime = {
  50: '#f9fbe7',
  100: '#f0f4c3',
  200: '#e6ee9c',
  300: '#dce775',
  400: '#d4e157',
  500: '#cddc39',
  600: '#c0ca33',
  700: '#afb42b',
  800: '#9e9d24',
  900: '#827717',
  A100: '#f4ff81',
  A200: '#eeff41',
  A400: '#c6ff00',
  A700: '#aeea00',
  contrastDefaultColor: 'dark',
};

export const yellow = {
  50: '#fffde7',
  100: '#fff9c4',
  200: '#fff59d',
  300: '#fff176',
  400: '#ffee58',
  500: '#ffeb3b',
  600: '#fdd835',
  700: '#fbc02d',
  800: '#f9a825',
  900: '#f57f17',
  A100: '#ffff8d',
  A200: '#ffff00',
  A400: '#ffea00',
  A700: '#ffd600',
  contrastDefaultColor: 'dark',
};

export const amber = {
  50: '#fff8e1',
  100: '#ffecb3',
  200: '#ffe082',
  300: '#ffd54f',
  400: '#ffca28',
  500: '#ffc107',
  600: '#ffb300',
  700: '#ffa000',
  800: '#ff8f00',
  900: '#ff6f00',
  A100: '#ffe57f',
  A200: '#ffd740',
  A400: '#ffc400',
  A700: '#ffab00',
  contrastDefaultColor: 'dark',
};

export const orange = {
  50: '#fff3e0',
  100: '#ffe0b2',
  200: '#ffcc80',
  300: '#ffb74d',
  400: '#ffa726',
  500: '#ff9800',
  600: '#fb8c00',
  700: '#f57c00',
  800: '#ef6c00',
  900: '#e65100',
  A100: '#ffd180',
  A200: '#ffab40',
  A400: '#ff9100',
  A700: '#ff6d00',
  contrastDefaultColor: 'dark',
};

export const deepOrange = {
  50: '#fbe9e7',
  100: '#ffccbc',
  200: '#ffab91',
  300: '#ff8a65',
  400: '#ff7043',
  500: '#ff5722',
  600: '#f4511e',
  700: '#e64a19',
  800: '#d84315',
  900: '#bf360c',
  A100: '#ff9e80',
  A200: '#ff6e40',
  A400: '#ff3d00',
  A700: '#dd2c00',
  contrastDefaultColor: 'light',
};

export const brown = {
  50: '#efebe9',
  100: '#d7ccc8',
  200: '#bcaaa4',
  300: '#a1887f',
  400: '#8d6e63',
  500: '#795548',
  600: '#6d4c41',
  700: '#5d4037',
  800: '#4e342e',
  900: '#3e2723',
  A100: '#d7ccc8',
  A200: '#bcaaa4',
  A400: '#8d6e63',
  A700: '#5d4037',
  contrastDefaultColor: 'brown',
};

export const grey = {
  50: '#fafafa',
  100: '#f5f5f5',
  200: '#eeeeee',
  300: '#e0e0e0',
  400: '#bdbdbd',
  500: '#9e9e9e',
  600: '#757575',
  700: '#616161',
  800: '#424242',
  900: '#212121',
  A100: '#d5d5d5',
  A200: '#aaaaaa',
  A400: '#303030',
  A700: '#616161',
  contrastDefaultColor: 'dark',
};

export const blueGrey = {
  50: '#eceff1',
  100: '#cfd8dc',
  200: '#b0bec5',
  300: '#90a4ae',
  400: '#78909c',
  500: '#607d8b',
  600: '#546e7a',
  700: '#455a64',
  800: '#37474f',
  900: '#263238',
  A100: '#cfd8dc',
  A200: '#b0bec5',
  A400: '#78909c',
  A700: '#455a64',
  contrastDefaultColor: 'light',
};
<|endoftext|>


<commit_before>"use strict";

var detector = module.exports = {};

detector.isIE = function(version) {
    function isAnyIeVersion() {
        var agent = navigator.userAgent.toLowerCase();
        return agent.indexOf("msie") !== -1 || agent.indexOf("trident") !== -1;
    }

    if(!isAnyIeVersion()) {
        return false;
    }

    if(!version) {
        return true;
    }

    //Shamelessly stolen from https://gist.github.com/padolsey/527683
    var ieVersion = (function(){
        var undef,
            v = 3,
            div = document.createElement("div"),
            all = div.getElementsByTagName("i");

        do {
            div.innerHTML = "";
        }
        while (all[0]);

        return v > 4 ? v : undef;
    }());

    return version === ieVersion;
};
<commit_msg>Removed whitespaces<commit_after>"use strict";

var detector = module.exports = {};

detector.isIE = function(version) {
    function isAnyIeVersion() {
        var agent = navigator.userAgent.toLowerCase();
        return agent.indexOf("msie") !== -1 || agent.indexOf("trident") !== -1;
    }

    if(!isAnyIeVersion()) {
        return false;
    }

    if(!version) {
        return true;
    }

    //Shamelessly stolen from https://gist.github.com/padolsey/527683
    var ieVersion = (function(){
        var undef,
            v = 3,
            div = document.createElement("div"),
            all = div.getElementsByTagName("i");

        do {
            div.innerHTML = "";
        }
        while (all[0]);

        return v > 4 ? v : undef;
    }());

    return version === ieVersion;
};
<|endoftext|>


<commit_before>const blessed = require('blessed');

const {SculptureStore} = require('@anyware/game-logic');

const VIEW_TITLE = "{center}{bold}Panels{/bold}{/center}";
const CELL_WIDTH = 3;

export default class PanelView extends blessed.Box {
  constructor(store, windowOptions) {
    super(Object.assign({
      tags: true,
      border: {
        type: 'line'
      },
      style: {
        fg: 'white',
        bg: 'gray'
      }
    }, windowOptions));

    this.store = store;
    this.renderPanels();

    this.store.on(SculptureStore.EVENT_CHANGE, this.renderPanels.bind(this));
  }

  renderPanels() {
    const lightArray = this.store.data.get('lights');

    let content = VIEW_TITLE + '\n';
    content += this.formatPanelIDs(lightArray) + '\n';

    const formattedStrips = Array.from(this.formatStrips(lightArray));
    content += formattedStrips.join('\n');

    this.setContent(content);
  }

  formatPanelIDs(lightArray) {
    let longestPanelIdList = null;
    for (let stripId of lightArray.stripIds) {
      const panelIds = lightArray.get(stripId).panelIds;
      if (!longestPanelIdList || panelIds.length > longestPanelIdList.length) {
        longestPanelIdList = panelIds;
      }
    }

    let result = '{yellow-fg}ID';
    for (let panelId of longestPanelIdList) {
      result += ' ' + ((' '.repeat(CELL_WIDTH)) + panelId).slice(-CELL_WIDTH);
    }
    result += '{/yellow-fg}';

    return result;
  }

  *formatStrips(lightArray) {
    for (let stripId of lightArray.stripIds) {
      const formattedPanels = Array.from(this.formatStripPanels(lightArray, stripId));
      yield `{yellow-fg}${stripId}:{/yellow-fg} ${formattedPanels.join(' ')}`;
    }
  }

  *formatStripPanels(lightArray, stripId) {
    const strip = lightArray.get(stripId);
    for (let panelId of strip.panelIds) {
      yield this.formatPanel(lightArray, stripId, panelId);
    }
  }

  formatPanel(lightArray, stripId, panelId) {
    const panelIntensity = lightArray.getIntensity(stripId, panelId);

    // pad cell to CELL_WIDTH and right align in cell
    let formattedPanel = ((' '.repeat(CELL_WIDTH)) + panelIntensity).slice(-CELL_WIDTH);

    if (panelIntensity > 50) {
      formattedPanel = `{bold}${formattedPanel}{/bold}`;
    }

    const panelColor = this._colorFromKeyword(lightArray.getColor(stripId, panelId));
    if (panelColor) {
      formattedPanel = `{${panelColor}-fg}${formattedPanel}{/${panelColor}-fg}`;
    }

    const panelActive = lightArray.isActive(stripId, panelId);
    if (panelActive) {
      formattedPanel = `{bright-red-bg}${formattedPanel}{/bright-red-bg}`;
    }

    return formattedPanel;
  }

  _colorFromKeyword(keyword) {
    switch (keyword) {
      case "success":
        return "green";
      case "error":
        return "red";
      default:
        return;
    }
  }
}
<commit_msg>Changed color when panel is pressed<commit_after>const blessed = require('blessed');

const {SculptureStore} = require('@anyware/game-logic');

const VIEW_TITLE = "{center}{bold}Panels{/bold}{/center}";
const CELL_WIDTH = 3;

export default class PanelView extends blessed.Box {
  constructor(store, windowOptions) {
    super(Object.assign({
      tags: true,
      border: {
        type: 'line'
      },
      style: {
        fg: 'white',
        bg: 'gray'
      }
    }, windowOptions));

    this.store = store;
    this.renderPanels();

    this.store.on(SculptureStore.EVENT_CHANGE, this.renderPanels.bind(this));
  }

  renderPanels() {
    const lightArray = this.store.data.get('lights');

    let content = VIEW_TITLE + '\n';
    content += this.formatPanelIDs(lightArray) + '\n';

    const formattedStrips = Array.from(this.formatStrips(lightArray));
    content += formattedStrips.join('\n');

    this.setContent(content);
  }

  formatPanelIDs(lightArray) {
    let longestPanelIdList = null;
    for (let stripId of lightArray.stripIds) {
      const panelIds = lightArray.get(stripId).panelIds;
      if (!longestPanelIdList || panelIds.length > longestPanelIdList.length) {
        longestPanelIdList = panelIds;
      }
    }

    let result = '{yellow-fg}ID';
    for (let panelId of longestPanelIdList) {
      result += ' ' + ((' '.repeat(CELL_WIDTH)) + panelId).slice(-CELL_WIDTH);
    }
    result += '{/yellow-fg}';

    return result;
  }

  *formatStrips(lightArray) {
    for (let stripId of lightArray.stripIds) {
      const formattedPanels = Array.from(this.formatStripPanels(lightArray, stripId));
      yield `{yellow-fg}${stripId}:{/yellow-fg} ${formattedPanels.join(' ')}`;
    }
  }

  *formatStripPanels(lightArray, stripId) {
    const strip = lightArray.get(stripId);
    for (let panelId of strip.panelIds) {
      yield this.formatPanel(lightArray, stripId, panelId);
    }
  }

  formatPanel(lightArray, stripId, panelId) {
    const panelIntensity = lightArray.getIntensity(stripId, panelId);

    // pad cell to CELL_WIDTH and right align in cell
    let formattedPanel = ((' '.repeat(CELL_WIDTH)) + panelIntensity).slice(-CELL_WIDTH);

    if (panelIntensity > 50) {
      formattedPanel = `{bold}${formattedPanel}{/bold}`;
    }

    const panelColor = this._colorFromKeyword(lightArray.getColor(stripId, panelId));
    if (panelColor) {
      formattedPanel = `{${panelColor}-fg}${formattedPanel}{/${panelColor}-fg}`;
    }

    const panelActive = lightArray.isActive(stripId, panelId);
    if (panelActive) {
      formattedPanel = `{bright-cyan-bg}${formattedPanel}{/bright-cyan-bg}`;
    }

    return formattedPanel;
  }

  _colorFromKeyword(keyword) {
    switch (keyword) {
      case "success":
        return "green";
      case "error":
        return "red";
      default:
        return;
    }
  }
}
<|endoftext|>