<commit_before>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ReactPropTypes
 */

'use strict';

var ReactElement = require('ReactElement');
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');

var emptyFunction = require('emptyFunction');
var getIteratorFn = require('getIteratorFn');
var invariant = require('invariant');
var warning = require('warning');

/**
 * Collection of methods that allow declaration and validation of props that are
 * supplied to React components. Example usage:
 *
 *   var Props = require('ReactPropTypes');
 *   var MyArticle = React.createClass({
 *     propTypes: {
 *       // An optional string prop named "description".
 *       description: Props.string,
 *
 *       // A required enum prop named "category".
 *       category: Props.oneOf(['News','Photos']).isRequired,
 *
 *       // A prop named "dialog" that requires an instance of Dialog.
 *       dialog: Props.instanceOf(Dialog).isRequired
 *     },
 *     render: function() { ... }
 *   });
 *
 * A more formal specification of how these methods are used:
 *
 *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
 *   decl := ReactPropTypes.{type}(.isRequired)?
 *
 * Each and every declaration produces a function with the same signature. This
 * allows the creation of custom validation functions. For example:
 *
 *  var MyLink = React.createClass({
 *    propTypes: {
 *      // An optional string or URI prop named "href".
 *      href: function(props, propName, componentName) {
 *        var propValue = props[propName];
 *        if (propValue != null && typeof propValue !== 'string' &&
 *            !(propValue instanceof URI)) {
 *          return new Error(
 *            'Expected a string or an URI for ' + propName + ' in ' +
 *            componentName
 *          );
 *        }
 *      }
 *    },
 *    render: function() {...}
 *  });
 *
 * @internal
 */

var ANONYMOUS = '<<anonymous>>';

var ReactPropTypes;

if (__DEV__) {
  // Keep in sync with production version below
  ReactPropTypes = {
    array: createPrimitiveTypeChecker('array'),
    bool: createPrimitiveTypeChecker('boolean'),
    func: createPrimitiveTypeChecker('function'),
    number: createPrimitiveTypeChecker('number'),
    object: createPrimitiveTypeChecker('object'),
    string: createPrimitiveTypeChecker('string'),
    symbol: createPrimitiveTypeChecker('symbol'),

    any: createAnyTypeChecker(),
    arrayOf: createArrayOfTypeChecker,
    element: createElementTypeChecker(),
    instanceOf: createInstanceTypeChecker,
    node: createNodeChecker(),
    objectOf: createObjectOfTypeChecker,
    oneOf: createEnumTypeChecker,
    oneOfType: createUnionTypeChecker,
    shape: createShapeTypeChecker,
  };
} else {
  var productionTypeChecker = function() {
    invariant(
      false,
      'React.PropTypes type checking code is stripped in production.'
    );
  };
  productionTypeChecker.isRequired = productionTypeChecker;
  var getProductionTypeChecker = () => productionTypeChecker;
  // Keep in sync with development version above
  ReactPropTypes = {
    array: productionTypeChecker,
    bool: productionTypeChecker,
    func: productionTypeChecker,
    number: productionTypeChecker,
    object: productionTypeChecker,
    string: productionTypeChecker,
    symbol: productionTypeChecker,

    any: productionTypeChecker,
    arrayOf: getProductionTypeChecker,
    element: productionTypeChecker,
    instanceOf: getProductionTypeChecker,
    node: productionTypeChecker,
    objectOf: getProductionTypeChecker,
    oneOf: getProductionTypeChecker,
    oneOfType: getProductionTypeChecker,
    shape: getProductionTypeChecker,
  };
}

/**
 * inlined Object.is polyfill to avoid requiring consumers ship their own
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 */
/*eslint-disable no-self-compare*/
function is(x, y) {
  // SameValue algorithm
  if (x === y) { // Steps 1-5, 7-10
    // Steps 6.b-6.e: +0 != -0
    return x !== 0 || 1 / x === 1 / y;
  } else {
    // Step 6.a: NaN == NaN
    return x !== x && y !== y;
  }
}
/*eslint-enable no-self-compare*/

/**
 * We use an Error-like object for backward compatibility as people may call
 * PropTypes directly and inspect their output. However we don't use real
 * Errors anymore. We don't inspect their stack anyway, and creating them
 * is prohibitively expensive if they are created too often, such as what
 * happens in oneOfType() for any type before the one that matched.
 */
function PropTypeError(message) {
  this.message = message;
  this.stack = '';
}
// Make `instanceof Error` still work for returned errors.
PropTypeError.prototype = Error.prototype;

function createChainableTypeChecker(validate) {
  function checkType(
    isRequired,
    props,
    propName,
    componentName,
    location,
    propFullName
  ) {
    componentName = componentName || ANONYMOUS;
    propFullName = propFullName || propName;
    if (props[propName] == null) {
      var locationName = ReactPropTypeLocationNames[location];
      if (isRequired) {
        if (props[propName] === null) {
          return new PropTypeError(
            `The ${locationName} \`${propFullName}\` is marked as required ` +
            `in \`${componentName}\`, but its value is \`null\`.`
          );
        }
        return new PropTypeError(
          `The ${locationName} \`${propFullName}\` is marked as required in ` +
          `\`${componentName}\`, but its value is \`undefined\`.`
        );
      }
      return null;
    } else {
      return validate(props, propName, componentName, location, propFullName);
    }
  }

  var chainedCheckType = checkType.bind(null, false);
  chainedCheckType.isRequired = checkType.bind(null, true);

  return chainedCheckType;
}

function createPrimitiveTypeChecker(expectedType) {
  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    var propType = getPropType(propValue);
    if (propType !== expectedType) {
      var locationName = ReactPropTypeLocationNames[location];
      // `propValue` being instance of, say, date/regexp, pass the 'object'
      // check, but we can offer a more precise error message here rather than
      // 'of type `object`'.
      var preciseType = getPreciseType(propValue);

      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${preciseType}\` supplied to \`${componentName}\`, expected ` +
        `\`${expectedType}\`.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createAnyTypeChecker() {
  return createChainableTypeChecker(emptyFunction.thatReturns(null));
}

function createArrayOfTypeChecker(typeChecker) {
  function validate(props, propName, componentName, location, propFullName) {
    if (typeof typeChecker !== 'function') {
      return new PropTypeError(
        `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside arrayOf.`
      );
    }
    var propValue = props[propName];
    if (!Array.isArray(propValue)) {
      var locationName = ReactPropTypeLocationNames[location];
      var propType = getPropType(propValue);
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${propType}\` supplied to \`${componentName}\`, expected an array.`
      );
    }
    for (var i = 0; i < propValue.length; i++) {
      var error = typeChecker(
        propValue,
        i,
        componentName,
        location,
        `${propFullName}[${i}]`
      );
      if (error instanceof Error) {
        return error;
      }
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createElementTypeChecker() {
  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    if (!ReactElement.isValidElement(propValue)) {
      var locationName = ReactPropTypeLocationNames[location];
      var propType = getPropType(propValue);
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${propType}\` supplied to \`${componentName}\`, expected a single ReactElement.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createInstanceTypeChecker(expectedClass) {
  function validate(props, propName, componentName, location, propFullName) {
    if (!(props[propName] instanceof expectedClass)) {
      var locationName = ReactPropTypeLocationNames[location];
      var expectedClassName = expectedClass.name || ANONYMOUS;
      var actualClassName = getClassName(props[propName]);
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${actualClassName}\` supplied to \`${componentName}\`, expected ` +
        `instance of \`${expectedClassName}\`.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createEnumTypeChecker(expectedValues) {
  if (!Array.isArray(expectedValues)) {
    warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.');
    return emptyFunction.thatReturnsNull;
  }

  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    for (var i = 0; i < expectedValues.length; i++) {
      if (is(propValue, expectedValues[i])) {
        return null;
      }
    }

    var locationName = ReactPropTypeLocationNames[location];
    var valuesString = JSON.stringify(expectedValues);
    return new PropTypeError(
      `Invalid ${locationName} \`${propFullName}\` of value \`${propValue}\` ` +
      `supplied to \`${componentName}\`, expected one of ${valuesString}.`
    );
  }
  return createChainableTypeChecker(validate);
}

function createObjectOfTypeChecker(typeChecker) {
  function validate(props, propName, componentName, location, propFullName) {
    if (typeof typeChecker !== 'function') {
      return new PropTypeError(
        `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside objectOf.`
      );
    }
    var propValue = props[propName];
    var propType = getPropType(propValue);
    if (propType !== 'object') {
      var locationName = ReactPropTypeLocationNames[location];
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${propType}\` supplied to \`${componentName}\`, expected an object.`
      );
    }
    for (var key in propValue) {
      if (propValue.hasOwnProperty(key)) {
        var error = typeChecker(
          propValue,
          key,
          componentName,
          location,
          `${propFullName}.${key}`
        );
        if (error instanceof Error) {
          return error;
        }
      }
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createUnionTypeChecker(arrayOfTypeCheckers) {
  if (!Array.isArray(arrayOfTypeCheckers)) {
    warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.');
    return emptyFunction.thatReturnsNull;
  }

  function validate(props, propName, componentName, location, propFullName) {
    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
      var checker = arrayOfTypeCheckers[i];
      if (
        checker(props, propName, componentName, location, propFullName) == null
      ) {
        return null;
      }
    }

    var locationName = ReactPropTypeLocationNames[location];
    return new PropTypeError(
      `Invalid ${locationName} \`${propFullName}\` supplied to ` +
      `\`${componentName}\`.`
    );
  }
  return createChainableTypeChecker(validate);
}

function createNodeChecker() {
  function validate(props, propName, componentName, location, propFullName) {
    if (!isNode(props[propName])) {
      var locationName = ReactPropTypeLocationNames[location];
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` supplied to ` +
        `\`${componentName}\`, expected a ReactNode.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createShapeTypeChecker(shapeTypes) {
  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    var propType = getPropType(propValue);
    if (propType !== 'object') {
      var locationName = ReactPropTypeLocationNames[location];
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type \`${propType}\` ` +
        `supplied to \`${componentName}\`, expected \`object\`.`
      );
    }
    for (var key in shapeTypes) {
      var checker = shapeTypes[key];
      if (!checker) {
        continue;
      }
      var error = checker(
        propValue,
        key,
        componentName,
        location,
        `${propFullName}.${key}`
      );
      if (error) {
        return error;
      }
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function isNode(propValue) {
  switch (typeof propValue) {
    case 'number':
    case 'string':
    case 'undefined':
      return true;
    case 'boolean':
      return !propValue;
    case 'object':
      if (Array.isArray(propValue)) {
        return propValue.every(isNode);
      }
      if (propValue === null || ReactElement.isValidElement(propValue)) {
        return true;
      }

      var iteratorFn = getIteratorFn(propValue);
      if (iteratorFn) {
        var iterator = iteratorFn.call(propValue);
        var step;
        if (iteratorFn !== propValue.entries) {
          while (!(step = iterator.next()).done) {
            if (!isNode(step.value)) {
              return false;
            }
          }
        } else {
          // Iterator will provide entry [k,v] tuples rather than values.
          while (!(step = iterator.next()).done) {
            var entry = step.value;
            if (entry) {
              if (!isNode(entry[1])) {
                return false;
              }
            }
          }
        }
      } else {
        return false;
      }

      return true;
    default:
      return false;
  }
}

function isSymbol(propType, propValue) {
  // Native Symbol.
  if (propType === 'symbol') {
    return true;
  }

  // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
  if (propValue['@@toStringTag'] === 'Symbol') {
    return true;
  }

  // Fallback for non-spec compliant Symbols which are polyfilled.
  if (typeof Symbol === 'function' && propValue instanceof Symbol) {
    return true;
  }

  return false;
}

// Equivalent of `typeof` but with special handling for array and regexp.
function getPropType(propValue) {
  var propType = typeof propValue;
  if (Array.isArray(propValue)) {
    return 'array';
  }
  if (propValue instanceof RegExp) {
    // Old webkits (at least until Android 4.0) return 'function' rather than
    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
    // passes PropTypes.object.
    return 'object';
  }
  if (isSymbol(propType, propValue)) {
    return 'symbol';
  }
  return propType;
}

// This handles more types than `getPropType`. Only used for error messages.
// See `createPrimitiveTypeChecker`.
function getPreciseType(propValue) {
  var propType = getPropType(propValue);
  if (propType === 'object') {
    if (propValue instanceof Date) {
      return 'date';
    } else if (propValue instanceof RegExp) {
      return 'regexp';
    }
  }
  return propType;
}

// Returns class name of the object, if any.
function getClassName(propValue) {
  if (!propValue.constructor || !propValue.constructor.name) {
    return ANONYMOUS;
  }
  return propValue.constructor.name;
}

module.exports = ReactPropTypes;
<commit_msg>Small ReactPropTypes refactor (#8771)<commit_after>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ReactPropTypes
 */

'use strict';

var ReactElement = require('ReactElement');
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');

var emptyFunction = require('emptyFunction');
var getIteratorFn = require('getIteratorFn');
var invariant = require('invariant');
var warning = require('warning');

/**
 * Collection of methods that allow declaration and validation of props that are
 * supplied to React components. Example usage:
 *
 *   var Props = require('ReactPropTypes');
 *   var MyArticle = React.createClass({
 *     propTypes: {
 *       // An optional string prop named "description".
 *       description: Props.string,
 *
 *       // A required enum prop named "category".
 *       category: Props.oneOf(['News','Photos']).isRequired,
 *
 *       // A prop named "dialog" that requires an instance of Dialog.
 *       dialog: Props.instanceOf(Dialog).isRequired
 *     },
 *     render: function() { ... }
 *   });
 *
 * A more formal specification of how these methods are used:
 *
 *   type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
 *   decl := ReactPropTypes.{type}(.isRequired)?
 *
 * Each and every declaration produces a function with the same signature. This
 * allows the creation of custom validation functions. For example:
 *
 *  var MyLink = React.createClass({
 *    propTypes: {
 *      // An optional string or URI prop named "href".
 *      href: function(props, propName, componentName) {
 *        var propValue = props[propName];
 *        if (propValue != null && typeof propValue !== 'string' &&
 *            !(propValue instanceof URI)) {
 *          return new Error(
 *            'Expected a string or an URI for ' + propName + ' in ' +
 *            componentName
 *          );
 *        }
 *      }
 *    },
 *    render: function() {...}
 *  });
 *
 * @internal
 */

var ANONYMOUS = '<<anonymous>>';

var ReactPropTypes;

if (__DEV__) {
  // Keep in sync with production version below
  ReactPropTypes = {
    array: createPrimitiveTypeChecker('array'),
    bool: createPrimitiveTypeChecker('boolean'),
    func: createPrimitiveTypeChecker('function'),
    number: createPrimitiveTypeChecker('number'),
    object: createPrimitiveTypeChecker('object'),
    string: createPrimitiveTypeChecker('string'),
    symbol: createPrimitiveTypeChecker('symbol'),

    any: createAnyTypeChecker(),
    arrayOf: createArrayOfTypeChecker,
    element: createElementTypeChecker(),
    instanceOf: createInstanceTypeChecker,
    node: createNodeChecker(),
    objectOf: createObjectOfTypeChecker,
    oneOf: createEnumTypeChecker,
    oneOfType: createUnionTypeChecker,
    shape: createShapeTypeChecker,
  };
} else {
  var productionTypeChecker = function() {
    invariant(
      false,
      'React.PropTypes type checking code is stripped in production.'
    );
  };
  productionTypeChecker.isRequired = productionTypeChecker;
  var getProductionTypeChecker = () => productionTypeChecker;
  // Keep in sync with development version above
  ReactPropTypes = {
    array: productionTypeChecker,
    bool: productionTypeChecker,
    func: productionTypeChecker,
    number: productionTypeChecker,
    object: productionTypeChecker,
    string: productionTypeChecker,
    symbol: productionTypeChecker,

    any: productionTypeChecker,
    arrayOf: getProductionTypeChecker,
    element: productionTypeChecker,
    instanceOf: getProductionTypeChecker,
    node: productionTypeChecker,
    objectOf: getProductionTypeChecker,
    oneOf: getProductionTypeChecker,
    oneOfType: getProductionTypeChecker,
    shape: getProductionTypeChecker,
  };
}

/**
 * inlined Object.is polyfill to avoid requiring consumers ship their own
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
 */
/*eslint-disable no-self-compare*/
function is(x, y) {
  // SameValue algorithm
  if (x === y) { // Steps 1-5, 7-10
    // Steps 6.b-6.e: +0 != -0
    return x !== 0 || 1 / x === 1 / y;
  } else {
    // Step 6.a: NaN == NaN
    return x !== x && y !== y;
  }
}
/*eslint-enable no-self-compare*/

/**
 * We use an Error-like object for backward compatibility as people may call
 * PropTypes directly and inspect their output. However we don't use real
 * Errors anymore. We don't inspect their stack anyway, and creating them
 * is prohibitively expensive if they are created too often, such as what
 * happens in oneOfType() for any type before the one that matched.
 */
function PropTypeError(message) {
  this.message = message;
  this.stack = '';
}
// Make `instanceof Error` still work for returned errors.
PropTypeError.prototype = Error.prototype;

function createChainableTypeChecker(validate) {
  function checkType(
    isRequired,
    props,
    propName,
    componentName,
    location,
    propFullName
  ) {
    componentName = componentName || ANONYMOUS;
    propFullName = propFullName || propName;
    if (props[propName] == null) {
      var locationName = ReactPropTypeLocationNames[location];
      if (isRequired) {
        if (props[propName] === null) {
          return new PropTypeError(
            `The ${locationName} \`${propFullName}\` is marked as required ` +
            `in \`${componentName}\`, but its value is \`null\`.`
          );
        }
        return new PropTypeError(
          `The ${locationName} \`${propFullName}\` is marked as required in ` +
          `\`${componentName}\`, but its value is \`undefined\`.`
        );
      }
      return null;
    } else {
      return validate(props, propName, componentName, location, propFullName);
    }
  }

  var chainedCheckType = checkType.bind(null, false);
  chainedCheckType.isRequired = checkType.bind(null, true);

  return chainedCheckType;
}

function createPrimitiveTypeChecker(expectedType) {
  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    var propType = getPropType(propValue);
    if (propType !== expectedType) {
      var locationName = ReactPropTypeLocationNames[location];
      // `propValue` being instance of, say, date/regexp, pass the 'object'
      // check, but we can offer a more precise error message here rather than
      // 'of type `object`'.
      var preciseType = getPreciseType(propValue);

      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${preciseType}\` supplied to \`${componentName}\`, expected ` +
        `\`${expectedType}\`.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createAnyTypeChecker() {
  return createChainableTypeChecker(emptyFunction.thatReturnsNull);
}

function createArrayOfTypeChecker(typeChecker) {
  function validate(props, propName, componentName, location, propFullName) {
    if (typeof typeChecker !== 'function') {
      return new PropTypeError(
        `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside arrayOf.`
      );
    }
    var propValue = props[propName];
    if (!Array.isArray(propValue)) {
      var locationName = ReactPropTypeLocationNames[location];
      var propType = getPropType(propValue);
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${propType}\` supplied to \`${componentName}\`, expected an array.`
      );
    }
    for (var i = 0; i < propValue.length; i++) {
      var error = typeChecker(
        propValue,
        i,
        componentName,
        location,
        `${propFullName}[${i}]`
      );
      if (error instanceof Error) {
        return error;
      }
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createElementTypeChecker() {
  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    if (!ReactElement.isValidElement(propValue)) {
      var locationName = ReactPropTypeLocationNames[location];
      var propType = getPropType(propValue);
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${propType}\` supplied to \`${componentName}\`, expected a single ReactElement.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createInstanceTypeChecker(expectedClass) {
  function validate(props, propName, componentName, location, propFullName) {
    if (!(props[propName] instanceof expectedClass)) {
      var locationName = ReactPropTypeLocationNames[location];
      var expectedClassName = expectedClass.name || ANONYMOUS;
      var actualClassName = getClassName(props[propName]);
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${actualClassName}\` supplied to \`${componentName}\`, expected ` +
        `instance of \`${expectedClassName}\`.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createEnumTypeChecker(expectedValues) {
  if (!Array.isArray(expectedValues)) {
    warning(false, 'Invalid argument supplied to oneOf, expected an instance of array.');
    return emptyFunction.thatReturnsNull;
  }

  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    for (var i = 0; i < expectedValues.length; i++) {
      if (is(propValue, expectedValues[i])) {
        return null;
      }
    }

    var locationName = ReactPropTypeLocationNames[location];
    var valuesString = JSON.stringify(expectedValues);
    return new PropTypeError(
      `Invalid ${locationName} \`${propFullName}\` of value \`${propValue}\` ` +
      `supplied to \`${componentName}\`, expected one of ${valuesString}.`
    );
  }
  return createChainableTypeChecker(validate);
}

function createObjectOfTypeChecker(typeChecker) {
  function validate(props, propName, componentName, location, propFullName) {
    if (typeof typeChecker !== 'function') {
      return new PropTypeError(
        `Property \`${propFullName}\` of component \`${componentName}\` has invalid PropType notation inside objectOf.`
      );
    }
    var propValue = props[propName];
    var propType = getPropType(propValue);
    if (propType !== 'object') {
      var locationName = ReactPropTypeLocationNames[location];
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type ` +
        `\`${propType}\` supplied to \`${componentName}\`, expected an object.`
      );
    }
    for (var key in propValue) {
      if (propValue.hasOwnProperty(key)) {
        var error = typeChecker(
          propValue,
          key,
          componentName,
          location,
          `${propFullName}.${key}`
        );
        if (error instanceof Error) {
          return error;
        }
      }
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createUnionTypeChecker(arrayOfTypeCheckers) {
  if (!Array.isArray(arrayOfTypeCheckers)) {
    warning(false, 'Invalid argument supplied to oneOfType, expected an instance of array.');
    return emptyFunction.thatReturnsNull;
  }

  function validate(props, propName, componentName, location, propFullName) {
    for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
      var checker = arrayOfTypeCheckers[i];
      if (
        checker(props, propName, componentName, location, propFullName) == null
      ) {
        return null;
      }
    }

    var locationName = ReactPropTypeLocationNames[location];
    return new PropTypeError(
      `Invalid ${locationName} \`${propFullName}\` supplied to ` +
      `\`${componentName}\`.`
    );
  }
  return createChainableTypeChecker(validate);
}

function createNodeChecker() {
  function validate(props, propName, componentName, location, propFullName) {
    if (!isNode(props[propName])) {
      var locationName = ReactPropTypeLocationNames[location];
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` supplied to ` +
        `\`${componentName}\`, expected a ReactNode.`
      );
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function createShapeTypeChecker(shapeTypes) {
  function validate(props, propName, componentName, location, propFullName) {
    var propValue = props[propName];
    var propType = getPropType(propValue);
    if (propType !== 'object') {
      var locationName = ReactPropTypeLocationNames[location];
      return new PropTypeError(
        `Invalid ${locationName} \`${propFullName}\` of type \`${propType}\` ` +
        `supplied to \`${componentName}\`, expected \`object\`.`
      );
    }
    for (var key in shapeTypes) {
      var checker = shapeTypes[key];
      if (!checker) {
        continue;
      }
      var error = checker(
        propValue,
        key,
        componentName,
        location,
        `${propFullName}.${key}`
      );
      if (error) {
        return error;
      }
    }
    return null;
  }
  return createChainableTypeChecker(validate);
}

function isNode(propValue) {
  switch (typeof propValue) {
    case 'number':
    case 'string':
    case 'undefined':
      return true;
    case 'boolean':
      return !propValue;
    case 'object':
      if (Array.isArray(propValue)) {
        return propValue.every(isNode);
      }
      if (propValue === null || ReactElement.isValidElement(propValue)) {
        return true;
      }

      var iteratorFn = getIteratorFn(propValue);
      if (iteratorFn) {
        var iterator = iteratorFn.call(propValue);
        var step;
        if (iteratorFn !== propValue.entries) {
          while (!(step = iterator.next()).done) {
            if (!isNode(step.value)) {
              return false;
            }
          }
        } else {
          // Iterator will provide entry [k,v] tuples rather than values.
          while (!(step = iterator.next()).done) {
            var entry = step.value;
            if (entry) {
              if (!isNode(entry[1])) {
                return false;
              }
            }
          }
        }
      } else {
        return false;
      }

      return true;
    default:
      return false;
  }
}

function isSymbol(propType, propValue) {
  // Native Symbol.
  if (propType === 'symbol') {
    return true;
  }

  // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
  if (propValue['@@toStringTag'] === 'Symbol') {
    return true;
  }

  // Fallback for non-spec compliant Symbols which are polyfilled.
  if (typeof Symbol === 'function' && propValue instanceof Symbol) {
    return true;
  }

  return false;
}

// Equivalent of `typeof` but with special handling for array and regexp.
function getPropType(propValue) {
  var propType = typeof propValue;
  if (Array.isArray(propValue)) {
    return 'array';
  }
  if (propValue instanceof RegExp) {
    // Old webkits (at least until Android 4.0) return 'function' rather than
    // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
    // passes PropTypes.object.
    return 'object';
  }
  if (isSymbol(propType, propValue)) {
    return 'symbol';
  }
  return propType;
}

// This handles more types than `getPropType`. Only used for error messages.
// See `createPrimitiveTypeChecker`.
function getPreciseType(propValue) {
  var propType = getPropType(propValue);
  if (propType === 'object') {
    if (propValue instanceof Date) {
      return 'date';
    } else if (propValue instanceof RegExp) {
      return 'regexp';
    }
  }
  return propType;
}

// Returns class name of the object, if any.
function getClassName(propValue) {
  if (!propValue.constructor || !propValue.constructor.name) {
    return ANONYMOUS;
  }
  return propValue.constructor.name;
}

module.exports = ReactPropTypes;
<|endoftext|>


<commit_before>'use strict';

define(['bitcoinjs-lib', 'model/pocket/base'], function(Bitcoin, BasePocket) {

/**
 * Hierarchical Deterministic Pocket functionality.
 * @param {Object} store Store for the object.
 * @param {Object} pockets Pockets parent object
 * @constructor
 */
function HdPocket(store, pockets) {
    this.store = store;
    BasePocket.call(this, pockets);
    this.name = store.name;
    this.mainAddress = null;
}

HdPocket.prototype = Object.create(BasePocket.prototype);

// Pocket definition
HdPocket.prototype.type = 'hd';
HdPocket.prototype.types = [undefined, 'stealth'];
HdPocket.prototype.autoCreate = true;

/**
 * Get the index for some address in this pocket
 */
HdPocket.prototype.getIndex = function(walletAddress) {
    return Math.floor(walletAddress.index[0]/2);
};

/**
 * Get the main address for this pocket
 */
HdPocket.prototype.getMainAddress = function() {
    var wallet = this.getMyWallet();
    var index = wallet.pockets.hdPockets.indexOf(this.store);
    if (index === -1) {
        throw new Error("Wrong hd pocket!");
    }
    return wallet.getAddress([index*2]);
};

/**
 * Get our index
 */
HdPocket.prototype.getPocketId = function() {
    var wallet = this.getMyWallet();
    return wallet.pockets.hdPockets.indexOf(this.store);
}

/**
 * Custom destroy to also cleanup the internal hdPocket
 */
HdPocket.prototype.destroy = function() {
    // First cleanup using the base class
    var destroyed = BasePocket.prototype.destroy.call(this);

    // Now do specific hd pocket cleaning
    var pocketId = this.getPocketId();
    var wallet = this.getMyWallet();
    wallet.pockets.hdPockets[pocketId] = null;
    return destroyed;
};

/**
 * Custom addToPocket so we treat pocket address in a special
 * way.
 */
HdPocket.prototype.addToPocket = function(walletAddress) {
    // We store pocket addresses as well as normal receiving addresses,
    // The pocket address is the one used to derive the stealth address,
    // and normally shouldn't receive funds and the user shouldn't see
    // it.
    // At the moment we leave it to the gui not to show the address
    // to the user and make it invisible.
    this.addresses.push(walletAddress.address);
    this.walletAddresses.push(walletAddress);
};

/**
 * Get a free address
 */
HdPocket.prototype.getFreeAddress = function(change, label) {
    var walletAddress;
    // normal address, get the address
    var branchIndex = this.getPocketId()*2;
    if (change) {
        branchIndex += 1;
    }
    var n = 0;
    do {
        walletAddress = this.getMyWallet().getAddress([branchIndex, n], label);
        n += 1;
    } while (walletAddress.nOutputs > 0);

    // This should have no type
    if (walletAddress.type) {
       throw new Error("Generated an incorrect change address");
    }
    return walletAddress;
};

return HdPocket;
});
<commit_msg>Cleanup trailing null pockets from the list after deleting a pocket.<commit_after>'use strict';

define(['bitcoinjs-lib', 'model/pocket/base'], function(Bitcoin, BasePocket) {

/**
 * Hierarchical Deterministic Pocket functionality.
 * @param {Object} store Store for the object.
 * @param {Object} pockets Pockets parent object
 * @constructor
 */
function HdPocket(store, pockets) {
    this.store = store;
    BasePocket.call(this, pockets);
    this.name = store.name;
    this.mainAddress = null;
}

HdPocket.prototype = Object.create(BasePocket.prototype);

// Pocket definition
HdPocket.prototype.type = 'hd';
HdPocket.prototype.types = [undefined, 'stealth'];
HdPocket.prototype.autoCreate = true;

/**
 * Get the index for some address in this pocket
 */
HdPocket.prototype.getIndex = function(walletAddress) {
    return Math.floor(walletAddress.index[0]/2);
};

/**
 * Get the main address for this pocket
 */
HdPocket.prototype.getMainAddress = function() {
    var wallet = this.getMyWallet();
    var index = wallet.pockets.hdPockets.indexOf(this.store);
    if (index === -1) {
        throw new Error("Wrong hd pocket!");
    }
    return wallet.getAddress([index*2]);
};

/**
 * Get our index
 */
HdPocket.prototype.getPocketId = function() {
    var wallet = this.getMyWallet();
    return wallet.pockets.hdPockets.indexOf(this.store);
}

/**
 * Custom destroy to also cleanup the internal hdPocket
 */
HdPocket.prototype.destroy = function() {
    // First cleanup using the base class
    var destroyed = BasePocket.prototype.destroy.call(this);

    // Now do specific hd pocket cleaning
    var pocketId = this.getPocketId();
    var wallet = this.getMyWallet();
    wallet.pockets.hdPockets[pocketId] = null;
    while(!wallet.pockets.hdPockets[wallet.pockets.hdPockets.length-1]) {
        wallet.pockets.hdPockets.pop();
    }
    return destroyed;
};

/**
 * Custom addToPocket so we treat pocket address in a special
 * way.
 */
HdPocket.prototype.addToPocket = function(walletAddress) {
    // We store pocket addresses as well as normal receiving addresses,
    // The pocket address is the one used to derive the stealth address,
    // and normally shouldn't receive funds and the user shouldn't see
    // it.
    // At the moment we leave it to the gui not to show the address
    // to the user and make it invisible.
    this.addresses.push(walletAddress.address);
    this.walletAddresses.push(walletAddress);
};

/**
 * Get a free address
 */
HdPocket.prototype.getFreeAddress = function(change, label) {
    var walletAddress;
    // normal address, get the address
    var branchIndex = this.getPocketId()*2;
    if (change) {
        branchIndex += 1;
    }
    var n = 0;
    do {
        walletAddress = this.getMyWallet().getAddress([branchIndex, n], label);
        n += 1;
    } while (walletAddress.nOutputs > 0);

    // This should have no type
    if (walletAddress.type) {
       throw new Error("Generated an incorrect change address");
    }
    return walletAddress;
};

return HdPocket;
});
<|endoftext|>


<commit_before>window.modus = function () {
    //Variables
    let _os = _getParameterByName("os");

    //Helpers
    function _getParameterByName(name, url) {
        if (!url) url = window.location.href;
        name = name.replace(/[\[\]]/g, '\\$&');
        var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
            results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, ' '));
    }
    let _createDefaultResult = function (request) {
        //TODO: should this be somewhere else?
        var name = request.name;
        var result = null;

        switch (name) {
            case "getCurrentUserName":
                result = "Obi Won Kenobi"
                break;
            case "getCurrentUserEmail":
                result = "maul_killer@jedicouncil.crst"
                break;
            case "getCurrentUserRegions":
                result = ["Tatooine", "Stewjon", "Coruscant"]
                break;
            case "getItem":
                var key = "temp_storage_" + request.data.key;
                result = window[key] ? "Item: " + window[key] : "No Item Set";
                break;
            case "setItem":
                var key = "temp_storage_" + request.data.key;
                window[key] = request.data.value; //stringify?
                result = "Item was set"
                break;
        }

        window[request.successId](result);
    }

    //Marshall
    let _callNativeFunction = function (methodName, methodData) {
        var id = Math.floor(Math.random() * 10000000);
        var successId = methodName + "_success_" + id;
        var errorId = methodName + "_error_" + id;

        return new Promise(function (resolve, reject) {
            //build success function
            window[successId] = function (data) {
                resolve(data);
                window[successId] = null;
                window[errorId] = null;
                delete window[successId];
                delete window[errorId];
            };

            //build error function
            window[errorId] = function (data) {
                reject(data);
                window[successId] = null;
                window[errorId] = null;
                delete window[successId];
                delete window[errorId];
            };

            //create request
            let request = {
                name: methodName,
                data: methodData,
                successId: successId,
                errorId: errorId
            };

            let os = _getParameterByName("os");

            //  Windows
            if (os === "windows") {
                return window.external.notify(JSON.stringify(request));
            }

            //  iOS
            if (os === "ios" || (window.webkit && window.webkit.messageHandlers.modus != undefined)) {
                return window.webkit.messageHandlers.modus.postMessage(request);
            }
            //  Android
            if (os === "android" || window.appInterface != undefined) {
                return window.appInterface.postMessage(JSON.stringify(request));
            }

            //Defaults and Stubs
            return _createDefaultResult(request);
        });
    }

    //Public
    return {
        //User
        getCurrentUserName: _callNativeFunction.bind(null, "getCurrentUserName", null),
        getCurrentUserEmail: _callNativeFunction.bind(null, "getCurrentUserEmail", null),
        getCurrentUserRegions: _callNativeFunction.bind(null, "getCurrentUserRegions", null),

        //Storage
        getItem: function (key) { return _callNativeFunction("getItem", { key: key }) },
        setItem: function (key, value) { return _callNativeFunction("setItem", { key: key, value: value }) }
        //Emails
    }
}();<commit_msg>Updating request params<commit_after>window.modus = function () {
    //Variables
    let _os = _getParameterByName("os");

    //Helpers
    function _getParameterByName(name, url) {
        if (!url) url = window.location.href;
        name = name.replace(/[\[\]]/g, '\\$&');
        var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
            results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, ' '));
    }
    let _createDefaultResult = function (request) {
        //TODO: should this be somewhere else?
        var name = request.name;
        var result = null;

        switch (name) {
            case "getCurrentUserName":
                result = "Obi Won Kenobi"
                break;
            case "getCurrentUserEmail":
                result = "maul_killer@jedicouncil.crst"
                break;
            case "getCurrentUserRegions":
                result = ["Tatooine", "Stewjon", "Coruscant"]
                break;
            case "getItem":
                var key = "temp_storage_" + request.data.key;
                result = window[key] ? "Item: " + window[key] : "No Item Set";
                break;
            case "setItem":
                var key = "temp_storage_" + request.data.key;
                window[key] = request.data.value; //stringify?
                result = "Item was set"
                break;
        }

        window[request.successId](result);
    }

    //Marshall
    let _callNativeFunction = function (methodName, methodData) {
        var id = Math.floor(Math.random() * 10000000);
        var successId = methodName + "_success_" + id;
        var errorId = methodName + "_error_" + id;

        return new Promise(function (resolve, reject) {
            //build success function
            window[successId] = function (data) {
                resolve(data);
                window[successId] = null;
                window[errorId] = null;
                delete window[successId];
                delete window[errorId];
            };

            //build error function
            window[errorId] = function (data) {
                reject(data);
                window[successId] = null;
                window[errorId] = null;
                delete window[successId];
                delete window[errorId];
            };

            //create request
            let request = {
                methodName: methodName,
                data: methodData,
                successMethodId: successId,
                errorMethodId: errorId
            };

            let os = _getParameterByName("os");

            //  Windows
            if (os === "windows") {
                return window.external.notify(JSON.stringify(request));
            }

            //  iOS
            if (os === "ios" || (window.webkit && window.webkit.messageHandlers.modus != undefined)) {
                return window.webkit.messageHandlers.modus.postMessage(request);
            }
            //  Android
            if (os === "android" || window.appInterface != undefined) {
                return window.appInterface.postMessage(JSON.stringify(request));
            }

            //Defaults and Stubs
            return _createDefaultResult(request);
        });
    }

    //Public
    return {
        //User
        getCurrentUserName: _callNativeFunction.bind(null, "getCurrentUserName", null),
        getCurrentUserEmail: _callNativeFunction.bind(null, "getCurrentUserEmail", null),
        getCurrentUserRegions: _callNativeFunction.bind(null, "getCurrentUserRegions", null),

        //Storage
        getItem: function (key) { return _callNativeFunction("getItem", { key: key }) },
        setItem: function (key, value) { return _callNativeFunction("setItem", { key: key, value: value }) }
        //Emails
    }
}();<|endoftext|>


<commit_before>var onPageLoad = require('../shared/pageload');
var FLImage = require('../models/image');
var Thumbnail = require('../views/thumbnail');
var Executable = require('../views/executable');

$(function(){
    onPageLoad('start_job');

    var gallery = $('#gallery');

    api.getImages(function(data) {
        if (data.res) {
            _.each(data.images, function(img) {
                var image = new FLImage({
                    src: api.url + 'img?id=' + img.imageid
                });
                var thumb = new Thumbnail({
                    model: image
                });
                thumb.render().$el.appendTo(gallery);
            });
        }
    });

    api.getExecutables(function(data) {
        if (data.res) {
            if (data.execs.length === 0) {
                $('#exelist').text('No executables to run. Please upload one.');
            }
            else {
                _.each(data.execs, function(exec) {
                    console.log(exec);
                    var exe = new Executable({
                        name: exec.name
                    });
                    exe.render().$el.appendTo('#exelist ul');
                });
            }
        }
    });

    $('#start').on('click', function() {
        console.log($('input[type=radio]:checked'));

        var exe = 1;
        var images = [1, 2, 3];

        api.startJob(exe, images, function(data) {
            console.log(data);
        });
    });
});
<commit_msg>fix start job types|<commit_after>var onPageLoad = require('../shared/pageload');
var FLImage = require('../models/image');
var Thumbnail = require('../views/thumbnail');
var Executable = require('../views/executable');

$(function(){
    onPageLoad('start_job');

    var gallery = $('#gallery');

    api.getImages(function(data) {
        if (data.res) {
            _.each(data.images, function(img) {
                var image = new FLImage({
                    src: api.url + 'img?id=' + img.imageid
                });
                var thumb = new Thumbnail({
                    model: image
                });
                thumb.render().$el.appendTo(gallery);
            });
        }
    });

    api.getExecutables(function(data) {
        if (data.res) {
            if (data.execs.length === 0) {
                $('#exelist').text('No executables to run. Please upload one.');
            }
            else {
                _.each(data.execs, function(exec) {
                    console.log(exec);
                    var exe = new Executable({
                        name: exec.name
                    });
                    exe.render().$el.appendTo('#exelist ul');
                });
            }
        }
    });

    $('#start').on('click', function() {
        console.log($('input[type=radio]:checked'));

        var exe = '4dafc690d01355d335169c52609bf08e';
        var images = ['b3639a00751454b1fa0f0cc39fb5992c', '11d70a64fee30a8dacb58f7bdfcf25f3'];

        api.startJob(exe, images, function(data) {
            console.log(data);
        });
    });
});
<|endoftext|>


<commit_before>'use strict';

var _ = require('./underscore_ext');
var Rx = require('./rx');
var widgets = require('./columnWidgets');
var colorScales = require('./colorScales');
var util = require('./util');
var Legend = require('./views/Legend');
var BandLegend = require('./views/BandLegend');
import PureComponent from './PureComponent';
var React = require('react');
var CanvasDrawing = require('./CanvasDrawing');
var {rxEvents} = require('./react-utils');
var {drawHeatmap} = require('./drawHeatmap');

// Since we don't set module.exports, but instead register ourselves
// with columWidgets, react-hot-loader can't handle the updates automatically.
// Accept hot loading here.
if (module.hot) {
	module.hot.accept();
}

// Since there are multiple components in the file we have to use makeHot
// explicitly.
function hotOrNot(component) {
	return module.makeHot ? module.makeHot(component) : component;
}

var colorFns = vs => _.map(vs, colorScales.colorScale);

//
// Tooltip
//

var prec = (function () {
	var precision = 6,
		factor = Math.pow(10, precision);
	return val => (val == null) ? 'NA' : Math.round((val * factor)) / factor;
}());

// We're getting events with coords < 0. Not sure if this
// is a side-effect of the react event system. This will
// restrict values to the given range.
function bounded(min, max, x) {
	return x < min ? min : (x > max ? max : x);
}

var posString = p => `${p.chrom}:${util.addCommas(p.chromstart)}-${util.addCommas(p.chromend)}`;
//gb position string of the segment with 15bp extra on each side, centered at segment
var posRegionString = p => {
	var pad = Math.round((p.chromend - p.chromstart) / 2);
	return `${p.chrom}:${util.addCommas(p.chromstart - pad)}-${util.addCommas(p.chromend + pad)}`;
};
var gbURL = (assembly, pos, hgtCustomtext) => {
	var assemblyString = encodeURIComponent(assembly),
		positionString = encodeURIComponent(posString(pos)),
		regionString = encodeURIComponent(posRegionString(pos));
	return `http://genome.ucsc.edu/cgi-bin/hgTracks?db=${assemblyString}
			&highlight=${assemblyString}.${positionString}
			&position=${regionString}
			${hgtCustomtext ? `&hgt.Customtext=${hgtCustomtext}` : ''}`;
};

function tooltip(id, heatmap, assembly, hgtCustomtext, fields, sampleFormat, fieldFormat, codes, position, width, zoom, samples, ev) {
	var coord = util.eventOffset(ev),
		sampleIndex = bounded(0, samples.length, Math.floor((coord.y * zoom.count / zoom.height) + zoom.index)),
		sampleID = samples[sampleIndex],
		fieldIndex = bounded(0, fields.length, Math.floor(coord.x * fields.length / width)),
		pos = _.get(position, fieldIndex),
		field = fields[fieldIndex];

	var val = _.getIn(heatmap, [fieldIndex, sampleIndex]),
		code = _.get(codes, val),
		label = fieldFormat(field);

	val = code ? code : prec(val);
	let mean = heatmap && prec(_.meannull(heatmap[fieldIndex])),
		median = heatmap && prec(_.medianNull(heatmap[fieldIndex]));
	return {
		sampleID: sampleFormat(sampleID),
		id,
		fieldIndex,
		rows: [
			[['labelValue', label, val]],
			...(pos && assembly ? [[['url', `${assembly} ${posString(pos)}`, gbURL(assembly, pos, hgtCustomtext)]]] : []),
			...((!code && (mean !== 'NA') && (median !== 'NA') ? [[['labelValue', 'Mean (Median)', mean + ' (' +
	         median + ')' ]]] : []))]
	};
}

//
// Legends
//

function categoryLegend(dataIn, colorScale, codes) {
	if (!colorScale) {
		return {colors: [], labels: []};
	}
	// only finds categories for the current data in the column
	var data = _.reject(_.uniq(dataIn), x => x == null).sort((v1, v2) =>  v1 - v2),
		colors = _.map(data, colorScale),
		labels = _.map(data, d => codes[d]);

	return {colors: colors, labels: labels};
}

// Color scale cases
// Use the domain of the scale as the label.
// If using thresholded scales, add '<' '>' to labels.

var cases = ([tag], arg, c) => c[tag](arg);

function legendForColorscale(colorSpec) {
	var scale = colorScales.colorScale(colorSpec),
		values = scale.domain(),
		colors = _.map(values, scale);

	var labels = cases(colorSpec, values, {
		'no-data': () => [],
		'float': _.identity,
		'float-pos': _.identity,
		'float-neg': _.identity,
		'float-thresh': ([nl, nh, pl, ph]) => [nl, nh, pl, ph],
		'float-thresh-pos': ([low, high]) => [low, high],
		'float-thresh-neg': ([low, high]) => [low, high],
		'float-thresh-log-pos': ([low, high]) => [low, high],
		'float-thresh-log-neg': ([low, high]) => [low, high],
		'float-log': ([low, high]) => [low, high],
	});

	return {colors, labels};
}

// We never want to draw multiple legends. We only draw the 1st scale
// passed in. The caller should provide labels/colors in the 'legend' prop
// if there are multiple scales.
function renderFloatLegend(props) {
	var {units, colors, vizSettings, data} = props;

	if (_.isEmpty(data)) {
		return <Legend colors={[]} labels={''} footnotes={[]}/>;;
	}
	var subColColor = _.max(colors, colorList => _.uniq(colorList.slice(Math.ceil(colorList.length / 2.0))).length),
		{labels, colors: legendColors} = legendForColorscale(subColColor),
		unitText = units[0],
		footnotes = [units && units[0] ? {unitText} : null],
		hasViz = vizSettings => !isNaN(_.getIn(vizSettings, ['min'])),
		multiScaled = colors && colors.length > 1 && !hasViz(vizSettings);

	if (multiScaled) {
		labels = labels.map((label, i) => {
			if (i === 0) {return "lower";}
			else if(i === labels.length - 1) {return "higher";}
			else {return "";}
		});
	}

	return <Legend colors={legendColors} labels={labels} footnotes={footnotes}/>;
}

// might want to use <wbr> here, instead, so cut & paste work better, but that
// will require a recursive split/flatmap to inject the <wbr> elements.
var addWordBreaks = str => str.replace(/([_/])/g, '\u200B$1\u200B');

function renderFloatLegendNew(props) {
	var {units, colors, data, vizSettings} = props;

	if (_.isEmpty(data)) {
		return null;
	}

	var colorSpec = _.max(colors, colorList => _.uniq(colorList.slice(Math.ceil(colorList.length / 2.0))).length);

	if (colorSpec[0] === 'no-data') {
		return null;
	}

	var scale = colorScales.colorScale(colorSpec),
		values = scale.domain(),
		footnotes = units && units[0] ? [{addWordBreaks(units[0])}] : null,
		hasViz = !isNaN(_.getIn(vizSettings, ['min'])),
		multiScaled = colors && colors.length > 1 && !hasViz;

	return (
		<BandLegend
			multiScaled={multiScaled}
			range={{min: _.first(values), max: _.last(values)}}
			colorScale={scale}
			footnotes={footnotes}
			width={50}
			height={20}/>);
}

// Might have colorScale but no data (phenotype), no data & no colorScale,
// or data & colorScale, no colorScale &  data?
function renderCodedLegend(props) {
	var {data: [data] = [], codes, colors = []} = props;
	var legendProps;
	var colorfn = _.first(colorFns(colors.slice(0, 1)));

	// We can use domain() for categorical, but we want to filter out
	// values not in the plot. Also, we build the categorical from all
	// values in the db (even those not in the plot) so that colors will
	// match in other datasets.
	if (data && colorfn) { // category
		legendProps = categoryLegend(data, colorfn, codes);
	} else {
		return ;
	}

	return <Legend {...legendProps} />;
}

var HeatmapLegend = hotOrNot(class extends PureComponent {
	render() {
		var {column, data, newLegend} = this.props,
			{units, heatmap, colors, valueType, vizSettings, defaultNormalization} = column,
			props = {
				units,
				colors,
				vizSettings,
				defaultNormalization,
				data: heatmap,
				coded: valueType === 'coded',
				codes: _.get(data, 'codes'),
			};
		return (props.coded ? renderCodedLegend :
			newLegend ? renderFloatLegendNew :
			renderFloatLegend)(props);
	}
});

//
// plot rendering
//

var HeatmapColumn = hotOrNot(//
// plot rendering
//

class extends PureComponent {
	componentWillMount() {
		var events = rxEvents(this, 'mouseout', 'mousemove', 'mouseover');

		// Compute tooltip events from mouse events.
		this.ttevents = events.mouseover.filter(ev => util.hasClass(ev.currentTarget, 'Tooltip-target'))
			.flatMap(() => {
				return events.mousemove
					.takeUntil(events.mouseout)
					.map(ev => ({
						data: this.tooltip(ev),
						open: true
					})) // look up current data
					.concat(Rx.Observable.of({open: false}));
			}).subscribe(this.props.tooltip);
	}

	componentWillUnmount() {
		this.ttevents.unsubscribe();
	}

	tooltip = (ev) => {
		var {samples, data, column, zoom, sampleFormat, fieldFormat, id} = this.props,
			codes = _.get(data, 'codes'),
			// support data.req.position for old bookmarks.
			position = column.position || _.getIn(data, ['req', 'position']),
			{assembly, fields, heatmap, width, dataset} = column,
			hgtCustomtext = _.getIn(dataset, ['probemapMeta', 'hgt.customtext']);
		return tooltip(id, heatmap, assembly, hgtCustomtext, fields, sampleFormat, fieldFormat(id),
			codes, position, width, zoom, samples, ev);
	};

	// To reduce this set of properties, we could
	//    - Drop data & move codes into the 'display' obj, outside of data
	// Might also want to copy fields into 'display', so we can drop req probes
	render() {
		var {data, column, zoom} = this.props,
			{heatmap, colors} = column,
			codes = _.get(data, 'codes');

		return (
			<CanvasDrawing
					ref='plot'
					draw={drawHeatmap}
					wrapperProps={{
						className: 'Tooltip-target',
						onMouseMove: this.on.mousemove,
						onMouseOut: this.on.mouseout,
						onMouseOver: this.on.mouseover,
						onClick: this.props.onClick
					}}
					codes={codes}
					width={_.get(column, 'width')}
					zoom={zoom}
					colors={colors}
					heatmapData={heatmap}/>);
	}
});

var getColumn = props => <HeatmapColumn {...props} />;

widgets.column.add("probes", getColumn);
widgets.column.add("geneProbes", getColumn);
widgets.column.add("genes", getColumn);
widgets.column.add("clinical", getColumn);

var getLegend = props => <HeatmapLegend {...props} />;

widgets.legend.add('probes', getLegend);
widgets.legend.add('geneProbes', getLegend);
widgets.legend.add('genes', getLegend);
widgets.legend.add('clinical', getLegend);
<commit_msg>fix matrix column linkout to GB custom track typo<commit_after>'use strict';

var _ = require('./underscore_ext');
var Rx = require('./rx');
var widgets = require('./columnWidgets');
var colorScales = require('./colorScales');
var util = require('./util');
var Legend = require('./views/Legend');
var BandLegend = require('./views/BandLegend');
import PureComponent from './PureComponent';
var React = require('react');
var CanvasDrawing = require('./CanvasDrawing');
var {rxEvents} = require('./react-utils');
var {drawHeatmap} = require('./drawHeatmap');

// Since we don't set module.exports, but instead register ourselves
// with columWidgets, react-hot-loader can't handle the updates automatically.
// Accept hot loading here.
if (module.hot) {
	module.hot.accept();
}

// Since there are multiple components in the file we have to use makeHot
// explicitly.
function hotOrNot(component) {
	return module.makeHot ? module.makeHot(component) : component;
}

var colorFns = vs => _.map(vs, colorScales.colorScale);

//
// Tooltip
//

var prec = (function () {
	var precision = 6,
		factor = Math.pow(10, precision);
	return val => (val == null) ? 'NA' : Math.round((val * factor)) / factor;
}());

// We're getting events with coords < 0. Not sure if this
// is a side-effect of the react event system. This will
// restrict values to the given range.
function bounded(min, max, x) {
	return x < min ? min : (x > max ? max : x);
}

var posString = p => `${p.chrom}:${util.addCommas(p.chromstart)}-${util.addCommas(p.chromend)}`;
//gb position string of the segment with 15bp extra on each side, centered at segment
var posRegionString = p => {
	var pad = Math.round((p.chromend - p.chromstart) / 2);
	return `${p.chrom}:${util.addCommas(p.chromstart - pad)}-${util.addCommas(p.chromend + pad)}`;
};
var gbURL = (assembly, pos, hgtCustomtext) => {
	var assemblyString = encodeURIComponent(assembly),
		positionString = encodeURIComponent(posString(pos)),
		regionString = encodeURIComponent(posRegionString(pos));
	return `http://genome.ucsc.edu/cgi-bin/hgTracks?db=${assemblyString}
			&highlight=${assemblyString}.${positionString}
			&position=${regionString}
			${hgtCustomtext ? `&hgt.customText=${hgtCustomtext}` : ''}`;
};

function tooltip(id, heatmap, assembly, hgtCustomtext, fields, sampleFormat, fieldFormat, codes, position, width, zoom, samples, ev) {
	var coord = util.eventOffset(ev),
		sampleIndex = bounded(0, samples.length, Math.floor((coord.y * zoom.count / zoom.height) + zoom.index)),
		sampleID = samples[sampleIndex],
		fieldIndex = bounded(0, fields.length, Math.floor(coord.x * fields.length / width)),
		pos = _.get(position, fieldIndex),
		field = fields[fieldIndex];

	var val = _.getIn(heatmap, [fieldIndex, sampleIndex]),
		code = _.get(codes, val),
		label = fieldFormat(field);

	val = code ? code : prec(val);
	let mean = heatmap && prec(_.meannull(heatmap[fieldIndex])),
		median = heatmap && prec(_.medianNull(heatmap[fieldIndex]));
	return {
		sampleID: sampleFormat(sampleID),
		id,
		fieldIndex,
		rows: [
			[['labelValue', label, val]],
			...(pos && assembly ? [[['url', `${assembly} ${posString(pos)}`, gbURL(assembly, pos, hgtCustomtext)]]] : []),
			...((!code && (mean !== 'NA') && (median !== 'NA') ? [[['labelValue', 'Mean (Median)', mean + ' (' +
	         median + ')' ]]] : []))]
	};
}

//
// Legends
//

function categoryLegend(dataIn, colorScale, codes) {
	if (!colorScale) {
		return {colors: [], labels: []};
	}
	// only finds categories for the current data in the column
	var data = _.reject(_.uniq(dataIn), x => x == null).sort((v1, v2) =>  v1 - v2),
		colors = _.map(data, colorScale),
		labels = _.map(data, d => codes[d]);

	return {colors: colors, labels: labels};
}

// Color scale cases
// Use the domain of the scale as the label.
// If using thresholded scales, add '<' '>' to labels.

var cases = ([tag], arg, c) => c[tag](arg);

function legendForColorscale(colorSpec) {
	var scale = colorScales.colorScale(colorSpec),
		values = scale.domain(),
		colors = _.map(values, scale);

	var labels = cases(colorSpec, values, {
		'no-data': () => [],
		'float': _.identity,
		'float-pos': _.identity,
		'float-neg': _.identity,
		'float-thresh': ([nl, nh, pl, ph]) => [nl, nh, pl, ph],
		'float-thresh-pos': ([low, high]) => [low, high],
		'float-thresh-neg': ([low, high]) => [low, high],
		'float-thresh-log-pos': ([low, high]) => [low, high],
		'float-thresh-log-neg': ([low, high]) => [low, high],
		'float-log': ([low, high]) => [low, high],
	});

	return {colors, labels};
}

// We never want to draw multiple legends. We only draw the 1st scale
// passed in. The caller should provide labels/colors in the 'legend' prop
// if there are multiple scales.
function renderFloatLegend(props) {
	var {units, colors, vizSettings, data} = props;

	if (_.isEmpty(data)) {
		return <Legend colors={[]} labels={''} footnotes={[]}/>;;
	}
	var subColColor = _.max(colors, colorList => _.uniq(colorList.slice(Math.ceil(colorList.length / 2.0))).length),
		{labels, colors: legendColors} = legendForColorscale(subColColor),
		unitText = units[0],
		footnotes = [units && units[0] ? {unitText} : null],
		hasViz = vizSettings => !isNaN(_.getIn(vizSettings, ['min'])),
		multiScaled = colors && colors.length > 1 && !hasViz(vizSettings);

	if (multiScaled) {
		labels = labels.map((label, i) => {
			if (i === 0) {return "lower";}
			else if(i === labels.length - 1) {return "higher";}
			else {return "";}
		});
	}

	return <Legend colors={legendColors} labels={labels} footnotes={footnotes}/>;
}

// might want to use <wbr> here, instead, so cut & paste work better, but that
// will require a recursive split/flatmap to inject the <wbr> elements.
var addWordBreaks = str => str.replace(/([_/])/g, '\u200B$1\u200B');

function renderFloatLegendNew(props) {
	var {units, colors, data, vizSettings} = props;

	if (_.isEmpty(data)) {
		return null;
	}

	var colorSpec = _.max(colors, colorList => _.uniq(colorList.slice(Math.ceil(colorList.length / 2.0))).length);

	if (colorSpec[0] === 'no-data') {
		return null;
	}

	var scale = colorScales.colorScale(colorSpec),
		values = scale.domain(),
		footnotes = units && units[0] ? [{addWordBreaks(units[0])}] : null,
		hasViz = !isNaN(_.getIn(vizSettings, ['min'])),
		multiScaled = colors && colors.length > 1 && !hasViz;

	return (
		<BandLegend
			multiScaled={multiScaled}
			range={{min: _.first(values), max: _.last(values)}}
			colorScale={scale}
			footnotes={footnotes}
			width={50}
			height={20}/>);
}

// Might have colorScale but no data (phenotype), no data & no colorScale,
// or data & colorScale, no colorScale &  data?
function renderCodedLegend(props) {
	var {data: [data] = [], codes, colors = []} = props;
	var legendProps;
	var colorfn = _.first(colorFns(colors.slice(0, 1)));

	// We can use domain() for categorical, but we want to filter out
	// values not in the plot. Also, we build the categorical from all
	// values in the db (even those not in the plot) so that colors will
	// match in other datasets.
	if (data && colorfn) { // category
		legendProps = categoryLegend(data, colorfn, codes);
	} else {
		return ;
	}

	return <Legend {...legendProps} />;
}

var HeatmapLegend = hotOrNot(class extends PureComponent {
	render() {
		var {column, data, newLegend} = this.props,
			{units, heatmap, colors, valueType, vizSettings, defaultNormalization} = column,
			props = {
				units,
				colors,
				vizSettings,
				defaultNormalization,
				data: heatmap,
				coded: valueType === 'coded',
				codes: _.get(data, 'codes'),
			};
		return (props.coded ? renderCodedLegend :
			newLegend ? renderFloatLegendNew :
			renderFloatLegend)(props);
	}
});

//
// plot rendering
//

var HeatmapColumn = hotOrNot(//
// plot rendering
//

class extends PureComponent {
	componentWillMount() {
		var events = rxEvents(this, 'mouseout', 'mousemove', 'mouseover');

		// Compute tooltip events from mouse events.
		this.ttevents = events.mouseover.filter(ev => util.hasClass(ev.currentTarget, 'Tooltip-target'))
			.flatMap(() => {
				return events.mousemove
					.takeUntil(events.mouseout)
					.map(ev => ({
						data: this.tooltip(ev),
						open: true
					})) // look up current data
					.concat(Rx.Observable.of({open: false}));
			}).subscribe(this.props.tooltip);
	}

	componentWillUnmount() {
		this.ttevents.unsubscribe();
	}

	tooltip = (ev) => {
		var {samples, data, column, zoom, sampleFormat, fieldFormat, id} = this.props,
			codes = _.get(data, 'codes'),
			// support data.req.position for old bookmarks.
			position = column.position || _.getIn(data, ['req', 'position']),
			{assembly, fields, heatmap, width, dataset} = column,
			hgtCustomtext = _.getIn(dataset, ['probemapMeta', 'hgt.customtext']);
		return tooltip(id, heatmap, assembly, hgtCustomtext, fields, sampleFormat, fieldFormat(id),
			codes, position, width, zoom, samples, ev);
	};

	// To reduce this set of properties, we could
	//    - Drop data & move codes into the 'display' obj, outside of data
	// Might also want to copy fields into 'display', so we can drop req probes
	render() {
		var {data, column, zoom} = this.props,
			{heatmap, colors} = column,
			codes = _.get(data, 'codes');

		return (
			<CanvasDrawing
					ref='plot'
					draw={drawHeatmap}
					wrapperProps={{
						className: 'Tooltip-target',
						onMouseMove: this.on.mousemove,
						onMouseOut: this.on.mouseout,
						onMouseOver: this.on.mouseover,
						onClick: this.props.onClick
					}}
					codes={codes}
					width={_.get(column, 'width')}
					zoom={zoom}
					colors={colors}
					heatmapData={heatmap}/>);
	}
});

var getColumn = props => <HeatmapColumn {...props} />;

widgets.column.add("probes", getColumn);
widgets.column.add("geneProbes", getColumn);
widgets.column.add("genes", getColumn);
widgets.column.add("clinical", getColumn);

var getLegend = props => <HeatmapLegend {...props} />;

widgets.legend.add('probes', getLegend);
widgets.legend.add('geneProbes', getLegend);
widgets.legend.add('genes', getLegend);
widgets.legend.add('clinical', getLegend);
<|endoftext|>


<commit_before>function spotPosting() {
	this.commentForm = null;
	this.uiStart = null;
	this.uiDone = null;

	this.cbHashcashCalculated = function (self, hash) {
	    self.commentForm['postcommentform[newmessageid]'].value = hash;
	    self.commentForm['postcommentform[submit]'].value = 'Post';
		self.uiDone();

		// convert the processed form to post values
		var dataString = $(self.commentForm).serialize()

		// and actually process the call
		$.ajax({
			type: "POST",
			url: "?page=postcomment",
			dataType: "xml",
			data: dataString,
			success: function(xml) {
				var result = $(xml).find('result').text();
				if(result == 'success') {
					var user = $(xml).find('user').text();
					var userid = $(xml).find('userid').text();
					var rating = $(xml).find('rating').text();
					var text = $(xml).find('body').text();
					var useridurl = 'http://'+window.location.hostname+window.location.pathname+'?search[tree]=&search[type]=UserID&search[text]='+userid;

					var data = "
  Gepost door "+user+" ("+userid+") @ just now
"+text+"
";

					$("li.nocomments").remove();
					$("li.firstComment").removeClass("firstComment");
					$("li.addComment").after(data).next().hide().addClass("firstComment").fadeIn(function(){
						$("#commentslist > li").removeClass("even");
						$("#commentslist > li:nth-child(even)").addClass('even');
						$("span.commentcount").html('# '+$("#commentslist").children().not(".addComment").size());
					});
				}
			},
			error: function(xml) {
				console.log('error: '+((new XMLSerializer()).serializeToString(xml)));
			}
		});

		this.rpHashcashCalculated = function (self, hash) {
			self.reportForm['postreportform[newmessageid]'].value = hash;
			self.reportForm['postreportform[submit]'].value = 'Post';
			self.uiDone();

			var dataString2 = $(self.reportForm).serialize()

			$.ajax({
				type: "POST",
				url: "?page=reportpost",
				dataType: "xml",
				data: dataString2,
				success: function(xml) {
					var result = $(xml).find('result').text();
					if(result == 'success') {
						var user = $(xml).find('user').text();
						var userid = $(xml).find('userid').text();
						var text = $(xml).find('body').text();
						var useridurl = 'http://'+window.location.hostname+window.location.pathname+'?search[tree]=&search[type]=UserID&search[text]='+userid;
					}
				},
				error: function(xml) {
					console.log('error: '+((new XMLSerializer()).serializeToString(xml)));
				}
			});

	} // callback

	this.postComment = function(commentForm, uiStart, uiDone) {
		this.commentForm = commentForm;
		this.uiStart = uiStart;
		this.uiDone = uiDone;

		// update the UI
		this.uiStart();

		// First retrieve some values from the form we are submitting
		var randomstr = commentForm['postcommentform[randomstr]'].value;
		var rating = commentForm['postcommentform[rating]'].value;

		// inreplyto is the whole messageid, we strip off the @ part to add
		// our own stuff
		var inreplyto = commentForm['postcommentform[inreplyto]'].value;
		inreplyto = inreplyto.substring(0, inreplyto.indexOf('@'));

		/* Nu vragen we om, asynchroon, een hashcash te berekenen. Zie comments van calculateCommentHashCash()
		   waarom dit asynhcroon verloopt */
		this.calculateCommentHashCash('<' + inreplyto + '.' + rating + '.' + randomstr, '@spot.net>', 0, this.cbHashcashCalculated);
	} // postComment

	this.postReport = function(reportForm) {
		this.reportForm = reportForm;
		this.uiStart = uiStart;
		this.uiDone = uiDone;

		this.uiStart();

		var randomstr = reportForm['postreportform[randomstr]'].value;

		var inreplyto = reportForm['postreportform[inreplyto]'].value;
		inreplyto = inreplyto.substring(0, inreplyto.indexOf('@'));

		this.calculateCommentHashCash('<' + inreplyto + '.' + randomstr, '@spot.net>', 0, this.rpHashcashCalculated);
	} // postReport

	//
	// We breken de make expensive hash op in stukken omdat
	// anders IE8 gaat zeuren over scripts die te lang lopen.
	//
	this.calculateCommentHashCash = function(prefix, suffix, runCount, cbWhenFound) {
		var possibleChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
		var hash = prefix + suffix;
		var validHash = false;

		do {
			runCount++;
			uniquePart = '';

			for(i = 0; i < 15; i++) {
				var irand = Math.round(Math.random() * (possibleChars.length - 1));
				uniquePart += possibleChars.charAt(irand);
			} // for

			hash = $.sha1(prefix + '.' + uniquePart + suffix);
			validHash = (hash.substr(0, 4) == '0000');
		} while ((!validHash) && ((runCount % 500) != 0));

		if (validHash) {
			cbWhenFound(this, prefix + '.' + uniquePart + suffix);
		} else {
			if (runCount > 400000) {
				alert("Unable to calculate SHA1 hash: " + runCount);
				cbWhenFound(this, '');
			} else {
				var _this = this;
				window.setTimeout(function() { _this.calculateCommentHashCash(prefix, suffix, runCount, cbWhenFound); }, 0);
			} // else
		} // if

	} // calculateCommentHashCash
};
<commit_msg>fixed javascript. bedankt spotweb.<commit_after>function spotPosting() {
	this.commentForm = null;
	this.uiStart = null;
	this.uiDone = null;

	this.cbHashcashCalculated = function (self, hash) {
	    self.commentForm['postcommentform[newmessageid]'].value = hash;
	    self.commentForm['postcommentform[submit]'].value = 'Post';
		self.uiDone();

		// convert the processed form to post values
		var dataString = $(self.commentForm).serialize()

		// and actually process the call
		$.ajax({
			type: "POST",
			url: "?page=postcomment",
			dataType: "xml",
			data: dataString,
			success: function(xml) {
				var result = $(xml).find('result').text();
				if(result == 'success') {
					var user = $(xml).find('user').text();
					var userid = $(xml).find('userid').text();
					var rating = $(xml).find('rating').text();
					var text = $(xml).find('body').text();
					var useridurl = 'http://'+window.location.hostname+window.location.pathname+'?search[tree]=&search[type]=UserID&search[text]='+userid;

					var data = "
  Gepost door "+user+" ("+userid+") @ just now
"+text+"
";

					$("li.nocomments").remove();
					$("li.firstComment").removeClass("firstComment");
					$("li.addComment").after(data).next().hide().addClass("firstComment").fadeIn(function(){
						$("#commentslist > li").removeClass("even");
						$("#commentslist > li:nth-child(even)").addClass('even');
						$("span.commentcount").html('# '+$("#commentslist").children().not(".addComment").size());
					});
				}
			},
			error: function(xml) {
				console.log('error: '+((new XMLSerializer()).serializeToString(xml)));
			}
		});
	} // cbHashcashCalculated

	this.rpHashcashCalculated = function (self, hash) {
			self.reportForm['postreportform[newmessageid]'].value = hash;
			self.reportForm['postreportform[submit]'].value = 'Post';
			self.uiDone();

			var dataString2 = $(self.reportForm).serialize()

			$.ajax({
				type: "POST",
				url: "?page=reportpost",
				dataType: "xml",
				data: dataString2,
				success: function(xml) {
			alert(((new XMLSerializer()).serializeToString(xml)));
					var result = $(xml).find('result').text();
					if(result == 'success') {
						var user = $(xml).find('user').text();
						var userid = $(xml).find('userid').text();
						var text = $(xml).find('body').text();
						var useridurl = 'http://'+window.location.hostname+window.location.pathname+'?search[tree]=&search[type]=UserID&search[text]='+userid;
					} else {
					console.log('error: '+((new XMLSerializer()).serializeToString(xml)));
					} // else
				},
				error: function(xml) {
					console.log('error: '+((new XMLSerializer()).serializeToString(xml)));
				}
			});
	} // callback rpHashcashCalculated

	this.postComment = function(commentForm, uiStart, uiDone) {
		this.commentForm = commentForm;
		this.uiStart = uiStart;
		this.uiDone = uiDone;

		// update the UI
		this.uiStart();

		// First retrieve some values from the form we are submitting
		var randomstr = commentForm['postcommentform[randomstr]'].value;
		var rating = commentForm['postcommentform[rating]'].value;

		// inreplyto is the whole messageid, we strip off the @ part to add
		// our own stuff
		var inreplyto = commentForm['postcommentform[inreplyto]'].value;
		inreplyto = inreplyto.substring(0, inreplyto.indexOf('@'));

		/* Nu vragen we om, asynchroon, een hashcash te berekenen. Zie comments van calculateCommentHashCash()
		   waarom dit asynhcroon verloopt */
		this.calculateCommentHashCash('<' + inreplyto + '.' + rating + '.' + randomstr + '.', '@spot.net>', 0, this.cbHashcashCalculated);
	} // postComment

	this.postReport = function(reportForm, uiStart, uiDone) {
		this.reportForm = reportForm;
		this.uiStart = uiStart;
		this.uiDone = uiDone;

		this.uiStart();

		var randomstr = reportForm['postreportform[randomstr]'].value;

		var inreplyto = reportForm['postreportform[inreplyto]'].value;
		inreplyto = inreplyto.substring(0, inreplyto.indexOf('@'));

		this.calculateCommentHashCash('<' + inreplyto + '.' + randomstr + '.', '@spot.net>', 0, this.rpHashcashCalculated);
	} // postReport

	//
	// We breken de make expensive hash op in stukken omdat
	// anders IE8 gaat zeuren over scripts die te lang lopen.
	//
	this.calculateCommentHashCash = function(prefix, suffix, runCount, cbWhenFound) {
		var possibleChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
		var hash = prefix + suffix;
		var validHash = false;

		do {
			runCount++;
			uniquePart = '';

			for(i = 0; i < 15; i++) {
				var irand = Math.round(Math.random() * (possibleChars.length - 1));
				uniquePart += possibleChars.charAt(irand);
			} // for

			hash = $.sha1(prefix + uniquePart + suffix);
			validHash = (hash.substr(0, 4) == '0000');
		} while ((!validHash) && ((runCount % 500) != 0));

		if (validHash) {
			cbWhenFound(this, prefix + uniquePart + suffix);
		} else {
			if (runCount > 400000) {
				alert("Unable to calculate SHA1 hash: " + runCount);
				cbWhenFound(this, '');
			} else {
				var _this = this;
				window.setTimeout(function() { _this.calculateCommentHashCash(prefix, suffix, runCount, cbWhenFound); }, 0);
			} // else
		} // if

	} // calculateCommentHashCash
};
<|endoftext|>


<commit_before>function preguntas_graba()
	{
var error = '';
var especialidad=document.getElementById("especialidad").value;
var cantidad=document.getElementById("cantidad").value;
var tratados=document.getElementById("tratados").value;
//alert("preguntas ="+especialidad+'  '+cantidad+'  '+tratados);
if(	especialidad == 0){error = error + '
Falta seleccionar una especialidad.
'}
if(	cantidad == 0){error = error + '
Falta seleccionar una cantidad.
'}
if(	tratados == 0){error = error + '
Falta selecionar un porcentaje.
'}
if(error.length > 0){
document.getElementById("alertContent").innerHTML='
Te agradecemos respondas a las preguntas para descargar la App
'+error;
document.getElementById("openModal").click();
					return}
if(checkConnection()){
var especialidadHTML=document.getElementById("especialidad").options[especialidad].text;//options[this.selectedIndex].text
var cantidadHTML=document.getElementById("cantidad").options[cantidad].text;
var tratadosHTML=document.getElementById("tratados").options[tratados].text;
alert("especialidadHTML"+especialidadHTML+"--cantidadHTML"+cantidadHTML+"--tratadosHTML"+tratadosHTML);
return;
window.analytics.trackEvent('Prguntas Iniciales', 'Especialidad', especialidadHTML, 1);
window.analytics.trackEvent('Prguntas Iniciales', 'Cantidad de Pacientes con FA', cantidadHTML, 1);
window.analytics.trackEvent('Prguntas Iniciales', 'Porcentaje tratados con NACOs', tratadosHTML, 1);
var xmlhttp;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
	 // alert("xmlhttp.readyState:"+xmlhttp.readyState+"-- xmlhttp.status:"+xmlhttp.status);
	if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    value=parseInt(xmlhttp.responseText);
	window.localStorage.setItem("login", "true");
	//var value = window.localStorage.getItem("login");
	window.location="index_prologo.html";
	// ir a la pagina principal.

    }
  }
xmlhttp.open("POST","http://www.swci.com.ar/fibrilacion/preguntas_graba.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("especialidad="+especialidad+"&cantidad="+cantidad+"&tratados="+tratados);
}else{
	document.getElementById("openModal2").click();
}
}
function checkConnection() {
//var state = navigator.connection.type;
var state = navigator.connection.type;
if (state == window.Connection.NONE)
{
    // doesn't have internet, notify
	return false;
}
else
{
    // has internet, continue work accessing internet
	return true;
}
	/*return true;// Prueba interna*/
    //alert('Connection type: ' + states[networkState]);
}

<commit_msg>preguntas solve<commit_after>function preguntas_graba()
	{
var error = '';
var especialidad=document.getElementById("especialidad").value;
var cantidad=document.getElementById("cantidad").value;
var tratados=document.getElementById("tratados").value;
//alert("preguntas ="+especialidad+'  '+cantidad+'  '+tratados);
if(	especialidad == 0){error = error + '
Falta seleccionar una especialidad.
'}
if(	cantidad == 0){error = error + '
Falta seleccionar una cantidad.
'}
if(	tratados == 0){error = error + '
Falta selecionar un porcentaje.
'}
if(error.length > 0){
document.getElementById("alertContent").innerHTML='
Te agradecemos respondas a las preguntas para descargar la App
'+error;
document.getElementById("openModal").click();
					return}
if(checkConnection()){
var especialidadHTML=document.getElementById("especialidad").options[especialidad].text;//options[this.selectedIndex].text
var cantidadHTML=document.getElementById("cantidad").options[cantidad].text;
var tratadosHTML=document.getElementById("tratados").options[tratados].text;
window.analytics.trackEvent('Prguntas Iniciales', 'Especialidad', especialidadHTML, 1);
window.analytics.trackEvent('Prguntas Iniciales', 'Cantidad de Pacientes con FA', cantidadHTML, 1);
window.analytics.trackEvent('Prguntas Iniciales', 'Porcentaje tratados con NACOs', tratadosHTML, 1);
var xmlhttp;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
	 // alert("xmlhttp.readyState:"+xmlhttp.readyState+"-- xmlhttp.status:"+xmlhttp.status);
	if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    value=parseInt(xmlhttp.responseText);
	window.localStorage.setItem("login", "true");
	//var value = window.localStorage.getItem("login");
	window.location="index_prologo.html";
	// ir a la pagina principal.

    }
  }
xmlhttp.open("POST","http://www.swci.com.ar/fibrilacion/preguntas_graba.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("especialidad="+especialidad+"&cantidad="+cantidad+"&tratados="+tratados);
}else{
	document.getElementById("openModal2").click();
}
}
function checkConnection() {
//var state = navigator.connection.type;
var state = navigator.connection.type;
if (state == window.Connection.NONE)
{
    // doesn't have internet, notify
	return false;
}
else
{
    // has internet, continue work accessing internet
	return true;
}
	/*return true;// Prueba interna*/
    //alert('Connection type: ' + states[networkState]);
}

<|endoftext|>


<commit_before>function checkProgress() {
  	if (localStorage["progress"]) {
		var savedProgress = JSON.parse(localStorage["progress"]);
		for (var page in savedProgress) {
			if (savedProgress[page] > 0) {
				$("a[href='" + page + "']").addClass('done');
			}
		}
	}
	else {
		var progress = {};
		$(".page-link").each(function() {
			var pageLink = $(this).attr('href');
			progress[pageLink] = 0;
		});
		localStorage["progress"] = JSON.stringify(progress);
		}
};

$(window).scroll(function() {
	if($(window).scrollTop() + $(window).height() == $(document).height()) {
		updateProgress();
   }
});

function updateProgress() {
	var savedProgress = JSON.parse(localStorage["progress"]);
	var currentPage = window.location.pathname
	savedProgress[currentPage] = 1;
	localStorage["progress"] = JSON.stringify(savedProgress);
	$("a[href='" + currentPage + "']").addClass('done');
};

$(document).ready(function() {
	checkProgress();
});
<commit_msg>triggering done status before reaching bottom of page<commit_after>function checkProgress() {
  	if (localStorage["progress"]) {
		var savedProgress = JSON.parse(localStorage["progress"]);
		for (var page in savedProgress) {
			if (savedProgress[page] > 0) {
				$("a[href='" + page + "']").addClass('done');
			}
		}
	}
	else {
		var progress = {};
		$(".page-link").each(function() {
			var pageLink = $(this).attr('href');
			progress[pageLink] = 0;
		});
		localStorage["progress"] = JSON.stringify(progress);
		}
};

$(window).scroll(function() {
	// A page is done when the scroll reaches doc height - footer height
	var doneHeight = $(document).height() - $( "footer" ).height();
	if($(window).scrollTop() + $(window).height() >= doneHeight ) {
		updateProgress();
   }
});

function updateProgress() {
	var savedProgress = JSON.parse(localStorage["progress"]);
	var currentPage = window.location.pathname
	savedProgress[currentPage] = 1;
	localStorage["progress"] = JSON.stringify(savedProgress);
	$("a[href='" + currentPage + "']").addClass('done');
};

$(document).ready(function() {
	checkProgress();
});
<|endoftext|>


<commit_before>import Tag from '../common/models/Tag';
import addTagsPermissionScope from './addTagsPermissionScope';
import addTagPermission from './addTagPermission';
import addTagsPane from './addTagsPane';
import addTagsHomePageOption from './addTagsHomePageOption';
import addTagChangePermission from './addTagChangePermission';

app.initializers.add('flarum-tags', app => {
  app.store.models.tags = Tag;

  addTagsPermissionScope();
  addTagPermission();
  addTagsPane();
  addTagsHomePageOption();
  addTagChangePermission();
});
<commit_msg>Expose compat API on admin frontend<commit_after>import Tag from '../common/models/Tag';
import addTagsPermissionScope from './addTagsPermissionScope';
import addTagPermission from './addTagPermission';
import addTagsPane from './addTagsPane';
import addTagsHomePageOption from './addTagsHomePageOption';
import addTagChangePermission from './addTagChangePermission';

app.initializers.add('flarum-tags', app => {
  app.store.models.tags = Tag;

  addTagsPermissionScope();
  addTagPermission();
  addTagsPane();
  addTagsHomePageOption();
  addTagChangePermission();
});

// Expose compat API
import tagsCompat from './compat';
import { compat } from '@flarum/core/admin';

Object.assign(compat, tagsCompat);
<|endoftext|>