<commit_before>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import {
  IconChevronUpSmallOutline,
  IconChevronDownSmallOutline,
  IconWarningBadgedSmallFilled,
} from '@teamleader/ui-icons';
import Box, { omitBoxProps, pickBoxProps } from '../box';
import Button from '../button';
import { TextSmall } from '../typography';
import theme from './theme.css';

export default class Input extends PureComponent {
  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.value !== undefined) {
      const newValue = nextProps.value || '';

      if (newValue !== prevState.value) {
        return {
          value: newValue,
        };
      }
    }

    return null;
  }

  parseValue(value) {
    const { type } = this.props;
    return type === 'number' ? this.bindToMinMax(this.toNumber(value)) : value;
  }

  toNumber(number) {
    let float = parseFloat(number);

    if (isNaN(float) || !isFinite(float)) {
      float = 0;
    }

    return float;
  }

  bindToMinMax(value) {
    const { min, max } = this.props;
    return Math.min(Math.max(value, min), max);
  }

  state = {
    value: '',
  };

  handleBlur = event => {
    const { value } = this.state;
    const parsedValue = this.parseValue(value);

    if (parsedValue !== value) {
      this.updateValue(event, parsedValue);
    }

    if (this.props.onBlur) {
      this.props.onBlur();
    }
  };

  handleChange = event => {
    this.updateValue(event, event.target.value);
  };

  handleIncreaseValue = event => {
    this.updateStep(event, 1);
  };

  handleDecreaseValue = event => {
    this.updateStep(event, -1);
  };

  updateValue(event, rawValue, triggerOnChange = true) {
    const { onChange } = this.props;
    const newValue = String(rawValue);

    this.setState({
      value: newValue,
    });

    if (triggerOnChange && onChange) {
      onChange(event, newValue);
    }
  }

  updateStep(event, n) {
    const { step } = this.props;

    const currentValue = this.toNumber(this.state.value || 0);
    const newValue = this.parseValue(currentValue + step * n);

    if (newValue !== currentValue) {
      this.updateValue(event, newValue);
    }
  }

  renderInput() {
    const { bold, max, min, step, type, ...otherProps } = this.props;
    const { value } = this.state;

    const classNames = cx(theme['input'], {
      [theme['is-bold']]: bold,
    });

    const otherPropsWithoutBoxProps = omitBoxProps(otherProps);
    const restProps = omit(otherPropsWithoutBoxProps, [
      'className',
      'connectedLeft',
      'connectedRight',
      'helpText',
      'inverse',
      'onChange',
      'prefix',
      'size',
      'spinner',
      'suffix',
      'value',
    ]);

    const numberTypeProps = {
      max,
      min,
      step,
      value,
    };

    const props = {
      className: classNames,
      onBlur: this.handleBlur,
      onChange: this.handleChange,
      type,
      value,
      ...restProps,
      ...(type === 'number' && numberTypeProps),
    };

    return <input {...props} />;
  }

  renderHelpText() {
    const { helpText, inverse } = this.props;

    if (helpText) {
      return (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      );
    }
  }

  renderSpinnerControls() {
    const { disabled, readOnly, spinner, type } = this.props;

    const props = {
      disabled: disabled || readOnly,
    };

    if (type === 'number' && spinner) {
      return (

          <Button
            className={theme['spinner-up']}
            icon={<IconChevronUpSmallOutline />}
            onClick={this.handleIncreaseValue}
            {...props}
          />
          <Button
            className={theme['spinner-down']}
            icon={<IconChevronDownSmallOutline />}
            onClick={this.handleDecreaseValue}
            {...props}
          />

      );
    }
  }

  renderValidationMessage() {
    return (
      <TextSmall className={theme['validation-text']} marginTop={2} display="flex">
        <Box element="span" className={theme['validation-icon']}>
          <IconWarningBadgedSmallFilled />
        </Box>
        <Box element="span" marginLeft={1}>
          {this.props.error}
        </Box>
      </TextSmall>
    );
  }

  render() {
    const {
      className,
      connectedLeft,
      connectedRight,
      disabled,
      error,
      inverse,
      prefix,
      size,
      spinner,
      suffix,
      readOnly,
      type,
      ...others
    } = this.props;

    const classNames = cx(
      theme['wrapper'],
      theme[`is-${size}`],
      {
        [theme['has-error']]: error,
        [theme['has-connected-left']]: connectedLeft,
        [theme['has-connected-right']]: connectedRight,
        [theme['has-spinner']]: type === 'number' && spinner,
        [theme['is-inverse']]: inverse,
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const inputWrapperClassnames = cx(theme['input-wrapper'], {
      [theme['has-error']]: error,
    });

    const rest = pickBoxProps(others);

    return (
      <Box className={classNames} {...rest}>

          {connectedLeft}

{prefix}

            {this.renderInput()}

{suffix}

            {this.renderSpinnerControls()}

          {connectedRight}

        {error ? this.renderValidationMessage() : this.renderHelpText()}
      </Box>
    );
  }
}

Input.propTypes = {
  /** Boolean indicating whether the input text should render in bold. */
  bold: PropTypes.bool,
  /** Sets a class name for the wrapper to give custom styles. */
  className: PropTypes.string,
  connectedLeft: PropTypes.element,
  connectedRight: PropTypes.element,
  /** Boolean indicating whether the input should render as disabled. */
  disabled: PropTypes.bool,
  /** The text string/element to use as error message below the input. */
  error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** The text string to use as help text below the input. */
  helpText: PropTypes.string,
  /** Boolean indicating whether the input should render as inverse. */
  inverse: PropTypes.bool,
  max: PropTypes.number,
  min: PropTypes.number,
  /** Boolean indicating whether to number type input should render spinner controls */
  spinner: PropTypes.bool,
  /** Callback function that is fired when blurring the input field. */
  onBlur: PropTypes.func,
  /** Callback function that is fired when the component's value changes. */
  onChange: PropTypes.func,
  /** The text string/element to use as a prefix inside the input field */
  prefix: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** Boolean indicating whether the input should render as read only. */
  readOnly: PropTypes.bool,
  /** Size of the input element. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** Limit increment value for numeric inputs. */
  step: PropTypes.number,
  /** The text string/element to use as a suffix inside the input field */
  suffix: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** Type of the input element. It can be a valid HTML5 input type. */
  type: PropTypes.string,
  /** Current value of the input element. */
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};

Input.defaultProps = {
  inverse: false,
  disabled: false,
  min: Number.MIN_SAFE_INTEGER,
  max: Number.MAX_SAFE_INTEGER,
  readOnly: false,
  size: 'medium',
  spinner: true,
  step: 1,
};
<commit_msg>Adjust the prop types of prefix & suffix<commit_after>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import omit from 'lodash.omit';
import {
  IconChevronUpSmallOutline,
  IconChevronDownSmallOutline,
  IconWarningBadgedSmallFilled,
} from '@teamleader/ui-icons';
import Box, { omitBoxProps, pickBoxProps } from '../box';
import Button from '../button';
import { TextSmall } from '../typography';
import theme from './theme.css';

export default class Input extends PureComponent {
  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.value !== undefined) {
      const newValue = nextProps.value || '';

      if (newValue !== prevState.value) {
        return {
          value: newValue,
        };
      }
    }

    return null;
  }

  parseValue(value) {
    const { type } = this.props;
    return type === 'number' ? this.bindToMinMax(this.toNumber(value)) : value;
  }

  toNumber(number) {
    let float = parseFloat(number);

    if (isNaN(float) || !isFinite(float)) {
      float = 0;
    }

    return float;
  }

  bindToMinMax(value) {
    const { min, max } = this.props;
    return Math.min(Math.max(value, min), max);
  }

  state = {
    value: '',
  };

  handleBlur = event => {
    const { value } = this.state;
    const parsedValue = this.parseValue(value);

    if (parsedValue !== value) {
      this.updateValue(event, parsedValue);
    }

    if (this.props.onBlur) {
      this.props.onBlur();
    }
  };

  handleChange = event => {
    this.updateValue(event, event.target.value);
  };

  handleIncreaseValue = event => {
    this.updateStep(event, 1);
  };

  handleDecreaseValue = event => {
    this.updateStep(event, -1);
  };

  updateValue(event, rawValue, triggerOnChange = true) {
    const { onChange } = this.props;
    const newValue = String(rawValue);

    this.setState({
      value: newValue,
    });

    if (triggerOnChange && onChange) {
      onChange(event, newValue);
    }
  }

  updateStep(event, n) {
    const { step } = this.props;

    const currentValue = this.toNumber(this.state.value || 0);
    const newValue = this.parseValue(currentValue + step * n);

    if (newValue !== currentValue) {
      this.updateValue(event, newValue);
    }
  }

  renderInput() {
    const { bold, max, min, step, type, ...otherProps } = this.props;
    const { value } = this.state;

    const classNames = cx(theme['input'], {
      [theme['is-bold']]: bold,
    });

    const otherPropsWithoutBoxProps = omitBoxProps(otherProps);
    const restProps = omit(otherPropsWithoutBoxProps, [
      'className',
      'connectedLeft',
      'connectedRight',
      'helpText',
      'inverse',
      'onChange',
      'prefix',
      'size',
      'spinner',
      'suffix',
      'value',
    ]);

    const numberTypeProps = {
      max,
      min,
      step,
      value,
    };

    const props = {
      className: classNames,
      onBlur: this.handleBlur,
      onChange: this.handleChange,
      type,
      value,
      ...restProps,
      ...(type === 'number' && numberTypeProps),
    };

    return <input {...props} />;
  }

  renderHelpText() {
    const { helpText, inverse } = this.props;

    if (helpText) {
      return (
        <TextSmall color={inverse ? 'white' : 'neutral'} marginTop={1} soft>
          {helpText}
        </TextSmall>
      );
    }
  }

  renderSpinnerControls() {
    const { disabled, readOnly, spinner, type } = this.props;

    const props = {
      disabled: disabled || readOnly,
    };

    if (type === 'number' && spinner) {
      return (

          <Button
            className={theme['spinner-up']}
            icon={<IconChevronUpSmallOutline />}
            onClick={this.handleIncreaseValue}
            {...props}
          />
          <Button
            className={theme['spinner-down']}
            icon={<IconChevronDownSmallOutline />}
            onClick={this.handleDecreaseValue}
            {...props}
          />

      );
    }
  }

  renderValidationMessage() {
    return (
      <TextSmall className={theme['validation-text']} marginTop={2} display="flex">
        <Box element="span" className={theme['validation-icon']}>
          <IconWarningBadgedSmallFilled />
        </Box>
        <Box element="span" marginLeft={1}>
          {this.props.error}
        </Box>
      </TextSmall>
    );
  }

  render() {
    const {
      className,
      connectedLeft,
      connectedRight,
      disabled,
      error,
      inverse,
      prefix,
      size,
      spinner,
      suffix,
      readOnly,
      type,
      ...others
    } = this.props;

    const classNames = cx(
      theme['wrapper'],
      theme[`is-${size}`],
      {
        [theme['has-error']]: error,
        [theme['has-connected-left']]: connectedLeft,
        [theme['has-connected-right']]: connectedRight,
        [theme['has-spinner']]: type === 'number' && spinner,
        [theme['is-inverse']]: inverse,
        [theme['is-disabled']]: disabled,
        [theme['is-read-only']]: readOnly,
      },
      className,
    );

    const inputWrapperClassnames = cx(theme['input-wrapper'], {
      [theme['has-error']]: error,
    });

    const rest = pickBoxProps(others);

    return (
      <Box className={classNames} {...rest}>

          {connectedLeft}

{prefix}

            {this.renderInput()}

{suffix}

            {this.renderSpinnerControls()}

          {connectedRight}

        {error ? this.renderValidationMessage() : this.renderHelpText()}
      </Box>
    );
  }
}

Input.propTypes = {
  /** Boolean indicating whether the input text should render in bold. */
  bold: PropTypes.bool,
  /** Sets a class name for the wrapper to give custom styles. */
  className: PropTypes.string,
  connectedLeft: PropTypes.element,
  connectedRight: PropTypes.element,
  /** Boolean indicating whether the input should render as disabled. */
  disabled: PropTypes.bool,
  /** The text string/element to use as error message below the input. */
  error: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
  /** The text string to use as help text below the input. */
  helpText: PropTypes.string,
  /** Boolean indicating whether the input should render as inverse. */
  inverse: PropTypes.bool,
  max: PropTypes.number,
  min: PropTypes.number,
  /** Boolean indicating whether to number type input should render spinner controls */
  spinner: PropTypes.bool,
  /** Callback function that is fired when blurring the input field. */
  onBlur: PropTypes.func,
  /** Callback function that is fired when the component's value changes. */
  onChange: PropTypes.func,
  /** The text string/element to use as a prefix inside the input field */
  prefix: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
  /** Boolean indicating whether the input should render as read only. */
  readOnly: PropTypes.bool,
  /** Size of the input element. */
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  /** Limit increment value for numeric inputs. */
  step: PropTypes.number,
  /** The text string/element to use as a suffix inside the input field */
  suffix: PropTypes.oneOfType([PropTypes.array, PropTypes.element]),
  /** Type of the input element. It can be a valid HTML5 input type. */
  type: PropTypes.string,
  /** Current value of the input element. */
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};

Input.defaultProps = {
  inverse: false,
  disabled: false,
  min: Number.MIN_SAFE_INTEGER,
  max: Number.MAX_SAFE_INTEGER,
  readOnly: false,
  size: 'medium',
  spinner: true,
  step: 1,
};
<|endoftext|>


<commit_before>/**
 * @author Kai Salmen / www.kaisalmen.de
 */

'use strict';

var MeshSpray = (function () {

	var Validator = THREE.OBJLoader2.Validator;

	function MeshSpray() {
		this.wwMeshProvider = new THREE.OBJLoader2.WWMeshProvider();
		this.materials = [];
	}

	MeshSpray.prototype.prepareRun = function ( functionCodeBuilder, sceneGraphBaseNode, streamMeshes) {
		this.wwMeshProvider._validate( functionCodeBuilder );
		console.time( 'MeshSpray' );

		var scope = this;
		var scopeFuncComplete = function ( reason ) {
			scope._finalize( reason );
		};
		var scopeFuncAnnounce = function ( baseText, text ) {
			console.log( baseText, text );
		};
		this.wwMeshProvider.setCallbacks( scopeFuncAnnounce, undefined, scopeFuncComplete );
		this.wwMeshProvider.prepareRun( sceneGraphBaseNode, streamMeshes );
		this.wwMeshProvider.postMessage( {
			cmd: 'init',
			debug: this.debug,
			materialPerSmoothingGroup: false
		} );
	};

	MeshSpray.prototype.run = function () {
		var materialNames = [];
		for ( var materialName in this.materials ) {
			materialNames.push( materialName );
		}
		this.wwMeshProvider.addMaterials( this.materials );
		this.wwMeshProvider.postMessage(
			{
				cmd: 'setMaterials',
				materialNames: materialNames
			}
		);

		this.wwMeshProvider.postMessage(
			{
				cmd: 'run',
				quantity: 1000,
				dimension: 500
			}
		);
	};

	MeshSpray.prototype._finalize = function () {
		this.wwMeshProvider._terminate();
		console.timeEnd( 'MeshSpray' );
	};

	MeshSpray.prototype._buildWebWorkerCode = function ( funcBuildObject, funcBuildSingelton, existingWorkerCode ) {
		var workerCode = existingWorkerCode;
		if ( Validator.isValid( workerCode ) ) return workerCode;

		console.time( 'buildWebWorkerCode' );
		var wwMeshSprayDef = (function () {

			function WWMeshSpray() {
				this.cmdState = 'created';
				this.debug = false;
				this.materialPerSmoothingGroup = false;
				this.materials = null;
				this.globalObjectCount = 0;
			}

			WWMeshSpray.prototype._finalize = function () {
				console.log( 'Global output object count: ' + this.globalObjectCount );
			};

			WWMeshSpray.prototype.init = function ( payload ) {
				this.cmdState = 'init';
				this.debug = payload.debug;
				this.materialPerSmoothingGroup = payload.materialPerSmoothingGroup;
			};

			WWMeshSpray.prototype.setMaterials = function ( payload ) {
				this.cmdState = 'setMaterials';
				this.materials = Validator.verifyInput( payload.materialNames, this.materials );
				this.materials = Validator.verifyInput( this.materials, { materials: [] } );
			};

			WWMeshSpray.prototype.run = function ( payload ) {
				this.cmdState = 'run';

				for ( var i = 0; i < payload.quantity; i++ ) {
					this.buildMesh( payload.dimension );
				}

				this.cmdState = 'complete';
				self.postMessage( {
					cmd: this.cmdState,
					msg: null
				} );
			};

			WWMeshSpray.prototype.buildMesh = function ( dimension ) {
				var absoluteVertexCount = 9;
				var absoluteColorCount = 0;
				var absoluteNormalCount = 0;
				var absoluteUvCount = 0;

				var vertexFA = new Float32Array( absoluteVertexCount );
				var colorFA = ( absoluteColorCount > 0 ) ? new Float32Array( absoluteColorCount ) : null;
				var normalFA = ( absoluteNormalCount > 0 ) ? new Float32Array( absoluteNormalCount ) : null;
				var uvFA = ( absoluteUvCount > 0 ) ? new Float32Array( absoluteUvCount ) : null;

				var materialDescription;
				var materialDescriptions = [];
				var materialGroups = [];

				materialDescription = {
					name: 'Gen' + this.globalObjectCount,
					flat: false,
					vertexColors: false,
					default: false
				};
				if ( this.materials[ materialDescription.name ] === null ) {

					materialDescription.default = true;
					console.warn( 'object_group "' + materialDescription.name + '" was defined without material! Assigning "defaultMaterial".' );

				}
				materialDescriptions.push( materialDescription );

				var vertices = [ 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.0, 1.0 ];
				for ( var i = 0; i < vertices.length; i++ ) {
					vertices[ i ] = vertices[ i ] * Math.random() * dimension;
				}
				vertexFA.set( vertices, 0 );

				if ( colorFA ) {

					colorFA.set( rawObjectDescription.colors, 0 );
					materialDescription.vertexColors = true;

				}

				if ( normalFA ) {

					normalFA.set( rawObjectDescription.normals, 0 );

				}
				if ( uvFA ) {

					uvFA.set( rawObjectDescription.uvs, 0 );

				}

				self.postMessage(
					{
						cmd: 'objData',
						meshName: 'Gen' + this.globalObjectCount,
						multiMaterial: false,
						materialDescriptions: materialDescriptions,
						materialGroups: materialGroups,
						vertices: vertexFA,
						colors: colorFA,
						normals: normalFA,
						uvs: uvFA
					},
					[ vertexFA.buffer ],
					colorFA !== null ? [ colorFA.buffer ] : null,
					normalFA !== null ? [ normalFA.buffer ] : null,
					uvFA !== null ? [ uvFA.buffer ] : null
				);

				this.globalObjectCount++;
			};

			return WWMeshSpray;
		})();

		var wwMeshSprayRunnerDef = (function () {

			function WWMeshSprayRunner() {
				self.addEventListener( 'message', this.runner, false );
			}

			WWMeshSprayRunner.prototype.runner = function ( event ) {
				var payload = event.data;

				console.log( 'Command state before: ' + WWMeshSprayRef.cmdState );

				switch ( payload.cmd ) {
					case 'init':

						WWMeshSprayRef.init( payload );
						break;

					case 'setMaterials':

						WWMeshSprayRef.setMaterials( payload );
						break;

					case 'run':

						WWMeshSprayRef.run( payload );
						break;

					default:

						console.error( 'OBJLoader: Received unknown command: ' + payload.cmd );
						break;

				}

				console.log( 'Command state after: ' + WWMeshSprayRef.cmdState );
			};

			return WWMeshSprayRunner;
		})();

		workerCode = '';
		workerCode += '/**\n';
		workerCode += '  * This code was constructed by MeshSpray._buildWebWorkerCode\n';
		workerCode += '  */\n\n';

		// web worker construction
		workerCode += funcBuildObject( 'Validator', Validator );
		workerCode += funcBuildSingelton( 'WWMeshSpray', 'WWMeshSpray', wwMeshSprayDef );
		workerCode += 'WWMeshSprayRef = new WWMeshSpray();\n\n';
		workerCode += funcBuildSingelton( 'WWMeshSprayRunner', 'WWMeshSprayRunner', wwMeshSprayRunnerDef );
		workerCode += 'new WWMeshSprayRunner();\n\n';

		console.timeEnd( 'buildWebWorkerCode' );

		return workerCode;
	};

	return MeshSpray;

})();
<commit_msg>Generating 5*10^6 triangles 10^5 each by worker<commit_after>/**
 * @author Kai Salmen / www.kaisalmen.de
 */

'use strict';

var MeshSpray = (function () {

	var Validator = THREE.OBJLoader2.Validator;

	function MeshSpray() {
		this.wwMeshProvider = new THREE.OBJLoader2.WWMeshProvider();
		this.materials = [];
	}

	MeshSpray.prototype.prepareRun = function ( functionCodeBuilder, sceneGraphBaseNode, streamMeshes) {
		this.wwMeshProvider._validate( functionCodeBuilder );
		console.time( 'MeshSpray' );

		var scope = this;
		var scopeFuncComplete = function ( reason ) {
			scope._finalize( reason );
		};
		var scopeFuncAnnounce = function ( baseText, text ) {
			console.log( baseText, text );
		};
		this.wwMeshProvider.setCallbacks( scopeFuncAnnounce, undefined, scopeFuncComplete );
		this.wwMeshProvider.prepareRun( sceneGraphBaseNode, streamMeshes );
		this.wwMeshProvider.postMessage( {
			cmd: 'init',
			debug: this.debug,
			materialPerSmoothingGroup: false
		} );
	};

	MeshSpray.prototype.run = function () {
		var materialNames = [];
		for ( var materialName in this.materials ) {
			materialNames.push( materialName );
		}
		this.wwMeshProvider.addMaterials( this.materials );
		this.wwMeshProvider.postMessage(
			{
				cmd: 'setMaterials',
				materialNames: materialNames
			}
		);

		this.wwMeshProvider.postMessage(
			{
				cmd: 'run',
				quantity: 50,
				dimension: 10000
			}
		);
	};

	MeshSpray.prototype._finalize = function () {
		this.wwMeshProvider._terminate();
		console.timeEnd( 'MeshSpray' );
	};

	MeshSpray.prototype._buildWebWorkerCode = function ( funcBuildObject, funcBuildSingelton, existingWorkerCode ) {
		var workerCode = existingWorkerCode;
		if ( Validator.isValid( workerCode ) ) return workerCode;

		console.time( 'buildWebWorkerCode' );
		var wwMeshSprayDef = (function () {

			function WWMeshSpray() {
				this.cmdState = 'created';
				this.debug = false;
				this.materialPerSmoothingGroup = false;
				this.materials = null;
				this.globalObjectCount = 0;
			}

			WWMeshSpray.prototype._finalize = function () {
				console.log( 'Global output object count: ' + this.globalObjectCount );
			};

			WWMeshSpray.prototype.init = function ( payload ) {
				this.cmdState = 'init';
				this.debug = payload.debug;
				this.materialPerSmoothingGroup = payload.materialPerSmoothingGroup;
			};

			WWMeshSpray.prototype.setMaterials = function ( payload ) {
				this.cmdState = 'setMaterials';
				this.materials = Validator.verifyInput( payload.materialNames, this.materials );
				this.materials = Validator.verifyInput( this.materials, { materials: [] } );
			};

			WWMeshSpray.prototype.run = function ( payload ) {
				this.cmdState = 'run';

				for ( var i = 0; i < payload.quantity; i++ ) {
					this.buildMesh( payload.dimension );
				}

				this.cmdState = 'complete';
				self.postMessage( {
					cmd: this.cmdState,
					msg: null
				} );
			};

			WWMeshSpray.prototype.buildMesh = function ( dimension ) {
				var materialDescription;
				var materialDescriptions = [];
				var materialGroups = [];

				materialDescription = {
					name: 'Gen' + this.globalObjectCount,
					flat: false,
					vertexColors: false,
					default: false
				};
				if ( this.materials[ materialDescription.name ] === null ) {

					materialDescription.default = true;
					console.warn( 'object_group "' + materialDescription.name + '" was defined without material! Assigning "defaultMaterial".' );

				}
				materialDescriptions.push( materialDescription );

				var baseTriangle = [ 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.0, 1.0 ];
				var vertices = [];
				var colors = [];
				var normals = [];
				var uvs = [];

				var dimensionHalf = dimension / 2;
				var fixedOffsetX;
				var fixedOffsetY;
				var fixedOffsetZ;
				// complete triagle
				var sizeVaring = 25 * Math.random();
				// local coords offset
				var localOffsetFactor = 25;

				for ( var i = 0; i < 100000; i++ ) {
					sizeVaring = 25 * Math.random();
					fixedOffsetX = dimension * Math.random() - dimensionHalf;
					fixedOffsetY = dimension * Math.random() - dimensionHalf;
					fixedOffsetZ = dimension * Math.random() - dimensionHalf;
					for ( var j = 0; j < baseTriangle.length; j += 3 ) {
						vertices.push( baseTriangle[ j ] * sizeVaring + localOffsetFactor * Math.random() + fixedOffsetX );
						vertices.push( baseTriangle[ j + 1 ] * sizeVaring + localOffsetFactor * Math.random() + fixedOffsetY );
						vertices.push( baseTriangle[ j + 2 ] * sizeVaring + localOffsetFactor * Math.random() + fixedOffsetZ );
						colors.push( Math.random() );
						colors.push( Math.random() );
						colors.push( Math.random() );
					}
				}

				var absoluteVertexCount = vertices.length;
				var absoluteColorCount = colors.length;
				var absoluteNormalCount = 0;
				var absoluteUvCount = 0;

				var vertexFA = new Float32Array( absoluteVertexCount );
				var colorFA = ( absoluteColorCount > 0 ) ? new Float32Array( absoluteColorCount ) : null;
				var normalFA = ( absoluteNormalCount > 0 ) ? new Float32Array( absoluteNormalCount ) : null;
				var uvFA = ( absoluteUvCount > 0 ) ? new Float32Array( absoluteUvCount ) : null;

				vertexFA.set( vertices, 0 );
				colorFA.set( colors, 0 );

				if ( colorFA ) {

					colorFA.set( colors, 0 );
					materialDescription.vertexColors = true;

				}

				if ( normalFA ) {

					normalFA.set( normals, 0 );

				}
				if ( uvFA ) {

					uvFA.set( uvs, 0 );

				}

				self.postMessage(
					{
						cmd: 'objData',
						meshName: 'Gen' + this.globalObjectCount,
						multiMaterial: false,
						materialDescriptions: materialDescriptions,
						materialGroups: materialGroups,
						vertices: vertexFA,
						colors: colorFA,
						normals: normalFA,
						uvs: uvFA
					},
					[ vertexFA.buffer ],
					colorFA !== null ? [ colorFA.buffer ] : null,
					normalFA !== null ? [ normalFA.buffer ] : null,
					uvFA !== null ? [ uvFA.buffer ] : null
				);

				this.globalObjectCount++;
			};

			return WWMeshSpray;
		})();

		var wwMeshSprayRunnerDef = (function () {

			function WWMeshSprayRunner() {
				self.addEventListener( 'message', this.runner, false );
			}

			WWMeshSprayRunner.prototype.runner = function ( event ) {
				var payload = event.data;

				console.log( 'Command state before: ' + WWMeshSprayRef.cmdState );

				switch ( payload.cmd ) {
					case 'init':

						WWMeshSprayRef.init( payload );
						break;

					case 'setMaterials':

						WWMeshSprayRef.setMaterials( payload );
						break;

					case 'run':

						WWMeshSprayRef.run( payload );
						break;

					default:

						console.error( 'OBJLoader: Received unknown command: ' + payload.cmd );
						break;

				}

				console.log( 'Command state after: ' + WWMeshSprayRef.cmdState );
			};

			return WWMeshSprayRunner;
		})();

		workerCode = '';
		workerCode += '/**\n';
		workerCode += '  * This code was constructed by MeshSpray._buildWebWorkerCode\n';
		workerCode += '  */\n\n';

		// web worker construction
		workerCode += funcBuildObject( 'Validator', Validator );
		workerCode += funcBuildSingelton( 'WWMeshSpray', 'WWMeshSpray', wwMeshSprayDef );
		workerCode += 'WWMeshSprayRef = new WWMeshSpray();\n\n';
		workerCode += funcBuildSingelton( 'WWMeshSprayRunner', 'WWMeshSprayRunner', wwMeshSprayRunnerDef );
		workerCode += 'new WWMeshSprayRunner();\n\n';

		console.timeEnd( 'buildWebWorkerCode' );

		return workerCode;
	};

	return MeshSpray;

})();
<|endoftext|>


<commit_before>/**
 * @namespace hs.query
 * @memberOf hs
 */
define(['angular', 'ol', 'map', 'core', 'angular-sanitize'],

    function(angular, ol) {
        angular.module('hs.query', ['hs.map', 'hs.core', 'ngSanitize'])
            .directive('hs.query.directiveInfopanel', ['config', function(config) {
                return {
                    templateUrl: config.infopanel_template || hsl_path + 'components/query/partials/infopanel.html?bust=' + gitsha
                };
            }])
            .directive('hs.query.infovalue', ['$compile', function($compile) {

                function link(scope, element, attrs) {
                    if (attrs.attribute == 'hstemplate') return;
                    if (attrs.template) {
                        var el = angular.element('');
                        el.attr({
                            attribute: attrs.attribute,
                            value: attrs.value
                        });
                        element.append(el);
                        $compile(el)(scope);
                    } else {
                        if (attrs.value) {
                            if (attrs.value.indexOf('http') == 0) {
                                var el = angular.element('');
                                el.attr({
                                    target: '_blank',
                                    href: attrs.value
                                });
                                el.html(attrs.value);
                                element.html(el);
                            } else {
                                element.html(attrs.value);
                            }
                        } else {
                            element.html(attrs.attribute);
                        }
                    }
                }

                return {
                    link: link
                };
            }])
            .service('hs.query.service_getwmsfeatureinfo', ['hs.utils.service',
                function(utils) {
                    this.request = function(url, info_format, coordinate) {
                        var req_url = utils.proxify(url);
                        var me = this;
                        $.ajax({
                            url: req_url,
                            cache: false,
                            success: function(response) {
                                me.featureInfoReceived(response, info_format, url, coordinate)
                            }
                        });
                    };

                }
            ]).service("hs.query.service_infopanel", ['$rootScope',
                function($rootScope) {
                    var me = {
                        //Used for tool specific info, such as lodexplorer region names and values
                        attributes: [],
                        //Used for getfeatureinfo. There exists a seperate group for each feature which is found at the specific coordinates
                        groups: [],
                        setAttributes: function(j) {
                            me.attributes = j;
                            $rootScope.$broadcast('infopanel.updated');
                        },
                        setGroups: function(j) {
                            me.groups = j;
                            $rootScope.$broadcast('infopanel.updated');
                        }
                    };

                    return me;
                }
            ])

        .controller('hs.query.controller', ['$scope', 'hs.map.service', 'hs.query.service_getwmsfeatureinfo', 'hs.query.service_infopanel', 'Core', '$sce',
            function($scope, OlMap, WmsGetFeatureInfo, InfoPanelService, Core, $sce) {
                var map = OlMap.map;
                var point_clicked = new ol.geom.Point([0, 0]);
                var lyr = null;

                //For vector layers use this to get the selected features
                var selector = new ol.interaction.Select({
                    condition: ol.events.condition.click
                });

                var vectors_selected = false;
                selector.getFeatures().on('add', function(e) {
                    //if (e.element.getKeys().length == 1) e.target.remove(e.element);
                    InfoPanelService.groups = []; // We can do this, because collection add is called before singleclick event
                    if (Core.mainpanel == 'measure') return;
                    $scope.$emit('infopanel.feature_selected', e.element, selector);
                    if (e.element.get('hs_notqueryable')) return;
                    getFeatureAttributes(e.element);
                });

                selector.getFeatures().on('remove', function(e) {
                    if (Core.mainpanel == 'measure') return;
                    InfoPanelService.setAttributes([]);
                    $scope.$emit('infopanel.feature_deselected', e.element);
                })

                var getFeatureAttributes = function(feature) {
                    var attributes = [];
                    var groups_added = false;
                    feature.getKeys().forEach(function(key) {
                        if (key == 'gid' || key == 'geometry') return;
                        if (key == "features") {
                            for (var sub_feature in feature.get('features')) {
                                var hstemplate = null;
                                if (feature.get('features')[sub_feature].get('hstemplate')) hstemplate = feature.get('features')[sub_feature].get('hstemplate');
                                var group = {
                                    name: "Feature",
                                    attributes: [],
                                    hstemplate: hstemplate
                                };
                                feature.get('features')[sub_feature].getKeys().forEach(function(key) {
                                    if (key == 'gid' || key == 'geometry') return;
                                    if ((typeof feature.get('features')[sub_feature].get(key)).toLowerCase() == "string") {
                                        group.attributes.push({
                                            name: key,
                                            value: $sce.trustAsHtml(feature.get('features')[sub_feature].get(key))
                                        });
                                    } else {
                                        group.attributes.push({
                                            name: key,
                                            value: feature.get('features')[sub_feature].get(key)
                                        });
                                    }
                                })
                                groups_added = true;
                                InfoPanelService.groups.push(group);
                            }
                        } else {
                            var obj
                            if ((typeof feature.get(key)).toLowerCase() == "string") {
                                obj = {
                                    name: key,
                                    value: $sce.trustAsHtml(feature.get(key))
                                };
                            } else {
                                obj = {
                                    name: key,
                                    value: feature.get(key)
                                };
                            }
                            attributes.push(obj)
                        };
                    })
                    Core.setMainPanel("info");
                    InfoPanelService.setAttributes(attributes);
                    InfoPanelService.feature = feature;
                    if (groups_added) InfoPanelService.setGroups(InfoPanelService.groups);
                    vectors_selected = true;
                }

                WmsGetFeatureInfo.featureInfoReceived = function(response, info_format, url, coordinate) {
                    /* Maybe this will work in future OL versions
                     *
                     * var format = new ol.format.GML();
                     *  console.log(format.readFeatures(response, {}));
                     */

                    //                    var x2js = new X2JS();
                    //                  var json = x2js.xml_str2json(response);
                    var something_updated = false;
                    if (info_format.indexOf("xml") > 0 || info_format.indexOf("gml") > 0) {
                        $("featureMember", response).each(function() {
                            var feature = $(this)[0].firstChild;
                            var group = {
                                name: "Feature",
                                attributes: []
                            };

                            for (var attribute in feature.children) {
                                if (feature.children[attribute].childElementCount == 0) {
                                    group.attributes.push({
                                        "name": feature.children[attribute].localName,
                                        "value": feature.children[attribute].innerHTML
                                    });
                                    something_updated = true;
                                }
                            }
                            if (something_updated)
                                InfoPanelService.groups.push(group);
                        });
                        $("msGMLOutput", response).each(function() {
                            for (var layer_i in $(this)[0].children) {
                                var layer = $(this)[0].children[layer_i];
                                var layer_name = "";
                                if (typeof layer.children == 'undefined') continue;
                                for (var feature_i = 0; feature_i < layer.children.length; feature_i++) {
                                    var feature = layer.children[feature_i];
                                    if (feature.nodeName == "gml:name") {
                                        layer_name = feature.innerHTML;
                                    } else {
                                        var group = {
                                            name: layer_name + " Feature",
                                            attributes: []
                                        };

                                        for (var attribute in feature.children) {
                                            if (feature.children[attribute].childElementCount == 0) {
                                                group.attributes.push({
                                                    "name": feature.children[attribute].localName,
                                                    "value": feature.children[attribute].innerHTML
                                                });
                                                something_updated = true;
                                            }
                                        }
                                        if (something_updated)
                                            InfoPanelService.groups.push(group);
                                    }

                                }
                            }
                        })
                        if (something_updated) {
                            InfoPanelService.setGroups(InfoPanelService.groups);
                            Core.setMainPanel("info");
                        }
                    }

                    if (info_format.indexOf("html") > 0) {
                        if (response.length <= 1) return;
                        fillIframeAndResize($("#invisible_popup"), response, true);
                        createFeatureInfoPopupIfNeeded(coordinate);
                        $(popup.getElement()).popover('show');
                        $(popup.getElement()).on('shown.bs.popover', function() {
                            fillIframeAndResize($('.getfeatureinfo_popup'), $("#invisible_popup").contents().find('body').html(), false);
                            $('.close', popup.getElement().nextElementSibling).click(function() {
                                $(popup.getElement()).popover('hide');
                            });
                            popup.setPosition(coordinate);
                            panIntoView(coordinate);
                        })
                    }
                }

                function fillIframeAndResize($iframe, response, append) {
                    if (append)
                        $iframe.contents().find('body').append(response);
                    else
                        $iframe.contents().find('body').html(response);
                    var tmp_width = $iframe.contents().innerWidth();
                    if (tmp_width > 700) tmp_width = 700;
                    $iframe.width(tmp_width + 20);
                    if ($iframe.width() == 20) $iframe.width(270);
                    var tmp_height = $iframe.contents().innerHeight();
                    if (tmp_height > 700) tmp_height = 700;
                    $iframe.height(tmp_height + 20);
                }

                var popup = null;

                function createFeatureInfoPopupIfNeeded(coordinate) {
                    if ($('.getfeatureinfo_popup').length > 0) {
                        $(popup.getElement()).popover('destroy');
                        OlMap.map.removeOverlay(popup);
                    }
                    var pop_div = document.createElement('div');
                    var element, content;
                    var width = $("#invisible_popup").width();
                    var height = $("#invisible_popup").height();
                    var close_button = '<button type="button" class="close">×Close</button>';

                    document.getElementsByTagName('body')[0].appendChild(pop_div);
                    popup = new ol.Overlay({
                        element: pop_div,
                        positioning: 'bottom-center'
                    });
                    element = popup.getElement();
                    OlMap.map.addOverlay(popup);
                    content = close_button + '';
                    $(element).popover({
                        'placement': 'top',
                        'animation': true,
                        'html': true,
                        'content': content
                    });
                    $(element).popover('show');
                    popup.setPosition(coordinate);
                }

                function panIntoView(coord) {
                    var popSize = {
                            width: $("#invisible_popup").width() + 40,
                            height: $("#invisible_popup").height() + 70
                        },
                        mapSize = OlMap.map.getSize();

                    var tailHeight = 20,
                        tailOffsetLeft = 60,
                        tailOffsetRight = popSize.width - tailOffsetLeft,
                        popOffset = popup.getOffset(),
                        popPx = OlMap.map.getPixelFromCoordinate(coord);

                    var fromLeft = (popPx[0] - tailOffsetLeft),
                        fromRight = mapSize[0] - (popPx[0] + tailOffsetRight);

                    var fromTop = popPx[1] - popSize.height + popOffset[1],
                        fromBottom = mapSize[1] - (popPx[1] + tailHeight) - popOffset[1];

                    var center = OlMap.map.getView().getCenter(),
                        curPx = OlMap.map.getPixelFromCoordinate(center),
                        newPx = curPx.slice();

                    if (fromRight < 0) {
                        newPx[0] -= fromRight;
                    } else if (fromLeft < 0) {
                        newPx[0] += fromLeft;
                    }

                    if (fromTop < 0) {
                        newPx[1] += fromTop;
                    } else if (fromBottom < 0) {
                        newPx[1] -= fromBottom;
                    }

                    if (newPx[0] !== curPx[0] || newPx[1] !== curPx[1]) {
                        OlMap.map.getView().setCenter(OlMap.map.getCoordinateFromPixel(newPx));
                    }

                    return OlMap.map.getView().getCenter();

                };

                $scope.InfoPanelService = InfoPanelService;

                //Example: displayGroupWithAttributes({name: "My group", attributes: [{name:"foo", value:"bar"}]
                $scope.displayGroupWithAttributes = function(group) {
                    InfoPanelService.groups.push(group);
                    if (!$scope.$$phase) $scope.$digest();
                }

                $scope.showCoordinate = function(coordinate, clear) {
                    point_clicked.setCoordinates(coordinate, 'XY');
                    var groups = clear ? [] : InfoPanelService.groups;
                    groups.push({
                        name: "Coordinates",
                        attributes: [{
                            "name": "EPSG:4326",
                            "value": ol.coordinate.toStringHDMS(ol.proj.transform(coordinate, 'EPSG:3857', 'EPSG:4326'))
                        }, {
                            "name": "EPSG:3857",
                            "value": ol.coordinate.createStringXY(7)(coordinate)
                        }]
                    });
                    InfoPanelService.setGroups(groups);
                }

                var isLayerQueriable = function(layer) {
                    if (layer instanceof ol.layer.Tile &&
                        layer.getSource() instanceof ol.source.TileWMS &&
                        layer.getSource().getParams().INFO_FORMAT) return true;
                    if (layer instanceof ol.layer.Image &&
                        layer.getSource() instanceof ol.source.ImageWMS &&
                        layer.getSource().getParams().INFO_FORMAT) return true;
                    return false;
                }

                $scope.queryWmsLayer = function(layer, coordinate) {
                    if (isLayerQueriable(layer)) {
                        var source = layer.getSource();
                        var viewResolution = map.getView().getResolution();
                        var url = source.getGetFeatureInfoUrl(
                            coordinate, viewResolution, source.getProjection() ? source.getProjection() : map.getView().getProjection(), {
                                'INFO_FORMAT': source.getParams().INFO_FORMAT
                            });
                        if (url) {
                            if (console) console.log(url);
                            if (source.getParams().INFO_FORMAT.indexOf('xml') > 0 || source.getParams().INFO_FORMAT.indexOf('html') > 0 || source.getParams().INFO_FORMAT.indexOf('gml') > 0) {
                                WmsGetFeatureInfo.request(url, source.getParams().INFO_FORMAT, coordinate);
                            }
                        }
                    }
                }

                $scope.activateFeatureQueries = function() {
                    map.addInteraction(selector);
                }

                $scope.clearInfoPanel = function() {
                    InfoPanelService.attributes = [];
                    InfoPanelService.setGroups([]);
                }

                $scope.activateFeatureQueries();

                $scope.$on('infopanel.updated', function(event) {
                    if (!$scope.$$phase) $scope.$digest();
                });

                $scope.createCurrentPointLayer = function() {
                    if (lyr) map.getLayers().remove(lyr);
                    lyr = new ol.layer.Vector({
                        title: "Point clicked",
                        source: new ol.source.Vector({
                            features: [new ol.Feature({
                                geometry: point_clicked
                            })]
                        }),
                        show_in_manager: false
                    });
                    map.addLayer(lyr);
                }

                $scope.$on('layermanager.updated', function(event, data) {
                    if (data == lyr) return; //Otherwise stack overflow
                    $scope.createCurrentPointLayer();
                });

                $scope.createCurrentPointLayer();

                //For wms layers use this to get the features at mouse coordinates
                map.on('singleclick', function(evt) {
                    if (Core.mainpanel == 'measure') return;
                    if (['layermanager', '', 'permalink'].indexOf(Core.mainpanel) >= 0) Core.setMainPanel("info");
                    $("#invisible_popup").contents().find('body').html('');
                    $scope.showCoordinate(evt.coordinate, !vectors_selected); //Clear the previous content if no vector feature was selected, because otherwise it would already be cleared there
                    map.getLayers().forEach(function(layer) {
                        $scope.queryWmsLayer(layer, evt.coordinate)
                    });
                    $scope.$emit('map_clicked', evt);
                    vectors_selected = false;
                });
                $scope.$emit('scope_loaded', "Query");
            }
        ]);

    })
<commit_msg>shrink getfeatureinfo popup on click<commit_after>/**
 * @namespace hs.query
 * @memberOf hs
 */
define(['angular', 'ol', 'map', 'core', 'angular-sanitize'],

    function(angular, ol) {
        angular.module('hs.query', ['hs.map', 'hs.core', 'ngSanitize'])
            .directive('hs.query.directiveInfopanel', ['config', function(config) {
                return {
                    templateUrl: config.infopanel_template || hsl_path + 'components/query/partials/infopanel.html?bust=' + gitsha
                };
            }])
            .directive('hs.query.infovalue', ['$compile', function($compile) {

                function link(scope, element, attrs) {
                    if (attrs.attribute == 'hstemplate') return;
                    if (attrs.template) {
                        var el = angular.element('');
                        el.attr({
                            attribute: attrs.attribute,
                            value: attrs.value
                        });
                        element.append(el);
                        $compile(el)(scope);
                    } else {
                        if (attrs.value) {
                            if (attrs.value.indexOf('http') == 0) {
                                var el = angular.element('');
                                el.attr({
                                    target: '_blank',
                                    href: attrs.value
                                });
                                el.html(attrs.value);
                                element.html(el);
                            } else {
                                element.html(attrs.value);
                            }
                        } else {
                            element.html(attrs.attribute);
                        }
                    }
                }

                return {
                    link: link
                };
            }])
            .service('hs.query.service_getwmsfeatureinfo', ['hs.utils.service',
                function(utils) {
                    this.request = function(url, info_format, coordinate) {
                        var req_url = utils.proxify(url);
                        var me = this;
                        $.ajax({
                            url: req_url,
                            cache: false,
                            success: function(response) {
                                me.featureInfoReceived(response, info_format, url, coordinate)
                            }
                        });
                    };

                }
            ]).service("hs.query.service_infopanel", ['$rootScope',
                function($rootScope) {
                    var me = {
                        //Used for tool specific info, such as lodexplorer region names and values
                        attributes: [],
                        //Used for getfeatureinfo. There exists a seperate group for each feature which is found at the specific coordinates
                        groups: [],
                        setAttributes: function(j) {
                            me.attributes = j;
                            $rootScope.$broadcast('infopanel.updated');
                        },
                        setGroups: function(j) {
                            me.groups = j;
                            $rootScope.$broadcast('infopanel.updated');
                        }
                    };

                    return me;
                }
            ])

        .controller('hs.query.controller', ['$scope', 'hs.map.service', 'hs.query.service_getwmsfeatureinfo', 'hs.query.service_infopanel', 'Core', '$sce',
            function($scope, OlMap, WmsGetFeatureInfo, InfoPanelService, Core, $sce) {
                var map = OlMap.map;
                var point_clicked = new ol.geom.Point([0, 0]);
                var lyr = null;

                //For vector layers use this to get the selected features
                var selector = new ol.interaction.Select({
                    condition: ol.events.condition.click
                });

                var vectors_selected = false;
                selector.getFeatures().on('add', function(e) {
                    //if (e.element.getKeys().length == 1) e.target.remove(e.element);
                    InfoPanelService.groups = []; // We can do this, because collection add is called before singleclick event
                    if (Core.mainpanel == 'measure') return;
                    $scope.$emit('infopanel.feature_selected', e.element, selector);
                    if (e.element.get('hs_notqueryable')) return;
                    getFeatureAttributes(e.element);
                });

                selector.getFeatures().on('remove', function(e) {
                    if (Core.mainpanel == 'measure') return;
                    InfoPanelService.setAttributes([]);
                    $scope.$emit('infopanel.feature_deselected', e.element);
                })

                var getFeatureAttributes = function(feature) {
                    var attributes = [];
                    var groups_added = false;
                    feature.getKeys().forEach(function(key) {
                        if (key == 'gid' || key == 'geometry') return;
                        if (key == "features") {
                            for (var sub_feature in feature.get('features')) {
                                var hstemplate = null;
                                if (feature.get('features')[sub_feature].get('hstemplate')) hstemplate = feature.get('features')[sub_feature].get('hstemplate');
                                var group = {
                                    name: "Feature",
                                    attributes: [],
                                    hstemplate: hstemplate
                                };
                                feature.get('features')[sub_feature].getKeys().forEach(function(key) {
                                    if (key == 'gid' || key == 'geometry') return;
                                    if ((typeof feature.get('features')[sub_feature].get(key)).toLowerCase() == "string") {
                                        group.attributes.push({
                                            name: key,
                                            value: $sce.trustAsHtml(feature.get('features')[sub_feature].get(key))
                                        });
                                    } else {
                                        group.attributes.push({
                                            name: key,
                                            value: feature.get('features')[sub_feature].get(key)
                                        });
                                    }
                                })
                                groups_added = true;
                                InfoPanelService.groups.push(group);
                            }
                        } else {
                            var obj
                            if ((typeof feature.get(key)).toLowerCase() == "string") {
                                obj = {
                                    name: key,
                                    value: $sce.trustAsHtml(feature.get(key))
                                };
                            } else {
                                obj = {
                                    name: key,
                                    value: feature.get(key)
                                };
                            }
                            attributes.push(obj)
                        };
                    })
                    Core.setMainPanel("info");
                    InfoPanelService.setAttributes(attributes);
                    InfoPanelService.feature = feature;
                    if (groups_added) InfoPanelService.setGroups(InfoPanelService.groups);
                    vectors_selected = true;
                }

                WmsGetFeatureInfo.featureInfoReceived = function(response, info_format, url, coordinate) {
                    /* Maybe this will work in future OL versions
                     *
                     * var format = new ol.format.GML();
                     *  console.log(format.readFeatures(response, {}));
                     */

                    //                    var x2js = new X2JS();
                    //                  var json = x2js.xml_str2json(response);
                    var something_updated = false;
                    if (info_format.indexOf("xml") > 0 || info_format.indexOf("gml") > 0) {
                        $("featureMember", response).each(function() {
                            var feature = $(this)[0].firstChild;
                            var group = {
                                name: "Feature",
                                attributes: []
                            };

                            for (var attribute in feature.children) {
                                if (feature.children[attribute].childElementCount == 0) {
                                    group.attributes.push({
                                        "name": feature.children[attribute].localName,
                                        "value": feature.children[attribute].innerHTML
                                    });
                                    something_updated = true;
                                }
                            }
                            if (something_updated)
                                InfoPanelService.groups.push(group);
                        });
                        $("msGMLOutput", response).each(function() {
                            for (var layer_i in $(this)[0].children) {
                                var layer = $(this)[0].children[layer_i];
                                var layer_name = "";
                                if (typeof layer.children == 'undefined') continue;
                                for (var feature_i = 0; feature_i < layer.children.length; feature_i++) {
                                    var feature = layer.children[feature_i];
                                    if (feature.nodeName == "gml:name") {
                                        layer_name = feature.innerHTML;
                                    } else {
                                        var group = {
                                            name: layer_name + " Feature",
                                            attributes: []
                                        };

                                        for (var attribute in feature.children) {
                                            if (feature.children[attribute].childElementCount == 0) {
                                                group.attributes.push({
                                                    "name": feature.children[attribute].localName,
                                                    "value": feature.children[attribute].innerHTML
                                                });
                                                something_updated = true;
                                            }
                                        }
                                        if (something_updated)
                                            InfoPanelService.groups.push(group);
                                    }

                                }
                            }
                        })
                        if (something_updated) {
                            InfoPanelService.setGroups(InfoPanelService.groups);
                            Core.setMainPanel("info");
                        }
                    }

                    if (info_format.indexOf("html") > 0) {
                        if (response.length <= 1) return;
                        fillIframeAndResize($("#invisible_popup"), response, true);
                        createFeatureInfoPopupIfNeeded(coordinate);
                        $(popup.getElement()).popover('show');
                        $(popup.getElement()).on('shown.bs.popover', function() {
                            fillIframeAndResize($('.getfeatureinfo_popup'), $("#invisible_popup").contents().find('body').html(), false);
                            $('.close', popup.getElement().nextElementSibling).click(function() {
                                $(popup.getElement()).popover('hide');
                            });
                            popup.setPosition(coordinate);
                            panIntoView(coordinate);
                        })
                    }
                }

                function fillIframeAndResize($iframe, response, append) {
                    if (append)
                        $iframe.contents().find('body').append(response);
                    else
                        $iframe.contents().find('body').html(response);
                    var tmp_width = $iframe.contents().innerWidth();
                    if (tmp_width > 700) tmp_width = 700;
                    $iframe.width(tmp_width + 20);
                    if ($iframe.width() == 20) $iframe.width(270);
                    var tmp_height = $iframe.contents().innerHeight();
                    if (tmp_height > 700) tmp_height = 700;
                    $iframe.height(tmp_height + 20);
                }

                var popup = null;

                function createFeatureInfoPopupIfNeeded(coordinate) {
                    if ($('.getfeatureinfo_popup').length > 0) {
                        $(popup.getElement()).popover('destroy');
                        OlMap.map.removeOverlay(popup);
                    }
                    var pop_div = document.createElement('div');
                    var element, content;
                    var width = $("#invisible_popup").width();
                    var height = $("#invisible_popup").height();
                    var close_button = '<button type="button" class="close">×Close</button>';

                    document.getElementsByTagName('body')[0].appendChild(pop_div);
                    popup = new ol.Overlay({
                        element: pop_div,
                        positioning: 'bottom-center'
                    });
                    element = popup.getElement();
                    OlMap.map.addOverlay(popup);
                    content = close_button + '';
                    $(element).popover({
                        'placement': 'top',
                        'animation': true,
                        'html': true,
                        'content': content
                    });
                    $(element).popover('show');
                    popup.setPosition(coordinate);
                }

                function panIntoView(coord) {
                    var popSize = {
                            width: $("#invisible_popup").width() + 40,
                            height: $("#invisible_popup").height() + 70
                        },
                        mapSize = OlMap.map.getSize();

                    var tailHeight = 20,
                        tailOffsetLeft = 60,
                        tailOffsetRight = popSize.width - tailOffsetLeft,
                        popOffset = popup.getOffset(),
                        popPx = OlMap.map.getPixelFromCoordinate(coord);

                    var fromLeft = (popPx[0] - tailOffsetLeft),
                        fromRight = mapSize[0] - (popPx[0] + tailOffsetRight);

                    var fromTop = popPx[1] - popSize.height + popOffset[1],
                        fromBottom = mapSize[1] - (popPx[1] + tailHeight) - popOffset[1];

                    var center = OlMap.map.getView().getCenter(),
                        curPx = OlMap.map.getPixelFromCoordinate(center),
                        newPx = curPx.slice();

                    if (fromRight < 0) {
                        newPx[0] -= fromRight;
                    } else if (fromLeft < 0) {
                        newPx[0] += fromLeft;
                    }

                    if (fromTop < 0) {
                        newPx[1] += fromTop;
                    } else if (fromBottom < 0) {
                        newPx[1] -= fromBottom;
                    }

                    if (newPx[0] !== curPx[0] || newPx[1] !== curPx[1]) {
                        OlMap.map.getView().setCenter(OlMap.map.getCoordinateFromPixel(newPx));
                    }

                    return OlMap.map.getView().getCenter();

                };

                $scope.InfoPanelService = InfoPanelService;

                //Example: displayGroupWithAttributes({name: "My group", attributes: [{name:"foo", value:"bar"}]
                $scope.displayGroupWithAttributes = function(group) {
                    InfoPanelService.groups.push(group);
                    if (!$scope.$$phase) $scope.$digest();
                }

                $scope.showCoordinate = function(coordinate, clear) {
                    point_clicked.setCoordinates(coordinate, 'XY');
                    var groups = clear ? [] : InfoPanelService.groups;
                    groups.push({
                        name: "Coordinates",
                        attributes: [{
                            "name": "EPSG:4326",
                            "value": ol.coordinate.toStringHDMS(ol.proj.transform(coordinate, 'EPSG:3857', 'EPSG:4326'))
                        }, {
                            "name": "EPSG:3857",
                            "value": ol.coordinate.createStringXY(7)(coordinate)
                        }]
                    });
                    InfoPanelService.setGroups(groups);
                }

                var isLayerQueriable = function(layer) {
                    if (layer instanceof ol.layer.Tile &&
                        layer.getSource() instanceof ol.source.TileWMS &&
                        layer.getSource().getParams().INFO_FORMAT) return true;
                    if (layer instanceof ol.layer.Image &&
                        layer.getSource() instanceof ol.source.ImageWMS &&
                        layer.getSource().getParams().INFO_FORMAT) return true;
                    return false;
                }

                $scope.queryWmsLayer = function(layer, coordinate) {
                    if (isLayerQueriable(layer)) {
                        var source = layer.getSource();
                        var viewResolution = map.getView().getResolution();
                        var url = source.getGetFeatureInfoUrl(
                            coordinate, viewResolution, source.getProjection() ? source.getProjection() : map.getView().getProjection(), {
                                'INFO_FORMAT': source.getParams().INFO_FORMAT
                            });
                        if (url) {
                            if (console) console.log(url);
                            if (source.getParams().INFO_FORMAT.indexOf('xml') > 0 || source.getParams().INFO_FORMAT.indexOf('html') > 0 || source.getParams().INFO_FORMAT.indexOf('gml') > 0) {
                                WmsGetFeatureInfo.request(url, source.getParams().INFO_FORMAT, coordinate);
                            }
                        }
                    }
                }

                $scope.activateFeatureQueries = function() {
                    map.addInteraction(selector);
                }

                $scope.clearInfoPanel = function() {
                    InfoPanelService.attributes = [];
                    InfoPanelService.setGroups([]);
                }

                $scope.activateFeatureQueries();

                $scope.$on('infopanel.updated', function(event) {
                    if (!$scope.$$phase) $scope.$digest();
                });

                $scope.createCurrentPointLayer = function() {
                    if (lyr) map.getLayers().remove(lyr);
                    lyr = new ol.layer.Vector({
                        title: "Point clicked",
                        source: new ol.source.Vector({
                            features: [new ol.Feature({
                                geometry: point_clicked
                            })]
                        }),
                        show_in_manager: false
                    });
                    map.addLayer(lyr);
                }

                $scope.$on('layermanager.updated', function(event, data) {
                    if (data == lyr) return; //Otherwise stack overflow
                    $scope.createCurrentPointLayer();
                });

                $scope.createCurrentPointLayer();

                //For wms layers use this to get the features at mouse coordinates
                map.on('singleclick', function(evt) {
                    if (Core.mainpanel == 'measure') return;
                    if (['layermanager', '', 'permalink'].indexOf(Core.mainpanel) >= 0) Core.setMainPanel("info");
                    $("#invisible_popup").contents().find('body').html('');
                    $("#invisible_popup").height(200).width(200);
                    $scope.showCoordinate(evt.coordinate, !vectors_selected); //Clear the previous content if no vector feature was selected, because otherwise it would already be cleared there
                    map.getLayers().forEach(function(layer) {
                        $scope.queryWmsLayer(layer, evt.coordinate)
                    });
                    $scope.$emit('map_clicked', evt);
                    vectors_selected = false;
                });
                $scope.$emit('scope_loaded', "Query");
            }
        ]);

    })
<|endoftext|>


<commit_before>const proxyquire = require('proxyquire').noCallThru();
const fs = require('fs');

const {
  match,
  pipe,
  map,
  slice,
  ap,
  concat,
  reduce,
  curry,
} = require('ramda');

const matchRequire = pipe(
  match(/require\(.*\)/g),
  map(slice(9, -2)),
);

const matchImport = pipe(
  match(/from.*'.*'/g),
  map(slice(6, -1)),
);

const getImports = pipe(
  v => [v],
  ap([
    matchImport,
    matchRequire,
  ]),
  reduce(concat, []),
);

const createMockObject = (mocks, imports) => mocks
  .map((mock) => {
    const importName = imports.find(importPath => mock.importMask.test(importPath)) || '';

    return {
      ...mock,
      importName,
    };
  })
  .filter(({ importName, importMask }) => importMask.test(importName))
  .reduce((acc, { importName, mock }) => ({
    ...acc,
    [importName]: mock,
  }), {});

const requireWithMocking = curry((mocks, absoluteFileName) => {
  const text = fs.readFileSync(absoluteFileName).toString();
  const imports = getImports(text);
  const mockObject = createMockObject(mocks, imports);

  return proxyquire(absoluteFileName, mockObject);
});

const loadMocksFile = (absoluteFileName) => {
  try {
    // eslint-disable-next-line global-require, import/no-dynamic-require
    return require(absoluteFileName);
  } catch (err) {
    return null;
  }
};

module.exports = {
  getImports,
  requireWithMocking,
  loadMocksFile,
};

<commit_msg>fix(mock-tools): fix mock objects composing<commit_after>const proxyquire = require('proxyquire').noCallThru();
const fs = require('fs');

const {
  match,
  pipe,
  map,
  slice,
  ap,
  concat,
  reduce,
  curry,
} = require('ramda');

const matchRequire = pipe(
  match(/require\(.*\)/g),
  map(slice(9, -2)),
);

const matchImport = pipe(
  match(/from.*'.*'/g),
  map(slice(6, -1)),
);

const getImports = pipe(
  v => [v],
  ap([
    matchImport,
    matchRequire,
  ]),
  reduce(concat, []),
);

const createMockObject = (mocks, imports) => imports
  .map((importName) => {
    const mock = mocks.find(({ importMask }) => importMask.test(importName));

    if (!mock) {
      return null;
    }

    return {
      ...mock,
      importName,
    };
  })
  .filter(Boolean)
  .reduce((acc, { importName, mock }) => ({
    ...acc,
    [importName]: mock,
  }), {});

const requireWithMocking = curry((mocks, absoluteFileName) => {
  const text = fs.readFileSync(absoluteFileName).toString();
  const imports = getImports(text);
  const mockObject = createMockObject(mocks, imports);

  return proxyquire(absoluteFileName, mockObject);
});

const loadMocksFile = (absoluteFileName) => {
  try {
    // eslint-disable-next-line global-require, import/no-dynamic-require
    return require(absoluteFileName);
  } catch (err) {
    return null;
  }
};

module.exports = {
  getImports,
  requireWithMocking,
  loadMocksFile,
};

<|endoftext|>


<commit_before>var logger = require('../common/logger')

var News = require('../models/news')
var Logistics = require('../models/logistics')
var Lecture = require('../models/lecture')
var Notice = require('../models/notice')

/**
 * 切换分类
 * @param {String} classify 分类标签
 * @param {String} fn 执行操作
 * @param {*} res 响应回掉
 */
function switchClassify (classify, fn, res) {
  switch (classify) {
    case 'news':
      fn(News)
      break
    case 'logistics':
      fn(Logistics)
      break
    case 'lecture':
      fn(Lecture)
      break
    case 'notice':
      fn(Notice)
      break
    default:
      res.status(404).json({
        statusCode: 404,
        errMsg: '未找到'
      })
  }
}

/**
 * 新闻聚合
 */
exports.news = function (req, res, next) {
  var classify = req.params.classify
  var query = req.query

  if (!classify) {
    return res.status(400).json({
      statusCode: 400,
      errMsg: '格式错误'
    })
  }

  /**
   * 查询数据库获取新闻
   * @param {String} classify 分类
   */
  function getNews (classify) {
    classify
      .find({})
      .skip(parseInt(query.start))
      .limit(parseInt(query.count))
      .then(doc => {
        if (doc && doc.length) {
          var data = {
            id: doc._id,
            title: doc.title,
            time: doc.time,
            tag: doc.tag
          }

          return res.status(200).json({
            statusCode: 200,
            errMsg: '获取新闻成功',
            data: data
          })
        } else {
          return res.status(404).json({
            statusCode: 404,
            errMsg: '获取新闻失败'
          })
        }
      })
      .catch(err => {
        logger.error('获取新闻失败', err)

        return res.status(500).json({
          statusCode: 500,
          errMsg: '内部错误'
        })
      })
  }

  switchClassify(classify, getNews, res)
}

/**
 * 文章详情
 */
exports.newsDetail = function (req, res, next) {
  var classify = req.params.classify
  var id = req.params.id

  if (!classify || !id) {
    return res.status(400).json({
      statusCode: 400,
      errMsg: '格式错误'
    })
  }

  function getNews (classify) {
    classify
      .findById(id)
      .then(doc => {
        if (doc && doc.length) {
          var data = {
            title: doc.title,
            time: doc.time,
            tag: doc.tag,
            content: doc.content
          }

          return res.status(200).json({
            statusCode: 200,
            errMsg: '获取新闻成功',
            data: data
          })
        } else {
          return res.status(404).json({
            statusCode: 404,
            errMsg: '获取新闻失败'
          })
        }
      })
      .catch(err => {
        logger.error('获取新闻失败', err)

        return res.status(500).json({
          statusCode: 500,
          errMsg: '内部错误'
        })
      })
  }

  switchClassify(classify, getNews, res)
}
<commit_msg>Hot fix: rss 返回指定字段<commit_after>var logger = require('../common/logger')

var News = require('../models/news')
var Logistics = require('../models/logistics')
var Lecture = require('../models/lecture')
var Notice = require('../models/notice')

/**
 * 切换分类
 * @param {String} classify 分类标签
 * @param {String} fn 执行操作
 * @param {*} res 响应回掉
 */
function switchClassify (classify, fn, res) {
  switch (classify) {
    case 'news':
      fn(News)
      break
    case 'logistics':
      fn(Logistics)
      break
    case 'lecture':
      fn(Lecture)
      break
    case 'notice':
      fn(Notice)
      break
    default:
      res.status(404).json({
        statusCode: 404,
        errMsg: '未找到'
      })
  }
}

/**
 * 新闻聚合
 */
exports.news = function (req, res, next) {
  var classify = req.params.classify
  var query = req.query

  if (!classify) {
    return res.status(400).json({
      statusCode: 400,
      errMsg: '格式错误'
    })
  }

  /**
   * 查询数据库获取新闻
   * @param {String} classify 分类
   */
  function getNews (classify) {
    classify
      .find({}, '_id title time tag')
      .skip(parseInt(query.start))
      .limit(parseInt(query.count))
      .then(doc => {
        if (doc && doc.length) {
          return res.status(200).json({
            statusCode: 200,
            errMsg: '获取新闻成功',
            data: doc
          })
        } else {
          return res.status(404).json({
            statusCode: 404,
            errMsg: '获取新闻失败'
          })
        }
      })
      .catch(err => {
        logger.error('获取新闻失败', err)

        return res.status(500).json({
          statusCode: 500,
          errMsg: '内部错误'
        })
      })
  }

  switchClassify(classify, getNews, res)
}

/**
 * 文章详情
 */
exports.newsDetail = function (req, res, next) {
  var classify = req.params.classify
  var id = req.params.id

  if (!classify || !id) {
    return res.status(400).json({
      statusCode: 400,
      errMsg: '格式错误'
    })
  }

  function getNews (classify) {
    classify
      .findById(id)
      .then(doc => {
        if (doc && doc.length) {
          var data = {
            title: doc.title,
            time: doc.time,
            tag: doc.tag,
            content: doc.content
          }

          return res.status(200).json({
            statusCode: 200,
            errMsg: '获取新闻成功',
            data: data
          })
        } else {
          return res.status(404).json({
            statusCode: 404,
            errMsg: '获取新闻失败'
          })
        }
      })
      .catch(err => {
        logger.error('获取新闻失败', err)

        return res.status(500).json({
          statusCode: 500,
          errMsg: '内部错误'
        })
      })
  }

  switchClassify(classify, getNews, res)
}
<|endoftext|>


<commit_before>'use strict';

let cli = require('heroku-cli-util');
let co = require('co');
let HerokuKafkaClusters = require('./clusters.js').HerokuKafkaClusters;
let columnify = require('columnify');
let _ = require('underscore');

function* kafkaInfo (context, heroku) {
  var infos = yield new HerokuKafkaClusters(heroku, process.env, context).info(context.args.CLUSTER);
  if (infos) {
    _.each(infos, function(info) {
      console.log('=== HEROKU_KAFKA');
      console.log(columnify(info.info, {showHeaders: false, preserveNewLines: true}));
      console.log();
    });
  } else {
    process.exit(1);
  }
}

module.exports = {
  topic: 'kafka',
  command: 'info',
  description: 'shows information about the state of your Heroku Kafka cluster',
  args: [
    {
      name: 'CLUSTER',
      optional: true
    }
  ],
  help: `
    Shows the state of your Heroku Kafka cluster.

    Examples:

    $ heroku kafka:info
    $ heroku kafka:info kafka-adjacent-1337
`,
  needsApp: true,
  needsAuth: true,
  run: cli.command(co.wrap(kafkaInfo))
};
<commit_msg>use attachment name in kafka:info if present<commit_after>'use strict';

let cli = require('heroku-cli-util');
let co = require('co');
let HerokuKafkaClusters = require('./clusters.js').HerokuKafkaClusters;
let columnify = require('columnify');
let _ = require('underscore');

function* kafkaInfo (context, heroku) {
  var infos = yield new HerokuKafkaClusters(heroku, process.env, context).info(context.args.CLUSTER);
  if (infos) {
    _.each(infos, function(info) {
      console.log('=== ' + (info.attachment_name || 'HEROKU_KAFKA'));
      console.log(columnify(info.info, {showHeaders: false, preserveNewLines: true}));
      console.log();
    });
  } else {
    process.exit(1);
  }
}

module.exports = {
  topic: 'kafka',
  command: 'info',
  description: 'shows information about the state of your Heroku Kafka cluster',
  args: [
    {
      name: 'CLUSTER',
      optional: true
    }
  ],
  help: `
    Shows the state of your Heroku Kafka cluster.

    Examples:

    $ heroku kafka:info
    $ heroku kafka:info kafka-adjacent-1337
`,
  needsApp: true,
  needsAuth: true,
  run: cli.command(co.wrap(kafkaInfo))
};
<|endoftext|>


<commit_before>"use strict";

function filterParams(pattern) {
	var first = new RegExp("\\\?" + pattern + "=[^&#]*&?");
	var rest = new RegExp("&" + pattern + "=[^&#]*", "g");

	return function(details) {

		var newUrl = details.url
			.replace(rest, "")
			.replace(first, "?");

		if (newUrl !== details.url) {
			return {redirectUrl: newUrl};
		}

		return {};
	}
}

var filters = [
	{
		urls: ["<all_urls>"],
		fn: filterParams("utm_(?:content|campaign|source|medium)")
	}
];

function event() {
	if (chrome.runtime.id === "deurchin@rahulg.io") {
		return chrome.webRequest.onBeforeSendHeaders;
	} else {
		return chrome.webRequest.onBeforeRequest;
	}
}

for (var idx = 0; idx < filters.length; idx++) {
	event().addListener(
		filters[idx].fn,
		{urls: filters[idx].urls},
		["blocking"]
	);
}
<commit_msg>filter: AliExpress A/B testing cruft<commit_after>"use strict";

function filterParams(pattern) {
	var first = new RegExp("\\\?" + pattern + "=[^&#]*&?");
	var rest = new RegExp("&" + pattern + "=[^&#]*", "g");

	return function(details) {

		var newUrl = details.url
			.replace(rest, "")
			.replace(first, "?");

		if (newUrl !== details.url) {
			return {redirectUrl: newUrl};
		}

		return {};
	}
}

var filters = [
	{
		urls: ["<all_urls>"],
		fn: filterParams("utm_(?:content|campaign|source|medium)")
	},
	{
		urls: ["*://*.aliexpress.com/*"],
		fn: filterParams("(?:ws_ab_test|btsid)")
	}
];

function event() {
	if (chrome.runtime.id === "deurchin@rahulg.io") {
		return chrome.webRequest.onBeforeSendHeaders;
	} else {
		return chrome.webRequest.onBeforeRequest;
	}
}

for (var idx = 0; idx < filters.length; idx++) {
	event().addListener(
		filters[idx].fn,
		{urls: filters[idx].urls},
		["blocking"]
	);
}
<|endoftext|>


<commit_before>import React from "react";
import PropTypes from "prop-types";
import { assign, omit, defaults, uniqueId, isObject } from "lodash";
import Portal from "../victory-portal/portal";
import Timer from "../victory-util/timer";

export default class VictoryContainer extends React.Component {
  static displayName = "VictoryContainer";
  static role = "container";
  static propTypes = {
    children: PropTypes.oneOfType([
      PropTypes.arrayOf(PropTypes.node),
      PropTypes.node
    ]),
    className: PropTypes.string,
    containerId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    desc: PropTypes.string,
    events: PropTypes.object,
    height: PropTypes.number,
    origin: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }),
    polar: PropTypes.bool,
    portalComponent: PropTypes.element,
    responsive: PropTypes.bool,
    style: PropTypes.object,
    theme: PropTypes.object,
    title: PropTypes.string,
    width: PropTypes.number
  }

  static defaultProps = {
    portalComponent: <Portal/>,
    responsive: true
  }

  static contextTypes = {
    getTimer: PropTypes.func
  }

  static childContextTypes = {
    portalUpdate: PropTypes.func,
    portalRegister: PropTypes.func,
    portalDeregister: PropTypes.func,
    getTimer: PropTypes.func
  }

  constructor(props) {
    super(props);
    this.getTimer = this.getTimer.bind(this);
    this.containerId = !(isObject(props) && typeof props.containerId === "undefined") ?
      uniqueId("victory-container-") : props.containerId;
  }

  getChildContext() {
    return {
      portalUpdate: this.portalUpdate,
      portalRegister: this.portalRegister,
      portalDeregister: this.portalDeregister,
      getTimer: this.getTimer
    };
  }

  componentWillMount() {
    this.savePortalRef = (portal) => {
      this.portalRef = portal;
      return portal;
    };
    this.portalUpdate = (key, el) => this.portalRef.portalUpdate(key, el);
    this.portalRegister = () => this.portalRef.portalRegister();
    this.portalDeregister = (key) => this.portalRef.portalDeregister(key);
  }

  componentWillUnmount() {
    if (!this.context.getTimer) {
      this.getTimer().stop();
    }
  }

  getTimer() {
    if (this.context.getTimer) {
      return this.context.getTimer();
    }
    if (!this.timer) {
      this.timer = new Timer();
    }
    return this.timer;
  }

  getIdForElement(elementName) {
    return `${this.containerId}-${elementName}`;
  }

  // overridden in custom containers
  getChildren(props) {
    return props.children;
  }

  renderContainer(props, svgProps, style) {
    const { title, desc, portalComponent, className, width, height } = props;
    const children = this.getChildren(props);
    const parentProps = defaults({ style, className }, svgProps);
    const percent = `${-height / width * 100}%`;
    return (

        <svg viewBox={parentProps.viewBox} style={{ width: "100%", height: "100%" }}>
          {children}
        </svg>
          {title ? <title id={this.getIdForElement("title")}>{title}</title> : null}
          {desc ? <desc id={this.getIdForElement("desc")}>{desc}</desc> : null}
        <foreignObject>

            <svg viewBox={parentProps.viewBox} style={{ width: "100%", height: "100%" }} overflow="visible">
              {React.cloneElement(portalComponent, { ref: this.savePortalRef })}
            </svg>

        </foreignObject>

    );
  }

  render() {
    const { width, height, responsive, events } = this.props;
    const style = responsive ? this.props.style : omit(this.props.style, ["height", "width"]);
    const touchStyle = defaults({}, style, { touchAction: "none" });
    const svgProps = assign(
      {
        width, height, role: "img",
        "aria-labelledby": `${this.getIdForElement("title")} ${this.getIdForElement("desc")}`,
        viewBox: responsive ? `0 0 ${width} ${height}` : undefined
      },
      events
    );
    return this.renderContainer(this.props, svgProps, touchStyle);
  }
}
<commit_msg>working but incorrectly positioned for responsive containers<commit_after>import React from "react";
import PropTypes from "prop-types";
import { assign, omit, defaults, uniqueId, isObject } from "lodash";
import Portal from "../victory-portal/portal";
import Timer from "../victory-util/timer";

export default class VictoryContainer extends React.Component {
  static displayName = "VictoryContainer";
  static role = "container";
  static propTypes = {
    children: PropTypes.oneOfType([
      PropTypes.arrayOf(PropTypes.node),
      PropTypes.node
    ]),
    className: PropTypes.string,
    containerId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    desc: PropTypes.string,
    events: PropTypes.object,
    height: PropTypes.number,
    origin: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }),
    polar: PropTypes.bool,
    portalComponent: PropTypes.element,
    responsive: PropTypes.bool,
    style: PropTypes.object,
    theme: PropTypes.object,
    title: PropTypes.string,
    width: PropTypes.number
  }

  static defaultProps = {
    portalComponent: <Portal/>,
    responsive: true
  }

  static contextTypes = {
    getTimer: PropTypes.func
  }

  static childContextTypes = {
    portalUpdate: PropTypes.func,
    portalRegister: PropTypes.func,
    portalDeregister: PropTypes.func,
    getTimer: PropTypes.func
  }

  constructor(props) {
    super(props);
    this.getTimer = this.getTimer.bind(this);
    this.containerId = !(isObject(props) && typeof props.containerId === "undefined") ?
      uniqueId("victory-container-") : props.containerId;
  }

  getChildContext() {
    return {
      portalUpdate: this.portalUpdate,
      portalRegister: this.portalRegister,
      portalDeregister: this.portalDeregister,
      getTimer: this.getTimer
    };
  }

  componentWillMount() {
    this.savePortalRef = (portal) => {
      this.portalRef = portal;
      return portal;
    };
    this.portalUpdate = (key, el) => this.portalRef.portalUpdate(key, el);
    this.portalRegister = () => this.portalRef.portalRegister();
    this.portalDeregister = (key) => this.portalRef.portalDeregister(key);
  }

  componentWillUnmount() {
    if (!this.context.getTimer) {
      this.getTimer().stop();
    }
  }

  getTimer() {
    if (this.context.getTimer) {
      return this.context.getTimer();
    }
    if (!this.timer) {
      this.timer = new Timer();
    }
    return this.timer;
  }

  getIdForElement(elementName) {
    return `${this.containerId}-${elementName}`;
  }

  // overridden in custom containers
  getChildren(props) {
    return props.children;
  }

  renderContainer(props, svgProps, style) {
    const { title, desc, portalComponent, className } = props;
    const children = this.getChildren(props);
    const parentProps = defaults({ style, className }, svgProps);
    return (
        <svg {...parentProps} overflow="visible">
        <svg>
          {children}
        </svg>
          {title ? <title id={this.getIdForElement("title")}>{title}</title> : null}
          {desc ? <desc id={this.getIdForElement("desc")}>{desc}</desc> : null}
        <foreignObject>

            <svg overflow="visible">
              {React.cloneElement(portalComponent, { ref: this.savePortalRef })}
            </svg>

        </foreignObject>
        </svg>
    );
  }

  render() {
    const { width, height, responsive, events } = this.props;
    const style = responsive ? this.props.style : omit(this.props.style, ["height", "width"]);
    const touchStyle = defaults({}, style, { touchAction: "none" });
    const svgProps = assign(
      {
        width, height, role: "img",
        "aria-labelledby": `${this.getIdForElement("title")} ${this.getIdForElement("desc")}`,
        viewBox: responsive ? `0 0 ${width} ${height}` : undefined
      },
      events
    );
    return this.renderContainer(this.props, svgProps, touchStyle);
  }
}
<|endoftext|>