<commit_before>import React from "react";
import { connect } from "react-redux";
import Radium from "radium";
import _ from "lodash";
import { handleZidMetadataUpdate, optimisticZidMetadataUpdateOnTyping } from "../../actions";
import Checkbox from "material-ui/lib/checkbox";
import InputField from "material-ui/lib/text-field";
import settings from "../../settings";
import Spinner from "../framework/spinner";
import Awesome from "react-fontawesome";

/* check if refer came from 'new' and if it did, show modal saying 'get started by...' */

const cardPadding = 10;
const cardBorderRadius = 3;

const styles = {
  container: {
    backgroundColor: "rgb(240,240,247)",
    minHeight: "100vh",
    paddingBottom: 10
  },
  configCard: {
    margin: 10,
    maxWidth: 400,
    backgroundColor: "rgb(253,253,253)",
    borderRadius: cardBorderRadius,
    padding: cardPadding,
    WebkitBoxShadow: "3px 3px 6px -1px rgba(220,220,220,1)",
    BoxShadow: "3px 3px 6px -1px rgba(220,220,220,1)"
  },
  sectionHeader: {
    fontSize: 22,
    marginTop: 0,
    marginBottom: 0,
    fontWeight: 500,
    color: "rgb(160,160,160)"
  },
  notification: {
    fontSize: 16,
    fontWeight: 500,
    color: "rgb(160,160,160)"
  }
}

@connect(state => state.zid_metadata)
@Radium
class ConversationConfig extends React.Component {

  handleBoolValueChange (field) {
    return () => {
      var val = this.refs[field].isChecked();
      if (field === "bgcolor") {
        // gray checked=default, unchecked white
        val = val ? "default" : "#fff";
      }
      this.props.dispatch(
        handleZidMetadataUpdate(
          this.props.zid_metadata,
          field,
          val
        )
      )
    }
  }

  transformBoolToInt(value) {
    return value ? 1 : 0;
  }

  handleIntegerBoolValueChange (field) {
    return () => {
      this.props.dispatch(
        handleZidMetadataUpdate(
          this.props.zid_metadata,
          field,
          this.transformBoolToInt(this.refs[field].isChecked())
        )
      )
    }
  }

  handleStringValueChange (field) {
    return () => {
      var val = this.refs[field].getValue();
      if (field === "help_bgcolor" || field === "help_color") {
        if (!val.length) {
          val = "default";
        }
      }
      this.props.dispatch(
        handleZidMetadataUpdate(
          this.props.zid_metadata,
          field,
          this.refs[field].getValue()
        )
      )
    }
  }

  handleConfigInputTyping (field) {
    return (e) => {
      this.props.dispatch(
        optimisticZidMetadataUpdateOnTyping(
          this.props.zid_metadata,
          field,
          e.target.value
        )
      )
    }
  }

  render() {
    console.log("md", this.props.zid_metadata.topic)
    return (

        {
          this.props.loading ?

 <Awesome name="cloud-upload"/> Saving
 :

 <Awesome name="bolt"/> Up to date

        }
        {this.props.error ?
 <Awesome name="exclamation-circle"/> Error Saving
 : ""}

Topic

          <InputField
            ref={"topic"}
            style={{width: 360}}
            onBlur={this.handleStringValueChange("topic").bind(this)}
            floatingLabelText="Topic"
            onChange={this.handleConfigInputTyping("topic")}
            value={this.props.zid_metadata.topic}
            multiLine={true} />

Description

          <InputField
            hintText="Can include markdown!"
            style={{width: 360}}
            ref={"description"}
            onBlur={this.handleStringValueChange("description").bind(this)}
            floatingLabelText="Description"
            onChange={this.handleConfigInputTyping("description")}
            value={this.props.zid_metadata.description}
            multiLine={true} />

 Customize the User Interface

          <Checkbox
            label="Visualization"
            ref={"vis_type"}
            checked={ this.props.zid_metadata.vis_type === 1 ? true : false }
            onCheck={ this.handleIntegerBoolValueChange("vis_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 participants can see the visualization

          <Checkbox
            label="Comment form"
            ref={"write_type"}
            checked={this.props.zid_metadata.write_type === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("write_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users can submit comments

          <Checkbox
            label="Voting pane"
            ref={"upvotes"}
            disabled
            checked={this.props.zid_metadata.upvotes === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("upvotes").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users can vote on comments

          <Checkbox
            label="Help text"
            ref={"help_type"}
            checked={this.props.zid_metadata.help_type === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("help_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Show the two explanation modals above voting and the visualization

          <Checkbox
            label="Social sharing buttons"
            ref={"socialbtn_type"}
            checked={this.props.zid_metadata.socialbtn_type === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("socialbtn_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

          <Checkbox
            label="Facebook login prompt"
            ref={"auth_opt_fb"}
            checked={this.props.zid_metadata.auth_opt_fb}
            onCheck={ this.handleBoolValueChange("auth_opt_fb").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

          <Checkbox
            label="Twitter login prompt"
            ref={"auth_opt_tw"}
            checked={this.props.zid_metadata.auth_opt_tw}
            onCheck={ this.handleBoolValueChange("auth_opt_tw").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

          <Checkbox
            label="Gray background"
            ref={"bgcolor"}
            checked={this.props.zid_metadata.bgcolor === null ? true : false}
            onCheck={ this.handleBoolValueChange("bgcolor").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

              {"Unchecked: white background"}

            <InputField
              ref={"style_btn"}
              style={{width: 360}}
              onBlur={this.handleStringValueChange("style_btn").bind(this)}
              hintText="ie., #e63082"
              onChange={this.handleConfigInputTyping("style_btn")}
              value={this.props.zid_metadata.style_btn}
              floatingLabelText="Customize submit button color"
              multiLine={true} />

            <InputField
              ref={"help_bgcolor"}
              style={{width: 360}}
              onBlur={this.handleStringValueChange("help_bgcolor").bind(this)}
              onChange={this.handleConfigInputTyping("help_bgcolor")}
              value={this.props.zid_metadata.help_bgcolor}
              hintText="ie., #e63082"
              floatingLabelText="Customize help text background"
              multiLine={true} />

            <InputField
              ref={"help_color"}
              style={{width: 360}}
              onBlur={this.handleStringValueChange("help_color").bind(this)}
              onChange={this.handleConfigInputTyping("help_color")}
              value={this.props.zid_metadata.help_color}
              hintText="ie., #e63082"
              floatingLabelText="Customize help text color"
              multiLine={true} />

 Schemes

          <Checkbox
            label="Strict Moderation"
            ref={"strict_moderation"}
            checked={ this.props.zid_metadata.strict_moderation }
            onCheck={ this.handleBoolValueChange("strict_moderation").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 no comments shown without moderator approval

          <Checkbox
            label="Require Auth to Comment"
            ref={"auth_needed_to_write"}
            checked={this.props.zid_metadata.auth_needed_to_write}
            onCheck={ this.handleBoolValueChange("auth_needed_to_write").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users cannot submit comments without first connecting either Facebook or Twitter

          <Checkbox
            label="Require Auth to Vote"
            ref={"auth_needed_to_vote"}
            checked={this.props.zid_metadata.auth_needed_to_vote}
            onCheck={ this.handleBoolValueChange("auth_needed_to_vote").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users cannot vote without first connecting either Facebook or Twitter

          <Checkbox
            label="Preserve Anonymity"
            ref={"is_anon"}
            disabled
            checked={this.props.zid_metadata.is_anon}
            onCheck={ this.handleBoolValueChange("is_anon").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}/>

 Disables visualization, does not transmit any participant statistics to you, requires social authorization for both writing and voting.

    );
  }
}

export default ConversationConfig;

// <Checkbox
//   label="Read Only"
//   disabled
//   checked={false}
//   onCheck={ () => {console.log("this should be an action")} }
//   labelPosition={"left"}
//   labelWrapperColor={settings.darkerGray}/>
//
 Disables writing and commenting, enables visualization.

<commit_msg>add is_data_open to conversation-config<commit_after>import React from "react";
import { connect } from "react-redux";
import Radium from "radium";
import _ from "lodash";
import { handleZidMetadataUpdate, optimisticZidMetadataUpdateOnTyping } from "../../actions";
import Checkbox from "material-ui/lib/checkbox";
import InputField from "material-ui/lib/text-field";
import settings from "../../settings";
import Spinner from "../framework/spinner";
import Awesome from "react-fontawesome";

/* check if refer came from 'new' and if it did, show modal saying 'get started by...' */

const cardPadding = 10;
const cardBorderRadius = 3;

const styles = {
  container: {
    backgroundColor: "rgb(240,240,247)",
    minHeight: "100vh",
    paddingBottom: 10
  },
  configCard: {
    margin: 10,
    maxWidth: 400,
    backgroundColor: "rgb(253,253,253)",
    borderRadius: cardBorderRadius,
    padding: cardPadding,
    WebkitBoxShadow: "3px 3px 6px -1px rgba(220,220,220,1)",
    BoxShadow: "3px 3px 6px -1px rgba(220,220,220,1)"
  },
  sectionHeader: {
    fontSize: 22,
    marginTop: 0,
    marginBottom: 0,
    fontWeight: 500,
    color: "rgb(160,160,160)"
  },
  notification: {
    fontSize: 16,
    fontWeight: 500,
    color: "rgb(160,160,160)"
  }
}

@connect(state => state.zid_metadata)
@Radium
class ConversationConfig extends React.Component {

  handleBoolValueChange (field) {
    return () => {
      var val = this.refs[field].isChecked();
      if (field === "bgcolor") {
        // gray checked=default, unchecked white
        val = val ? "default" : "#fff";
      }
      this.props.dispatch(
        handleZidMetadataUpdate(
          this.props.zid_metadata,
          field,
          val
        )
      )
    }
  }

  transformBoolToInt(value) {
    return value ? 1 : 0;
  }

  handleIntegerBoolValueChange (field) {
    return () => {
      this.props.dispatch(
        handleZidMetadataUpdate(
          this.props.zid_metadata,
          field,
          this.transformBoolToInt(this.refs[field].isChecked())
        )
      )
    }
  }

  handleStringValueChange (field) {
    return () => {
      var val = this.refs[field].getValue();
      if (field === "help_bgcolor" || field === "help_color") {
        if (!val.length) {
          val = "default";
        }
      }
      this.props.dispatch(
        handleZidMetadataUpdate(
          this.props.zid_metadata,
          field,
          this.refs[field].getValue()
        )
      )
    }
  }

  handleConfigInputTyping (field) {
    return (e) => {
      this.props.dispatch(
        optimisticZidMetadataUpdateOnTyping(
          this.props.zid_metadata,
          field,
          e.target.value
        )
      )
    }
  }

  render() {
    console.log("md", this.props.zid_metadata.topic)
    return (

        {
          this.props.loading ?

 <Awesome name="cloud-upload"/> Saving
 :

 <Awesome name="bolt"/> Up to date

        }
        {this.props.error ?
 <Awesome name="exclamation-circle"/> Error Saving
 : ""}

Topic

          <InputField
            ref={"topic"}
            style={{width: 360}}
            onBlur={this.handleStringValueChange("topic").bind(this)}
            floatingLabelText="Topic"
            onChange={this.handleConfigInputTyping("topic")}
            value={this.props.zid_metadata.topic}
            multiLine={true} />

Description

          <InputField
            hintText="Can include markdown!"
            style={{width: 360}}
            ref={"description"}
            onBlur={this.handleStringValueChange("description").bind(this)}
            floatingLabelText="Description"
            onChange={this.handleConfigInputTyping("description")}
            value={this.props.zid_metadata.description}
            multiLine={true} />

 Customize the User Interface

          <Checkbox
            label="Visualization"
            ref={"vis_type"}
            checked={ this.props.zid_metadata.vis_type === 1 ? true : false }
            onCheck={ this.handleIntegerBoolValueChange("vis_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 participants can see the visualization

          <Checkbox
            label="Comment form"
            ref={"write_type"}
            checked={this.props.zid_metadata.write_type === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("write_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users can submit comments

          <Checkbox
            label="Voting pane"
            ref={"upvotes"}
            disabled
            checked={this.props.zid_metadata.upvotes === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("upvotes").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users can vote on comments

          <Checkbox
            label="Help text"
            ref={"help_type"}
            checked={this.props.zid_metadata.help_type === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("help_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Show the two explanation modals above voting and the visualization

          <Checkbox
            label="Social sharing buttons"
            ref={"socialbtn_type"}
            checked={this.props.zid_metadata.socialbtn_type === 1 ? true : false}
            onCheck={ this.handleIntegerBoolValueChange("socialbtn_type").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

          <Checkbox
            label="Facebook login prompt"
            ref={"auth_opt_fb"}
            checked={this.props.zid_metadata.auth_opt_fb}
            onCheck={ this.handleBoolValueChange("auth_opt_fb").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

          <Checkbox
            label="Twitter login prompt"
            ref={"auth_opt_tw"}
            checked={this.props.zid_metadata.auth_opt_tw}
            onCheck={ this.handleBoolValueChange("auth_opt_tw").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

          <Checkbox
            label="Gray background"
            ref={"bgcolor"}
            checked={this.props.zid_metadata.bgcolor === null ? true : false}
            onCheck={ this.handleBoolValueChange("bgcolor").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

              {"Unchecked: white background"}

            <InputField
              ref={"style_btn"}
              style={{width: 360}}
              onBlur={this.handleStringValueChange("style_btn").bind(this)}
              hintText="ie., #e63082"
              onChange={this.handleConfigInputTyping("style_btn")}
              value={this.props.zid_metadata.style_btn}
              floatingLabelText="Customize submit button color"
              multiLine={true} />

            <InputField
              ref={"help_bgcolor"}
              style={{width: 360}}
              onBlur={this.handleStringValueChange("help_bgcolor").bind(this)}
              onChange={this.handleConfigInputTyping("help_bgcolor")}
              value={this.props.zid_metadata.help_bgcolor}
              hintText="ie., #e63082"
              floatingLabelText="Customize help text background"
              multiLine={true} />

            <InputField
              ref={"help_color"}
              style={{width: 360}}
              onBlur={this.handleStringValueChange("help_color").bind(this)}
              onChange={this.handleConfigInputTyping("help_color")}
              value={this.props.zid_metadata.help_color}
              hintText="ie., #e63082"
              floatingLabelText="Customize help text color"
              multiLine={true} />

 Schemes

          <Checkbox
            label="Strict Moderation"
            ref={"strict_moderation"}
            checked={ this.props.zid_metadata.strict_moderation }
            onCheck={ this.handleBoolValueChange("strict_moderation").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 no comments shown without moderator approval

          <Checkbox
            label="Require Auth to Comment"
            ref={"auth_needed_to_write"}
            checked={this.props.zid_metadata.auth_needed_to_write}
            onCheck={ this.handleBoolValueChange("auth_needed_to_write").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users cannot submit comments without first connecting either Facebook or Twitter

          <Checkbox
            label="Require Auth to Vote"
            ref={"auth_needed_to_vote"}
            checked={this.props.zid_metadata.auth_needed_to_vote}
            onCheck={ this.handleBoolValueChange("auth_needed_to_vote").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Users cannot vote without first connecting either Facebook or Twitter

          <Checkbox
            label="Open Data"
            ref={"is_data_open"}
            checked={this.props.zid_metadata.is_data_open}
            onCheck={ this.handleBoolValueChange("is_data_open").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}
            color={settings.polisBlue}/>

 Comments, votes, and group data can be exported by any user

          <Checkbox
            label="Preserve Anonymity"
            ref={"is_anon"}
            disabled
            checked={this.props.zid_metadata.is_anon}
            onCheck={ this.handleBoolValueChange("is_anon").bind(this) }
            labelPosition={"left"}
            labelWrapperColor={settings.darkerGray}/>

 Disables visualization, does not transmit any participant statistics to you, requires social authorization for both writing and voting.

    );
  }
}

export default ConversationConfig;

// <Checkbox
//   label="Read Only"
//   disabled
//   checked={false}
//   onCheck={ () => {console.log("this should be an action")} }
//   labelPosition={"left"}
//   labelWrapperColor={settings.darkerGray}/>
//
 Disables writing and commenting, enables visualization.

<|endoftext|>


<commit_before>// Copyright 2013-2017, University of Colorado Boulder

/**
 * Button for a single screen in the navigation bar, shows the text and the navigation bar icon.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var DerivedProperty = require( 'AXON/DerivedProperty' );
  var FocusHighlightPath = require( 'SCENERY/accessibility/FocusHighlightPath' );
  var HighlightNode = require( 'JOIST/HighlightNode' );
  var inherit = require( 'PHET_CORE/inherit' );
  var joist = require( 'JOIST/joist' );
  var JoistA11yStrings = require( 'JOIST/JoistA11yStrings' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PhetColorScheme = require( 'SCENERY_PHET/PhetColorScheme' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var PushButtonModel = require( 'SUN/buttons/PushButtonModel' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var Shape = require( 'KITE/Shape' );
  var StringUtils = require( 'PHETCOMMON/util/StringUtils' );
  var Tandem = require( 'TANDEM/Tandem' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Util = require( 'DOT/Util' );
  var VBox = require( 'SCENERY/nodes/VBox' );

  // constants
  var HIGHLIGHT_SPACING = 4;

  // a11y strings
  var simScreenString = JoistA11yStrings.simScreen.value;
  var screenNameStringPatternString = JoistA11yStrings.screenNumberPattern.value;

  /**
   * Create a nav bar.  Layout assumes all of the screen widths are the same.
   * @param {Property.<string>} navigationBarFillProperty - the color of the navbar, as a string.
   * @param {Property.<number>} screenIndexProperty
   * @param {Array.<Screen>} screens - all of the available sim content screens (excluding the home screen)
   * @param {Screen} screen
   * @param {number} navBarHeight
   * @param {Object} [options]
   * @constructor
   */
  function NavigationBarScreenButton( navigationBarFillProperty, screenIndexProperty, screens, screen, navBarHeight, options ) {

    assert && assert( screen.name, 'name is required for screen ' + screens.indexOf( screen ) );
    assert && assert( screen.navigationBarIcon, 'navigationBarIcon is required for screen ' + screen.name );

    // The index of the screen that the button is being constructed for.
    var screenIndex = screens.indexOf( screen );

    function clicked() {
      screenIndexProperty.value = screenIndex;
    }

    options = _.extend( {
      cursor: 'pointer',
      tandem: Tandem.required,
      maxButtonWidth: null, // {number|null} the maximum width of the button, causes text and/or icon to be scaled down if necessary

      // a11y
      tagName: 'button',
      containerTagName: 'li',
      descriptionContent: screen.descriptionContent,
      appendDescription: true,
      innerContent: StringUtils.fillIn( screenNameStringPatternString, {
        number: screenIndex + 1 // convert from index to display number
      } )
    }, options );

    Node.call( this );

    // icon
    var icon = new Node( {
      children: [ screen.navigationBarIcon ], // wrap in case this icon is used in multiple place (eg, home screen and navbar)
      maxHeight: 0.625 * navBarHeight,
      tandem: options.tandem.createTandem( 'icon' )
    } );

    // Is this button's screen selected?
    var selectedProperty = new DerivedProperty( [ screenIndexProperty ], function( screenIndex ) {
      return screenIndex === screens.indexOf( screen );
    } );

    // @public (phet-io) - create the button model, needs to be public so that PhET-iO wrappers can hook up to it if needed
    // Note it shares a tandem with this, so the emitter will be instrumented as a child of the button
    // Note that this buttonModel will always be phetioReadOnly false despite the parent value
    this.buttonModel = new PushButtonModel( {
      listener: clicked,
      tandem: options.tandem
    } );

    // Hook up the input listener
    var pressListener = this.buttonModel.createListener( {
      tandem: options.tandem.createTandem( 'pressListener' ),
      phetioDocumentation: 'Indicates when the screen button has been pressed or released'
    } );

    this.addInputListener( pressListener );
    this.addAccessibleInputListener( pressListener.a11yListener );

    var text = new Text( screen.name, {
      font: new PhetFont( 10 ),
      tandem: options.tandem.createTandem( 'text' )
    } );

    var box = new VBox( {
      children: [ icon, text ],
      pickable: false,
      spacing: Math.max( 0, 12 - text.height ), // see https://github.com/phetsims/joist/issues/143
      usesOpacity: true, // hint, since we change its opacity
      maxHeight: navBarHeight
    } );

    // add a transparent overlay for input handling and to size touchArea/mouseArea
    var overlay = new Rectangle( 0, 0, box.width, box.height, { center: box.center } );

    // highlights
    var highlightWidth = overlay.width + ( 2 * HIGHLIGHT_SPACING );
    var brightenHighlight = new HighlightNode( highlightWidth, overlay.height, {
      center: box.center,
      fill: 'white'
    } );
    var darkenHighlight = new HighlightNode( highlightWidth, overlay.height, {
      center: box.center,
      fill: 'black'
    } );

    this.addChild( box );
    this.addChild( overlay );
    this.addChild( brightenHighlight );
    this.addChild( darkenHighlight );

    // manage interaction feedback
    Property.multilink( [
      selectedProperty,
      this.buttonModel.looksPressedProperty,
      this.buttonModel.overProperty,
      navigationBarFillProperty
    ], function update( selected, looksPressed, over, navigationBarFill ) {

      var useDarkenHighlights = ( navigationBarFill !== 'black' );

      // Color match yellow with the PhET Logo
      var selectedTextColor = useDarkenHighlights ? 'black' : PhetColorScheme.BUTTON_YELLOW;
      var unselectedTextColor = useDarkenHighlights ? 'gray' : 'white';

      text.fill = selected ? selectedTextColor : unselectedTextColor;
      box.opacity = selected ? 1.0 : ( looksPressed ? 0.65 : 0.5 );
      brightenHighlight.visible = !useDarkenHighlights && ( over || looksPressed );
      darkenHighlight.visible = useDarkenHighlights && ( over || looksPressed );
    } );

    // Constrain text and icon width, if necessary
    if ( options.maxButtonWidth && ( this.width > options.maxButtonWidth ) ) {

      text.maxWidth = icon.maxWidth = options.maxButtonWidth - ( this.width - box.width );

      // adjust the overlay
      overlay.setRect( 0, 0, box.width, overlay.height );
      overlay.center = box.center;

      // adjust the highlights
      brightenHighlight.spacing = darkenHighlight.spacing = overlay.width + ( 2 * HIGHLIGHT_SPACING );
      brightenHighlight.center = darkenHighlight.center = box.center;

      assert && assert( Util.toFixed( this.width, 0 ) === Util.toFixed( options.maxButtonWidth, 0 ) );
    }
    else {

      // Don't allow the text to grow larger than the icon if changed later on using PhET-iO, see #438
      // Text is allowed to go beyond the bounds of the icon, hence we use `this.width` instead of `icon.width`
      text.maxWidth = this.width;
    }

    // a11y - set the role description for the button
    this.setAccessibleAttribute( 'aria-roledescription', simScreenString );

    // a11y - Pass a shape to the focusHighlight to prevent dilation, then tweak the top up just a hair.
    var highlightLineWidth = FocusHighlightPath.getOuterLineWidthFromNode( this );
    this.focusHighlight = Shape.bounds( this.bounds.setMinY( this.bounds.minY - highlightLineWidth / 2 ) );

    this.mutate( options );
  }

  joist.register( 'NavigationBarScreenButton', NavigationBarScreenButton );

  return inherit( Node, NavigationBarScreenButton );
} );
<commit_msg>Formatting and documentation, see https://github.com/phetsims/sun/issues/396<commit_after>// Copyright 2013-2017, University of Colorado Boulder

/**
 * Button for a single screen in the navigation bar, shows the text and the navigation bar icon.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 * @author Chris Malley (PixelZoom, Inc.)
 */
define( function( require ) {
  'use strict';

  // modules
  var DerivedProperty = require( 'AXON/DerivedProperty' );
  var FocusHighlightPath = require( 'SCENERY/accessibility/FocusHighlightPath' );
  var HighlightNode = require( 'JOIST/HighlightNode' );
  var inherit = require( 'PHET_CORE/inherit' );
  var joist = require( 'JOIST/joist' );
  var JoistA11yStrings = require( 'JOIST/JoistA11yStrings' );
  var Node = require( 'SCENERY/nodes/Node' );
  var PhetColorScheme = require( 'SCENERY_PHET/PhetColorScheme' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var PushButtonModel = require( 'SUN/buttons/PushButtonModel' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var Shape = require( 'KITE/Shape' );
  var StringUtils = require( 'PHETCOMMON/util/StringUtils' );
  var Tandem = require( 'TANDEM/Tandem' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Util = require( 'DOT/Util' );
  var VBox = require( 'SCENERY/nodes/VBox' );

  // constants
  var HIGHLIGHT_SPACING = 4;

  // a11y strings
  var simScreenString = JoistA11yStrings.simScreen.value;
  var screenNameStringPatternString = JoistA11yStrings.screenNumberPattern.value;

  /**
   * Create a nav bar.  Layout assumes all of the screen widths are the same.
   * @param {Property.<string>} navigationBarFillProperty - the color of the navbar, as a string.
   * @param {Property.<number>} screenIndexProperty
   * @param {Array.<Screen>} screens - all of the available sim content screens (excluding the home screen)
   * @param {Screen} screen
   * @param {number} navBarHeight
   * @param {Object} [options]
   * @constructor
   */
  function NavigationBarScreenButton( navigationBarFillProperty, screenIndexProperty, screens, screen, navBarHeight, options ) {

    assert && assert( screen.name, 'name is required for screen ' + screens.indexOf( screen ) );
    assert && assert( screen.navigationBarIcon, 'navigationBarIcon is required for screen ' + screen.name );

    // The index of the screen that the button is being constructed for.
    var screenIndex = screens.indexOf( screen );

    function clicked() {
      screenIndexProperty.value = screenIndex;
    }

    options = _.extend( {
      cursor: 'pointer',
      tandem: Tandem.required,
      phetioDocumentation: 'Button in the navigation bar that selects the \'' + screen.name + '\' screen',
      maxButtonWidth: null, // {number|null} the maximum width of the button, causes text and/or icon to be scaled down if necessary

      // a11y
      tagName: 'button',
      containerTagName: 'li',
      descriptionContent: screen.descriptionContent,
      appendDescription: true,
      innerContent: StringUtils.fillIn( screenNameStringPatternString, {
        number: screenIndex + 1 // convert from index to display number
      } )
    }, options );

    Node.call( this );

    // icon
    var icon = new Node( {
      children: [ screen.navigationBarIcon ], // wrap in case this icon is used in multiple place (eg, home screen and navbar)
      maxHeight: 0.625 * navBarHeight,
      tandem: options.tandem.createTandem( 'icon' )
    } );

    // Is this button's screen selected?
    var selectedProperty = new DerivedProperty( [ screenIndexProperty ], function( screenIndex ) {
      return screenIndex === screens.indexOf( screen );
    } );

    // @public (phet-io) - create the button model, needs to be public so that PhET-iO wrappers can hook up to it if needed
    // Note it shares a tandem with this, so the emitter will be instrumented as a child of the button
    // Note that this buttonModel will always be phetioReadOnly false despite the parent value
    this.buttonModel = new PushButtonModel( {
      listener: clicked,
      tandem: options.tandem
    } );

    // Hook up the input listener
    var pressListener = this.buttonModel.createListener( {
      tandem: options.tandem.createTandem( 'pressListener' ),
      phetioDocumentation: 'Indicates when the screen button has been pressed or released'
    } );

    this.addInputListener( pressListener );
    this.addAccessibleInputListener( pressListener.a11yListener );

    var text = new Text( screen.name, {
      font: new PhetFont( 10 ),
      tandem: options.tandem.createTandem( 'text' )
    } );

    var box = new VBox( {
      children: [ icon, text ],
      pickable: false,
      spacing: Math.max( 0, 12 - text.height ), // see https://github.com/phetsims/joist/issues/143
      usesOpacity: true, // hint, since we change its opacity
      maxHeight: navBarHeight
    } );

    // add a transparent overlay for input handling and to size touchArea/mouseArea
    var overlay = new Rectangle( 0, 0, box.width, box.height, { center: box.center } );

    // highlights
    var highlightWidth = overlay.width + ( 2 * HIGHLIGHT_SPACING );
    var brightenHighlight = new HighlightNode( highlightWidth, overlay.height, {
      center: box.center,
      fill: 'white'
    } );
    var darkenHighlight = new HighlightNode( highlightWidth, overlay.height, {
      center: box.center,
      fill: 'black'
    } );

    this.addChild( box );
    this.addChild( overlay );
    this.addChild( brightenHighlight );
    this.addChild( darkenHighlight );

    // manage interaction feedback
    Property.multilink( [
      selectedProperty,
      this.buttonModel.looksPressedProperty,
      this.buttonModel.overProperty,
      navigationBarFillProperty
    ], function update( selected, looksPressed, over, navigationBarFill ) {

      var useDarkenHighlights = ( navigationBarFill !== 'black' );

      // Color match yellow with the PhET Logo
      var selectedTextColor = useDarkenHighlights ? 'black' : PhetColorScheme.BUTTON_YELLOW;
      var unselectedTextColor = useDarkenHighlights ? 'gray' : 'white';

      text.fill = selected ? selectedTextColor : unselectedTextColor;
      box.opacity = selected ? 1.0 : ( looksPressed ? 0.65 : 0.5 );
      brightenHighlight.visible = !useDarkenHighlights && ( over || looksPressed );
      darkenHighlight.visible = useDarkenHighlights && ( over || looksPressed );
    } );

    // Constrain text and icon width, if necessary
    if ( options.maxButtonWidth && ( this.width > options.maxButtonWidth ) ) {

      text.maxWidth = icon.maxWidth = options.maxButtonWidth - ( this.width - box.width );

      // adjust the overlay
      overlay.setRect( 0, 0, box.width, overlay.height );
      overlay.center = box.center;

      // adjust the highlights
      brightenHighlight.spacing = darkenHighlight.spacing = overlay.width + ( 2 * HIGHLIGHT_SPACING );
      brightenHighlight.center = darkenHighlight.center = box.center;

      assert && assert( Util.toFixed( this.width, 0 ) === Util.toFixed( options.maxButtonWidth, 0 ) );
    }
    else {

      // Don't allow the text to grow larger than the icon if changed later on using PhET-iO, see #438
      // Text is allowed to go beyond the bounds of the icon, hence we use `this.width` instead of `icon.width`
      text.maxWidth = this.width;
    }

    // a11y - set the role description for the button
    this.setAccessibleAttribute( 'aria-roledescription', simScreenString );

    // a11y - Pass a shape to the focusHighlight to prevent dilation, then tweak the top up just a hair.
    var highlightLineWidth = FocusHighlightPath.getOuterLineWidthFromNode( this );
    this.focusHighlight = Shape.bounds( this.bounds.setMinY( this.bounds.minY - highlightLineWidth / 2 ) );

    this.mutate( options );
  }

  joist.register( 'NavigationBarScreenButton', NavigationBarScreenButton );

  return inherit( Node, NavigationBarScreenButton );
} );
<|endoftext|>


<commit_before>// D3

const d3Chart = {}

d3Chart.create = function (el, props, state) {
  const svg = d3.select(el).append('svg')
    .attr('class', 'd3')
    .attr('width', props.width)
    .attr('height', props.height)
  svg.append('g')
    .attr('class', 'd3-points')
  this.update(el, state)
}

d3Chart._scales = function (el, domain) {
  if (!domain) {
    return null
  }
  const width = el.offsetWidth
  const height = el.offsetHeight

  const x = d3.scaleOrdinal()
    .range([0, width])
    .domain(domain.x)
  const y = d3.scaleLinear()
    .range([0, height])
    .domain(domain.y)
  return { x, y }
}

d3Chart.update = function (el, state) {
  const g = d3.select(el).selectAll('.d3-points')
  const point = g.selectAll('.d3-point')
    .data(state.data)
  point.enter().append('circle')
    .attr('class', 'd3-point')
  point
    .attr('cy', d => d.val)
    .attr('cx', d => d.id)
    .attr('r', d => 5)
  point.exit().remove()
  const scales = this._scales(el, state.domain)
  const prevScales = this._scales(el, state.prevDomain)
  this._drawPoints(el, scales, state.data, prevScales)
}

d3Chart._drawPoints = function (el, scales, data, prevScales) {
  const g = d3.select(el).selectAll('.d3-points')
  const point = g.selectAll('.d3-point')
    .data(data, function(d) { return d.id })
  point.enter().append('circle')
    .attr('class', 'd3-point')
    .attr('cx', d => {
      if (prevScales) {
        return prevScales.x(d.id)
      }
      return scales.x(d.id)
    })
  point
    .attr('cx', d => scales.x(d.id))
    .attr('cy', d => scales.y(d.val))
  point.exit().remove()
}

const Chart = React.createClass({
  propTypes: {
    data: React.PropTypes.array,
    domain: React.PropTypes.object
  },
  componentDidMount: function () {
    const el = ReactDOM.findDOMNode(this)
    d3Chart.create(el, {
      width: '100%',
      height: '300px'
    }, this.getChartState())
  },
  componentDidUpdate: function () {
    const el = ReactDOM.findDOMNode(this)
    d3Chart.update(el, this.getChartState())
  },
  getChartState: function () {
    return {
      data: this.props.data,
      domain: this.props.domain
    }
  },
  componentWillUnmount: function () {
    const el = ReactDOM.findDOMNode(this)
    d3Chart.destroy(el)
  },
  render: function () {
    return (

    )
  }
})

// React

const GraphDashboard = React.createClass({
  getInitialState: function () {
    return {
      data: [{ id: 0, val: 0}],
      domain: {
        x: [0, 10],
        y: [0, 10]
      }
    }
  },
  componentWillMount: function () {
    this.ws = new WebSocket("ws://parrot:3000/")
    this.ws.onopen = () => this.ws.send("ok")
  },
  componentDidMount: function () {
    this.ws.onmessage = (event, flags) => {
      const oldStateData = this.state.data
      if (oldStateData.length > 10) {
        oldStateData.shift()
      }
      const newData = event.data
      oldStateData.push({
        id: oldStateData[oldStateData.length - 1].id + 1,
        val: newData
      })
      this.setState({ data: oldStateData })
    }
  },
  render: function () {
    return (

        <Chart
          data={this.state.data}
          domain={this.state.domain}
        />

    )
  }
})

ReactDOM.render(
  <GraphDashboard />,
  document.getElementById('content')
)
<commit_msg>oldStateData mutable, x location between 1 and 10<commit_after>// D3

const d3Chart = {}

d3Chart.create = function (el, props, state) {
  const svg = d3.select(el).append('svg')
    .attr('class', 'd3')
    .attr('width', props.width)
    .attr('height', props.height)
  svg.append('g')
    .attr('class', 'd3-points')
  this.update(el, state)
}

d3Chart._scales = function (el, domain) {
  if (!domain) {
    return null
  }
  const width = el.offsetWidth
  const height = el.offsetHeight

  const x = d3.scaleOrdinal()
    .range([0, width])
    .domain(domain.x)
  const y = d3.scaleLinear()
    .range([0, height])
    .domain(domain.y)
  return { x, y }
}

d3Chart.update = function (el, state) {
  const g = d3.select(el).selectAll('.d3-points')
  const point = g.selectAll('.d3-point')
    .data(state.data)
  point.enter().append('circle')
    .attr('class', 'd3-point')
  point
    .attr('cy', d => d.y)
    .attr('cx', d => d.x)
    .attr('r', d => 5)
  point.exit().remove()
  const scales = this._scales(el, state.domain)
  const prevScales = this._scales(el, state.prevDomain)
  this._drawPoints(el, scales, state.data, prevScales)
}

d3Chart._drawPoints = function (el, scales, data, prevScales) {
  const g = d3.select(el).selectAll('.d3-points')
  const point = g.selectAll('.d3-point')
    .data(data, function(d) { return d.id })
  point.enter().append('circle')
    .attr('class', 'd3-point')
    .attr('cx', d => {
      if (prevScales) {
        return prevScales.x(d.x)
      }
      return scales.x(d.x)
    })
  point
    .attr('cx', d => scales.x(d.x))
    .attr('cy', d => scales.y(d.y))
  point.exit().remove()
}

const Chart = React.createClass({
  propTypes: {
    data: React.PropTypes.array,
    domain: React.PropTypes.object
  },
  componentDidMount: function () {
    const el = ReactDOM.findDOMNode(this)
    d3Chart.create(el, {
      width: '100%',
      height: '300px'
    }, this.getChartState())
  },
  componentDidUpdate: function () {
    const el = ReactDOM.findDOMNode(this)
    d3Chart.update(el, this.getChartState())
  },
  getChartState: function () {
    return {
      data: this.props.data,
      domain: this.props.domain
    }
  },
  componentWillUnmount: function () {
    const el = ReactDOM.findDOMNode(this)
    d3Chart.destroy(el)
  },
  render: function () {
    return (

    )
  }
})

// React

const GraphDashboard = React.createClass({
  getInitialState: function () {
    return {
      data: [{ id: 9, y: 0, x: 10 }],
      domain: {
        x: [10, 0],
        y: [0, 10]
      }
    }
  },
  componentWillMount: function () {
    this.ws = new WebSocket("ws://parrot:3000/")
    this.ws.onopen = () => this.ws.send("ok")
  },
  componentDidMount: function () {
    this.ws.onmessage = (event, flags) => {
      let oldStateData = this.state.data

      if (oldStateData.length > 9) {
        oldStateData.shift()
      }

      oldStateData = oldStateData.map(d => {
        d.x = d.x -1
        return d
      })

      const newData = event.data
      oldStateData.push({
        id: oldStateData[oldStateData.length - 1].id + 1,
        x: oldStateData[oldStateData.length - 1].x + 1,
        y: newData
      })
      this.setState({ data: oldStateData })
    }
  },
  render: function () {
    return (

        <Chart
          data={this.state.data}
          domain={this.state.domain}
        />

    )
  }
})

ReactDOM.render(
  <GraphDashboard />,
  document.getElementById('content')
)
<|endoftext|>


<commit_before>var Fiber = require("fibers");
var fs = require("fs");
var path = require("path");
var Future = require("fibers/future");
var _ = require('underscore');
var sourcemap_support = require('source-map-support');

var bootUtils = require('./boot-utils.js');
var files = require('./mini-files.js');

// This code is duplicated in tools/main.js.
var MIN_NODE_VERSION = 'v0.10.33';

if (require('semver').lt(process.version, MIN_NODE_VERSION)) {
  process.stderr.write(
    'Meteor requires Node ' + MIN_NODE_VERSION + ' or later.\n');
  process.exit(1);
}

// read our control files
var serverJsonPath = path.resolve(process.argv[2]);
var serverDir = path.dirname(serverJsonPath);
var serverJson = JSON.parse(fs.readFileSync(serverJsonPath, 'utf8'));
var configJson =
  JSON.parse(fs.readFileSync(path.resolve(serverDir, 'config.json'), 'utf8'));

// Set up environment
__meteor_bootstrap__ = {
  startupHooks: [],
  serverDir: serverDir,
  configJson: configJson };
__meteor_runtime_config__ = { meteorRelease: configJson.meteorRelease };

// connect (and some other NPM modules) use $NODE_ENV to make some decisions;
// eg, if $NODE_ENV is not production, they send stack traces on error. connect
// considers 'development' to be the default mode, but that's less safe than
// assuming 'production' to be the default. If you really want development mode,
// set it in your wrapper script (eg, run-app.js).
if (!process.env.NODE_ENV)
  process.env.NODE_ENV = 'production';

// Map from load path to its source map.
var parsedSourceMaps = {};

// Read all the source maps into memory once.
_.each(serverJson.load, function (fileInfo) {
  if (fileInfo.sourceMap) {
    var rawSourceMap = fs.readFileSync(
      path.resolve(serverDir, fileInfo.sourceMap), 'utf8');
    // Parse the source map only once, not each time it's needed. Also remove
    // the anti-XSSI header if it's there.
    var parsedSourceMap = JSON.parse(rawSourceMap.replace(/^\)\]\}'/, ''));
    // source-map-support doesn't ever look at the sourcesContent field, so
    // there's no point in keeping it in memory.
    delete parsedSourceMap.sourcesContent;
    var url;
    if (fileInfo.sourceMapRoot) {
      // Add the specified root to any root that may be in the file.
      parsedSourceMap.sourceRoot = path.join(
        fileInfo.sourceMapRoot, parsedSourceMap.sourceRoot || '');
    }
    parsedSourceMaps[path.resolve(__dirname, fileInfo.path)] = parsedSourceMap;
  }
});

var retrieveSourceMap = function (pathForSourceMap) {
  if (_.has(parsedSourceMaps, pathForSourceMap))
    return { map: parsedSourceMaps[pathForSourceMap] };
  return null;
};

sourcemap_support.install({
  // Use the source maps specified in program.json instead of parsing source
  // code for them.
  retrieveSourceMap: retrieveSourceMap,
  // For now, don't fix the source line in uncaught exceptions, because we
  // haven't fixed handleUncaughtExceptions in source-map-support to properly
  // locate the source files.
  handleUncaughtExceptions: false
});

// Only enabled by default in development.
if (process.env.METEOR_SHELL_DIR) {
  require('./shell.js').listen(process.env.METEOR_SHELL_DIR);
}

// As a replacement to the old keepalives mechanism, check for a running
// parent every few seconds. Exit if the parent is not running.
//
// Two caveats to this strategy:
// * Doesn't catch the case where the parent is CPU-hogging (but maybe we
//   don't want to catch that case anyway, since the bundler not yielding
//   is what caused #2536).
// * Could be fooled by pid re-use, i.e. if another process comes up and
//   takes the parent process's place before the child process dies.
var startCheckForLiveParent = function (parentPid) {
  if (parentPid) {
    if (! bootUtils.validPid(parentPid)) {
      console.error("METEOR_PARENT_PID must be a valid process ID.");
      process.exit(1);
    }

    setInterval(function () {
      try {
        process.kill(parentPid, 0);
      } catch (err) {
        console.error("Parent process is dead! Exiting.");
        process.exit(1);
      }
    }, 3000);
  }
};

Fiber(function () {
  _.each(serverJson.load, function (fileInfo) {
    var code = fs.readFileSync(path.resolve(serverDir, fileInfo.path));

    var Npm = {
      /**
       * @summary Require a package that was specified using
       * `Npm.depends()`.
       * @param  {String} name The name of the package to require.
       * @locus Server
       * @memberOf Npm
       */
      require: function (name) {
        if (! fileInfo.node_modules) {
          return require(name);
        }

        var nodeModuleBase = path.resolve(serverDir, fileInfo.node_modules);
        var nodeModuleDir = path.resolve(nodeModuleBase, name);

        // If the user does `Npm.require('foo/bar')`, then we should resolve to
        // the package's node modules if `foo` was one of the modules we
        // installed.  (`foo/bar` might be implemented as `foo/bar.js` so we
        // can't just naively see if all of nodeModuleDir exists.
        if (fs.existsSync(path.resolve(nodeModuleBase, name.split("/")[0]))) {
          return require(nodeModuleDir);
        }

        try {
          return require(name);
        } catch (e) {
          // Try to guess the package name so we can print a nice
          // error message
          // fileInfo.path is a standard path, use files.pathSep
          var filePathParts = fileInfo.path.split(files.pathSep);
          var packageName = filePathParts[1].replace(/\.js$/, '');

          // XXX better message
          throw new Error(
            "Can't find npm module '" + name +
              "'. Did you forget to call 'Npm.depends' in package.js " +
              "within the '" + packageName + "' package?");
          }
      }
    };
    var getAsset = function (assetPath, encoding, callback) {
      var fut;
      if (! callback) {
        fut = new Future();
        callback = fut.resolver();
      }
      // This assumes that we've already loaded the meteor package, so meteor
      // itself (and weird special cases like js-analyze) can't call
      // Assets.get*. (We could change this function so that it doesn't call
      // bindEnvironment if you don't pass a callback if we need to.)
      var _callback = Package.meteor.Meteor.bindEnvironment(function (err, result) {
        if (result && ! encoding)
          // Sadly, this copies in Node 0.10.
          result = new Uint8Array(result);
        callback(err, result);
      }, function (e) {
        console.log("Exception in callback of getAsset", e.stack);
      });

      // Convert a DOS-style path to Unix-style in case the application code was
      // written on Windows.
      assetPath = files.convertToStandardPath(assetPath);

      if (!fileInfo.assets || !_.has(fileInfo.assets, assetPath)) {
        _callback(new Error("Unknown asset: " + assetPath));
      } else {
        var filePath = path.join(serverDir, fileInfo.assets[assetPath]);
        fs.readFile(files.convertToOSPath(filePath), encoding, _callback);
      }
      if (fut)
        return fut.wait();
    };

    var Assets = {
      getText: function (assetPath, callback) {
        return getAsset(assetPath, "utf8", callback);
      },
      getBinary: function (assetPath, callback) {
        return getAsset(assetPath, undefined, callback);
      }
    };

    // \n is necessary in case final line is a //-comment
    var wrapped = "(function(Npm, Assets){" + code + "\n})";

    // It is safer to use the absolute path when source map is present as
    // different tooling, such as node-inspector, can get confused on relative
    // urls.

    // fileInfo.path is a standard path, convert it to OS path to join with
    // __dirname
    var fileInfoOSPath = files.convertToOSPath(fileInfo.path);
    var absoluteFilePath = path.resolve(__dirname, fileInfoOSPath);

    var scriptPath =
      parsedSourceMaps[absoluteFilePath] ? absoluteFilePath : fileInfoOSPath;
    // The final 'true' is an undocumented argument to runIn[Foo]Context that
    // causes it to print out a descriptive error message on parse error. It's
    // what require() uses to generate its errors.
    var func = require('vm').runInThisContext(wrapped, scriptPath, true);
    func.call(global, Npm, Assets); // Coffeescript
  });

  // run the user startup hooks.  other calls to startup() during this can still
  // add hooks to the end.
  while (__meteor_bootstrap__.startupHooks.length) {
    var hook = __meteor_bootstrap__.startupHooks.shift();
    hook();
  }
  // Setting this to null tells Meteor.startup to call hooks immediately.
  __meteor_bootstrap__.startupHooks = null;

  // find and run main()
  // XXX hack. we should know the package that contains main.
  var mains = [];
  var globalMain;
  if ('main' in global) {
    mains.push(main);
    globalMain = main;
  }
  typeof Package !== 'undefined' && _.each(Package, function (p, n) {
    if ('main' in p && p.main !== globalMain) {
      mains.push(p.main);
    }
  });
  if (! mains.length) {
    process.stderr.write("Program has no main() function.\n");
    process.exit(1);
  }
  if (mains.length > 1) {
    process.stderr.write("Program has more than one main() function?\n");
    process.exit(1);
  }
  var exitCode = mains[0].call({}, process.argv.slice(3));
  // XXX hack, needs a better way to keep alive
  if (exitCode !== 'DAEMON')
    process.exit(exitCode);

  if (process.env.METEOR_PARENT_PID) {
    startCheckForLiveParent(process.env.METEOR_PARENT_PID);
  }
}).run();
<commit_msg>Fix the use of paths in Npm.require on Windows<commit_after>var Fiber = require("fibers");
var fs = require("fs");
var path = require("path");
var Future = require("fibers/future");
var _ = require('underscore');
var sourcemap_support = require('source-map-support');

var bootUtils = require('./boot-utils.js');
var files = require('./mini-files.js');

// This code is duplicated in tools/main.js.
var MIN_NODE_VERSION = 'v0.10.33';

if (require('semver').lt(process.version, MIN_NODE_VERSION)) {
  process.stderr.write(
    'Meteor requires Node ' + MIN_NODE_VERSION + ' or later.\n');
  process.exit(1);
}

// read our control files
var serverJsonPath = path.resolve(process.argv[2]);
var serverDir = path.dirname(serverJsonPath);
var serverJson = JSON.parse(fs.readFileSync(serverJsonPath, 'utf8'));
var configJson =
  JSON.parse(fs.readFileSync(path.resolve(serverDir, 'config.json'), 'utf8'));

// Set up environment
__meteor_bootstrap__ = {
  startupHooks: [],
  serverDir: serverDir,
  configJson: configJson };
__meteor_runtime_config__ = { meteorRelease: configJson.meteorRelease };

// connect (and some other NPM modules) use $NODE_ENV to make some decisions;
// eg, if $NODE_ENV is not production, they send stack traces on error. connect
// considers 'development' to be the default mode, but that's less safe than
// assuming 'production' to be the default. If you really want development mode,
// set it in your wrapper script (eg, run-app.js).
if (!process.env.NODE_ENV)
  process.env.NODE_ENV = 'production';

// Map from load path to its source map.
var parsedSourceMaps = {};

// Read all the source maps into memory once.
_.each(serverJson.load, function (fileInfo) {
  if (fileInfo.sourceMap) {
    var rawSourceMap = fs.readFileSync(
      path.resolve(serverDir, fileInfo.sourceMap), 'utf8');
    // Parse the source map only once, not each time it's needed. Also remove
    // the anti-XSSI header if it's there.
    var parsedSourceMap = JSON.parse(rawSourceMap.replace(/^\)\]\}'/, ''));
    // source-map-support doesn't ever look at the sourcesContent field, so
    // there's no point in keeping it in memory.
    delete parsedSourceMap.sourcesContent;
    var url;
    if (fileInfo.sourceMapRoot) {
      // Add the specified root to any root that may be in the file.
      parsedSourceMap.sourceRoot = path.join(
        fileInfo.sourceMapRoot, parsedSourceMap.sourceRoot || '');
    }
    parsedSourceMaps[path.resolve(__dirname, fileInfo.path)] = parsedSourceMap;
  }
});

var retrieveSourceMap = function (pathForSourceMap) {
  if (_.has(parsedSourceMaps, pathForSourceMap))
    return { map: parsedSourceMaps[pathForSourceMap] };
  return null;
};

sourcemap_support.install({
  // Use the source maps specified in program.json instead of parsing source
  // code for them.
  retrieveSourceMap: retrieveSourceMap,
  // For now, don't fix the source line in uncaught exceptions, because we
  // haven't fixed handleUncaughtExceptions in source-map-support to properly
  // locate the source files.
  handleUncaughtExceptions: false
});

// Only enabled by default in development.
if (process.env.METEOR_SHELL_DIR) {
  require('./shell.js').listen(process.env.METEOR_SHELL_DIR);
}

// As a replacement to the old keepalives mechanism, check for a running
// parent every few seconds. Exit if the parent is not running.
//
// Two caveats to this strategy:
// * Doesn't catch the case where the parent is CPU-hogging (but maybe we
//   don't want to catch that case anyway, since the bundler not yielding
//   is what caused #2536).
// * Could be fooled by pid re-use, i.e. if another process comes up and
//   takes the parent process's place before the child process dies.
var startCheckForLiveParent = function (parentPid) {
  if (parentPid) {
    if (! bootUtils.validPid(parentPid)) {
      console.error("METEOR_PARENT_PID must be a valid process ID.");
      process.exit(1);
    }

    setInterval(function () {
      try {
        process.kill(parentPid, 0);
      } catch (err) {
        console.error("Parent process is dead! Exiting.");
        process.exit(1);
      }
    }, 3000);
  }
};

Fiber(function () {
  _.each(serverJson.load, function (fileInfo) {
    var code = fs.readFileSync(path.resolve(serverDir, fileInfo.path));

    var Npm = {
      /**
       * @summary Require a package that was specified using
       * `Npm.depends()`.
       * @param  {String} name The name of the package to require.
       * @locus Server
       * @memberOf Npm
       */
      require: function (name) {
        if (! fileInfo.node_modules) {
          return require(name);
        }

        var nodeModuleBase = path.resolve(serverDir,
          files.convertToOSPath(fileInfo.node_modules));
        var nodeModuleDir = path.resolve(nodeModuleBase, name);

        // If the user does `Npm.require('foo/bar')`, then we should resolve to
        // the package's node modules if `foo` was one of the modules we
        // installed.  (`foo/bar` might be implemented as `foo/bar.js` so we
        // can't just naively see if all of nodeModuleDir exists.
        if (fs.existsSync(path.resolve(nodeModuleBase, name.split("/")[0]))) {
          return require(nodeModuleDir);
        }

        try {
          return require(name);
        } catch (e) {
          // Try to guess the package name so we can print a nice
          // error message
          // fileInfo.path is a standard path, use files.pathSep
          var filePathParts = fileInfo.path.split(files.pathSep);
          var packageName = filePathParts[1].replace(/\.js$/, '');

          // XXX better message
          throw new Error(
            "Can't find npm module '" + name +
              "'. Did you forget to call 'Npm.depends' in package.js " +
              "within the '" + packageName + "' package?");
          }
      }
    };
    var getAsset = function (assetPath, encoding, callback) {
      var fut;
      if (! callback) {
        fut = new Future();
        callback = fut.resolver();
      }
      // This assumes that we've already loaded the meteor package, so meteor
      // itself (and weird special cases like js-analyze) can't call
      // Assets.get*. (We could change this function so that it doesn't call
      // bindEnvironment if you don't pass a callback if we need to.)
      var _callback = Package.meteor.Meteor.bindEnvironment(function (err, result) {
        if (result && ! encoding)
          // Sadly, this copies in Node 0.10.
          result = new Uint8Array(result);
        callback(err, result);
      }, function (e) {
        console.log("Exception in callback of getAsset", e.stack);
      });

      // Convert a DOS-style path to Unix-style in case the application code was
      // written on Windows.
      assetPath = files.convertToStandardPath(assetPath);

      if (!fileInfo.assets || !_.has(fileInfo.assets, assetPath)) {
        _callback(new Error("Unknown asset: " + assetPath));
      } else {
        var filePath = path.join(serverDir, fileInfo.assets[assetPath]);
        fs.readFile(files.convertToOSPath(filePath), encoding, _callback);
      }
      if (fut)
        return fut.wait();
    };

    var Assets = {
      getText: function (assetPath, callback) {
        return getAsset(assetPath, "utf8", callback);
      },
      getBinary: function (assetPath, callback) {
        return getAsset(assetPath, undefined, callback);
      }
    };

    // \n is necessary in case final line is a //-comment
    var wrapped = "(function(Npm, Assets){" + code + "\n})";

    // It is safer to use the absolute path when source map is present as
    // different tooling, such as node-inspector, can get confused on relative
    // urls.

    // fileInfo.path is a standard path, convert it to OS path to join with
    // __dirname
    var fileInfoOSPath = files.convertToOSPath(fileInfo.path);
    var absoluteFilePath = path.resolve(__dirname, fileInfoOSPath);

    var scriptPath =
      parsedSourceMaps[absoluteFilePath] ? absoluteFilePath : fileInfoOSPath;
    // The final 'true' is an undocumented argument to runIn[Foo]Context that
    // causes it to print out a descriptive error message on parse error. It's
    // what require() uses to generate its errors.
    var func = require('vm').runInThisContext(wrapped, scriptPath, true);
    func.call(global, Npm, Assets); // Coffeescript
  });

  // run the user startup hooks.  other calls to startup() during this can still
  // add hooks to the end.
  while (__meteor_bootstrap__.startupHooks.length) {
    var hook = __meteor_bootstrap__.startupHooks.shift();
    hook();
  }
  // Setting this to null tells Meteor.startup to call hooks immediately.
  __meteor_bootstrap__.startupHooks = null;

  // find and run main()
  // XXX hack. we should know the package that contains main.
  var mains = [];
  var globalMain;
  if ('main' in global) {
    mains.push(main);
    globalMain = main;
  }
  typeof Package !== 'undefined' && _.each(Package, function (p, n) {
    if ('main' in p && p.main !== globalMain) {
      mains.push(p.main);
    }
  });
  if (! mains.length) {
    process.stderr.write("Program has no main() function.\n");
    process.exit(1);
  }
  if (mains.length > 1) {
    process.stderr.write("Program has more than one main() function?\n");
    process.exit(1);
  }
  var exitCode = mains[0].call({}, process.argv.slice(3));
  // XXX hack, needs a better way to keep alive
  if (exitCode !== 'DAEMON')
    process.exit(exitCode);

  if (process.env.METEOR_PARENT_PID) {
    startCheckForLiveParent(process.env.METEOR_PARENT_PID);
  }
}).run();
<|endoftext|>


<commit_before>var camera, scene, renderer, viewSyncEffect, material, pano_url, videoTexture, ws, mesh;
var _xTwist = 0, _yTwist = 0, _zTwist = 0;

var isUserInteracting = false,
    onMouseDownMouseX = 0, onMouseDownMouseY = 0,
    lon = 0, onMouseDownLon = 0,
    lat = 0, onMouseDownLat = 0,
    phi = 0, theta = 0;

pano_url = '../media/harvard-hall_6277-pano6432r.jpg';

function pano_runner() {
  init();
  animate(0);
}

function getConfig(key, def) {
  key = key.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  var regex = new RegExp("[\\?&]" + key + "=([^&#]*)"),
      results = regex.exec(location.search);
  return results === null ? def : decodeURIComponent(results[1].replace(/\+/g, " "));
}

function init() {

  var container, vertFov;
  var config;

  ros = new ROSLIB.Ros({ url : 'ws://localhost:9090' });

  ros.on('connection', function() {
    console.log("Connected to rosbridge");
  });

  ros.on('error', function(e) {
    console.log("rosbridge error: " + e);
  });

  ros.on('close', function() {
    console.log("Disconnected from rosbridge");
  });

  povListener = new ROSLIB.Topic({
    ros : ros,
    name : '/panoviewer/pov',
    messageType : 'geometry_msgs/Quaternion'
  });

  povListener.subscribe(function(msg) {
    _xTwist = msg.x;
    _yTwist = msg.y;
    _zTwist = msg.z;
  });

  panoListener = new ROSLIB.Topic({
    ros : ros,
    name : '/panoviewer/pano',
    messageType : 'std_msgs/String'
  });

  panoListener.subscribe(function(msg) {
    console.log("Received new pano: " + msg.data);
    pano_url = msg.data;
  });

  var initPublisher = new ROSLIB.Topic({
    ros : ros,
    name : '/panoviewer/init',
    messageType : 'std_msgs/String'
  })

  // If you do this immediately, you tend not to catch the responses
  window.setTimeout( function() {
    initPublisher.publish(new ROSLIB.Message({ data: "Hello" }));
  }, 250);

  container = document.getElementById( 'container' );

  vertFov = getConfig('vertFov', 75);
  camera = new THREE.PerspectiveCamera( vertFov, window.innerWidth / window.innerHeight, 1, 1100 );
  camera.target = new THREE.Quaternion(0, 0, 0, 0);

  scene = new THREE.Scene();

  mesh = getMesh();

  //var path = "textures/downsize/ov2_point5_50per_q90/";
  var path = "../media/"
  var format = '.jpg';
  /*
  var urls = [
    path + 'px' + format, path + 'nx' + format,
         path + 'py' + format, path + 'ny' + format,
         path + 'pz' + format, path + 'nz' + format
           ];
  */
  var urls = [
    path + 'harvard-hall_6277-pano6432r' + format,
    path + 'panorama-YDFq-5cL4hqTkx5Bg0yFQA-1.png'
  ];

  var cubeTexture = THREE.ImageUtils.loadTextureCube( urls );
  cubeTexture.format = THREE.RGBFormat;
  //material = new THREE.MeshBasicMaterial( {
  //    map: cubeTexture,
  //    side: THREE.BackSide
  //} );

  var shader = THREE.ShaderLib[ "cube" ];
  shader.uniforms[ "tCube" ].value = cubeTexture;
  material = new THREE.ShaderMaterial( {
    fragmentShader: shader.fragmentShader,
    vertexShader: shader.vertexShader,
    uniforms: shader.uniforms,
    depthWrite: false,
    side: THREE.BackSide
  });

  //mesh = new THREE.Mesh( new THREE.BoxGeometry( 100, 100, 100 ), material );

  scene.add(mesh);
  scene.add(camera);

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  container.appendChild( renderer.domElement );

  // viewSyncEffect.configure( {
  //     slave: getConfig('slave', false),
  //     pitch: getConfig('pitch', 0.0) * 1.0,
  //      roll: getConfig('roll',  0.0) * 1.0,
  //       yaw: getConfig('yaw',   0.0) * 1.0
  // });

  document.addEventListener( 'mousedown', onDocumentMouseDown, false );
  document.addEventListener( 'mousemove', onDocumentMouseMove, false );
  document.addEventListener( 'mouseup', onDocumentMouseUp, false );

  window.addEventListener( 'resize', onWindowResize, false );
}

function navigationCallback(navData) {
  var NAV_SENSITIVITY = 0.01;
  var NAV_GUTTER_VALUE = 2 * NAV_SENSITIVITY;
  for (var axis in navData.abs) {
    switch(axis) {
      case '3':
        value = navData.abs[axis] * NAV_SENSITIVITY;
        if( Math.abs( value ) > NAV_GUTTER_VALUE ) {
          lat += value;
        }
        break;
      case '5':
        value = navData.abs[axis] * NAV_SENSITIVITY;
        if( Math.abs( value ) > NAV_GUTTER_VALUE ) {
          lon += value;
        }
        break;
    }
  }
}

function loadNewTexture(url, type) {
  var texture;

  document.getElementById('info').innerText = 'Loading image...';
  console.log("Loading texture " + url + " of type " + type);
  var proxyUrl = "http://" + window.location.host + "/proxy?query=" + url;
  if (type === 'video') {
    videoTexture = new THREEx.VideoTexture(url);
    //videoTexture = new THREEx.VideoTexture(proxyUrl);
    texture = videoTexture.texture;
    texture.needsUpdate = true;
  }
  else {
    var canvas = document.createElement('canvas');
    videoTexture = undefined;
    canvas.style.position = 'absolute';
    canvas.style.top = '0';
    canvas.style.left = '0';
    texture = new THREE.Texture(canvas);

    var img = new Image();
    img.crossOrigin = 'anonymous';
    img.onload = function() {
      canvas.width = img.width;
      canvas.height = img.height;
      var context = canvas.getContext('2d');
      context.drawImage(img, 0, 0);
      texture.needsUpdate = true;
      document.getElementById('info').innerText = '';
    };
    img.src = url;
    //img.src = proxyUrl;
  }
  return texture;
}

function extraVSCallback(data) {
  if (data.type === 'pano' && data.fileurl !== pano_url) {
    material.map = loadNewTexture(data.fileurl, data.filetype);
    material.map.needsUpdate = true;
    pano_url = data.fileurl;
  }
}

function onWindowResize() {

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize( window.innerWidth, window.innerHeight );

}

function onDocumentMouseDown( event ) {

  event.preventDefault();

  isUserInteracting = true;

  onPointerDownPointerX = event.clientX;
  onPointerDownPointerY = event.clientY;

  onPointerDownLon = lon;
  onPointerDownLat = lat;

}

function onDocumentMouseMove( event ) {

  if ( isUserInteracting === true ) {

    lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
    lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;

  }

}

function onDocumentMouseUp( event ) {

  isUserInteracting = false;

}

/*            function onDocumentMouseWheel( event ) {

// WebKit

if ( event.wheelDeltaY ) {

camera.fov -= event.wheelDeltaY * 0.05;

// Opera / Explorer 9

} else if ( event.wheelDelta ) {

camera.fov -= event.wheelDelta * 0.05;

// Firefox

} else if ( event.detail ) {

camera.fov += event.detail * 1.0;

}

camera.updateProjectionMatrix();

} */

function animate(nowMsec) {

  requestAnimationFrame( animate );
  update(nowMsec);

}

function update(nowMsec) {

  // viewSyncEffect.extraInfo({'type': 'pano', 'fileurl' : pano_url});
  if (typeof(videoTexture) !== 'undefined') {
    videoTexture.update(.2, nowMsec - 100 / 6);
  }
  scene.children[0] = getMesh();
  // viewSyncEffect.render( scene, camera );
  renderer.render(scene, camera);

  // if (! viewSyncEffect.isSlave()) {
  //     lat = Math.max( - 85, Math.min( 85, lat ) );
  //     phi = THREE.Math.degToRad( 90 - lat );
  //     theta = THREE.Math.degToRad( lon );

  //     camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
  //     camera.target.y = 500 * Math.cos( phi );
  //     camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );

  //     camera.lookAt( camera.target );
  // }
}

function getMesh() {
  setQuaternion();
  if (mesh != null && mesh.material.map.sourceFile === pano_url)
    return mesh;

  mesh = new THREE.Mesh(
      new THREE.SphereGeometry(100, 32, 32),
      new THREE.MeshBasicMaterial({
        map: THREE.ImageUtils.loadTexture(pano_url)
      })
  );
  mesh.scale.x = -1;
  return mesh;
}

function setQuaternion() {
  if (mesh == null)
    return;
  mesh.quaternion.x = _xTwist;
  mesh.quaternion.y = -_yTwist;
  //mesh.quaternion.z = _zTwist;
}
<commit_msg>lg_pano: camera.rotation.{x,z} makes for a better experience<commit_after>var camera, scene, renderer, viewSyncEffect, material, pano_url, videoTexture, ws, mesh;
var _xTwist = 0, _yTwist = 0, _zTwist = 0;

var isUserInteracting = false,
    onMouseDownMouseX = 0, onMouseDownMouseY = 0,
    lon = 0, onMouseDownLon = 0,
    lat = 0, onMouseDownLat = 0,
    phi = 0, theta = 0;

pano_url = '../media/harvard-hall_6277-pano6432r.jpg';

function pano_runner() {
  init();
  animate(0);
}

function getConfig(key, def) {
  key = key.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  var regex = new RegExp("[\\?&]" + key + "=([^&#]*)"),
      results = regex.exec(location.search);
  return results === null ? def : decodeURIComponent(results[1].replace(/\+/g, " "));
}

function init() {

  var container, vertFov;
  var config;

  ros = new ROSLIB.Ros({ url : 'ws://localhost:9090' });

  ros.on('connection', function() {
    console.log("Connected to rosbridge");
  });

  ros.on('error', function(e) {
    console.log("rosbridge error: " + e);
  });

  ros.on('close', function() {
    console.log("Disconnected from rosbridge");
  });

  povListener = new ROSLIB.Topic({
    ros : ros,
    name : '/panoviewer/pov',
    throttle_rate: 33,
    queue_length: 1,
    messageType : 'geometry_msgs/Quaternion'
  });

  povListener.subscribe(function(msg) {
    _xTwist = msg.x;
    _yTwist = msg.y;
    _zTwist = msg.z;
  });

  panoListener = new ROSLIB.Topic({
    ros : ros,
    name : '/panoviewer/pano',
    messageType : 'std_msgs/String'
  });

  panoListener.subscribe(function(msg) {
    console.log("Received new pano: " + msg.data);
    pano_url = msg.data;
  });

  var initPublisher = new ROSLIB.Topic({
    ros : ros,
    name : '/panoviewer/init',
    messageType : 'std_msgs/String'
  })

  // If you do this immediately, you tend not to catch the responses
  window.setTimeout( function() {
    initPublisher.publish(new ROSLIB.Message({ data: "Hello" }));
  }, 250);

  container = document.getElementById( 'container' );

  vertFov = getConfig('vertFov', 75);
  camera = new THREE.PerspectiveCamera( vertFov, window.innerWidth / window.innerHeight, 1, 1100 );
  camera.target = new THREE.Quaternion(0, 0, 0, 0);

  scene = new THREE.Scene();

  mesh = getMesh();

  //var path = "textures/downsize/ov2_point5_50per_q90/";
  var path = "../media/"
  var format = '.jpg';
  /*
  var urls = [
    path + 'px' + format, path + 'nx' + format,
         path + 'py' + format, path + 'ny' + format,
         path + 'pz' + format, path + 'nz' + format
           ];
  */
  var urls = [
    path + 'harvard-hall_6277-pano6432r' + format,
    path + 'panorama-YDFq-5cL4hqTkx5Bg0yFQA-1.png'
  ];

  var cubeTexture = THREE.ImageUtils.loadTextureCube( urls );
  cubeTexture.format = THREE.RGBFormat;
  //material = new THREE.MeshBasicMaterial( {
  //    map: cubeTexture,
  //    side: THREE.BackSide
  //} );

  var shader = THREE.ShaderLib[ "cube" ];
  shader.uniforms[ "tCube" ].value = cubeTexture;
  material = new THREE.ShaderMaterial( {
    fragmentShader: shader.fragmentShader,
    vertexShader: shader.vertexShader,
    uniforms: shader.uniforms,
    depthWrite: false,
    side: THREE.BackSide
  });

  //mesh = new THREE.Mesh( new THREE.BoxGeometry( 100, 100, 100 ), material );

  scene.add(mesh);
  scene.add(camera);

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  container.appendChild( renderer.domElement );

  // viewSyncEffect.configure( {
  //     slave: getConfig('slave', false),
  //     pitch: getConfig('pitch', 0.0) * 1.0,
  //      roll: getConfig('roll',  0.0) * 1.0,
  //       yaw: getConfig('yaw',   0.0) * 1.0
  // });

  document.addEventListener( 'mousedown', onDocumentMouseDown, false );
  document.addEventListener( 'mousemove', onDocumentMouseMove, false );
  document.addEventListener( 'mouseup', onDocumentMouseUp, false );

  window.addEventListener( 'resize', onWindowResize, false );
}

function navigationCallback(navData) {
  var NAV_SENSITIVITY = 0.01;
  var NAV_GUTTER_VALUE = 2 * NAV_SENSITIVITY;
  for (var axis in navData.abs) {
    switch(axis) {
      case '3':
        value = navData.abs[axis] * NAV_SENSITIVITY;
        if( Math.abs( value ) > NAV_GUTTER_VALUE ) {
          lat += value;
        }
        break;
      case '5':
        value = navData.abs[axis] * NAV_SENSITIVITY;
        if( Math.abs( value ) > NAV_GUTTER_VALUE ) {
          lon += value;
        }
        break;
    }
  }
}

function loadNewTexture(url, type) {
  var texture;

  document.getElementById('info').innerText = 'Loading image...';
  console.log("Loading texture " + url + " of type " + type);
  var proxyUrl = "http://" + window.location.host + "/proxy?query=" + url;
  if (type === 'video') {
    videoTexture = new THREEx.VideoTexture(url);
    //videoTexture = new THREEx.VideoTexture(proxyUrl);
    texture = videoTexture.texture;
    texture.needsUpdate = true;
  }
  else {
    var canvas = document.createElement('canvas');
    videoTexture = undefined;
    canvas.style.position = 'absolute';
    canvas.style.top = '0';
    canvas.style.left = '0';
    texture = new THREE.Texture(canvas);

    var img = new Image();
    img.crossOrigin = 'anonymous';
    img.onload = function() {
      canvas.width = img.width;
      canvas.height = img.height;
      var context = canvas.getContext('2d');
      context.drawImage(img, 0, 0);
      texture.needsUpdate = true;
      document.getElementById('info').innerText = '';
    };
    img.src = url;
    //img.src = proxyUrl;
  }
  return texture;
}

function extraVSCallback(data) {
  if (data.type === 'pano' && data.fileurl !== pano_url) {
    material.map = loadNewTexture(data.fileurl, data.filetype);
    material.map.needsUpdate = true;
    pano_url = data.fileurl;
  }
}

function onWindowResize() {

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize( window.innerWidth, window.innerHeight );

}

function onDocumentMouseDown( event ) {

  event.preventDefault();

  isUserInteracting = true;

  onPointerDownPointerX = event.clientX;
  onPointerDownPointerY = event.clientY;

  onPointerDownLon = lon;
  onPointerDownLat = lat;

}

function onDocumentMouseMove( event ) {

  if ( isUserInteracting === true ) {

    lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
    lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;

  }

}

function onDocumentMouseUp( event ) {

  isUserInteracting = false;

}

/*            function onDocumentMouseWheel( event ) {

// WebKit

if ( event.wheelDeltaY ) {

camera.fov -= event.wheelDeltaY * 0.05;

// Opera / Explorer 9

} else if ( event.wheelDelta ) {

camera.fov -= event.wheelDelta * 0.05;

// Firefox

} else if ( event.detail ) {

camera.fov += event.detail * 1.0;

}

camera.updateProjectionMatrix();

} */

function animate(nowMsec) {

  requestAnimationFrame( animate );
  update(nowMsec);

}

function update(nowMsec) {

  // viewSyncEffect.extraInfo({'type': 'pano', 'fileurl' : pano_url});
  if (typeof(videoTexture) !== 'undefined') {
    videoTexture.update(.2, nowMsec - 100 / 6);
  }
  scene.children[0] = getMesh();
  // viewSyncEffect.render( scene, camera );
  renderer.render(scene, camera);

  // if (! viewSyncEffect.isSlave()) {
  //     lat = Math.max( - 85, Math.min( 85, lat ) );
  //     phi = THREE.Math.degToRad( 90 - lat );
  //     theta = THREE.Math.degToRad( lon );

  //     camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
  //     camera.target.y = 500 * Math.cos( phi );
  //     camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );

  //     camera.lookAt( camera.target );
  // }
}

function getMesh() {
  setQuaternion();
  if (mesh != null && mesh.material.map.sourceFile === pano_url)
    return mesh;

  mesh = new THREE.Mesh(
      new THREE.SphereGeometry(100, 32, 32),
      new THREE.MeshBasicMaterial({
        map: THREE.ImageUtils.loadTexture(pano_url)
      })
  );
  mesh.scale.x = -1;
  return mesh;
}

function setQuaternion() {
  if (mesh == null)
    return;
  camera.rotation.x = toRad(_xTwist);
  //camera.rotation.z = toRad(_yTwist);
  camera.rotation.y = toRad(_zTwist);
}

function toRad(deg) {
  return THREE.Math.degToRad(deg);
}
<|endoftext|>


<commit_before>define([
    'jquery',
    'oroui/js/app/views/base/view'
], function($, BaseView) {
    'use strict';

    var CalendarEventAllDayView;
    CalendarEventAllDayView = BaseView.extend({

        /**
         * Options
         */
        options: {},

        autoRender: true,

        events: {
            'change input[name$="[allDay]"]': 'onAllDayChange'
        },

        startAtTimeElement: null,
        oldStartAtValue: null,

        endAtTimeElement: null,
        oldEndAtValue: null,

        /**
         * @inheritDoc
         */
        constructor: function CalendarEventAllDayView() {
            CalendarEventAllDayView.__super__.constructor.apply(this, arguments);
        },

        render: function() {
            this.handleAllDayEventFlag(this.$('input[name$="[allDay]"]'), 0);
        },

        onAllDayChange: function(event) {
            this.handleAllDayEventFlag($(event.target), 200);
        },

        handleAllDayEventFlag: function(allDayEventElement, animationDuration) {
            if (!this.startAtTimeElement) {
                var startAtElements = this.$('input[name$="[start]"]').closest('.control-group-datetime');
                this.startAtTimeElement = startAtElements.find('.timepicker-input');
            }
            if (!this.endAtTimeElement) {
                var endAtElements = this.$('input[name$="[end]"]').closest('.control-group-datetime');
                this.endAtTimeElement = endAtElements.find('.timepicker-input');
            }
            if (allDayEventElement.prop('checked')) {
                this.oldStartAtValue = this.startAtTimeElement.timepicker('getTime');
                this.oldEndAtValue = this.endAtTimeElement.timepicker('getTime');

                this.startAtTimeElement.hide(animationDuration, function() {
                    $(this).timepicker('setTime', 0).trigger('change');
                });
                this.endAtTimeElement.hide(animationDuration, function() {
                    $(this).timepicker('setTime', '11:59pm').trigger('change');
                });
            } else {
                if (this.oldStartAtValue) {
                    this.startAtTimeElement.timepicker('setTime', this.oldStartAtValue).trigger('change');
                }
                if (this.oldEndAtValue) {
                    this.endAtTimeElement.timepicker('setTime', this.oldEndAtValue).trigger('change');
                }

                this.startAtTimeElement.show(animationDuration);
                this.endAtTimeElement.show(animationDuration);
            }
        }
    });

    return CalendarEventAllDayView;
});
<commit_msg>BAP-18779: Randomly failing behat create_calendar_events.feature (#23685)<commit_after>define([
    'jquery',
    'oroui/js/app/views/base/view'
], function($, BaseView) {
    'use strict';

    var CalendarEventAllDayView;
    CalendarEventAllDayView = BaseView.extend({

        /**
         * Options
         */
        options: {},

        autoRender: true,

        events: {
            'change input[name$="[allDay]"]': 'onAllDayChange'
        },

        startAtTimeElement: null,
        oldStartAtValue: null,

        endAtTimeElement: null,
        oldEndAtValue: null,

        /**
         * @inheritDoc
         */
        constructor: function CalendarEventAllDayView() {
            CalendarEventAllDayView.__super__.constructor.apply(this, arguments);
        },

        render: function() {
            this.handleAllDayEventFlag(this.$('input[name$="[allDay]"]'), 0);
        },

        onAllDayChange: function(event) {
            this.handleAllDayEventFlag($(event.target), 200);
        },

        handleAllDayEventFlag: function(allDayEventElement, animationDuration) {
            if (!this.startAtTimeElement) {
                var startAtElements = this.$('input[name$="[start]"]').closest('.control-group-datetime');
                this.startAtTimeElement = startAtElements.find('.timepicker-input');
            }
            if (!this.endAtTimeElement) {
                var endAtElements = this.$('input[name$="[end]"]').closest('.control-group-datetime');
                this.endAtTimeElement = endAtElements.find('.timepicker-input');
            }
            if (allDayEventElement.prop('checked')) {
                this.oldStartAtValue = this.startAtTimeElement.timepicker('getTime');
                this.oldEndAtValue = this.endAtTimeElement.timepicker('getTime');

                this.startAtTimeElement.hide(animationDuration, function() {
                    $(this).timepicker('setTime', 0).trigger('change');
                });
                this.endAtTimeElement.hide(animationDuration, function() {
                    $(this).timepicker('setTime', '11:59pm').trigger('change');
                });
            } else {
                this.startAtTimeElement.show({
                    duration: animationDuration,
                    start: function() {
                        if (this.oldStartAtValue) {
                            this.startAtTimeElement.timepicker('setTime', this.oldStartAtValue).trigger('change');
                        }
                    }.bind(this)
                });

                this.endAtTimeElement.show({
                    duration: animationDuration,
                    start: function() {
                        if (this.oldEndAtValue) {
                            this.endAtTimeElement.timepicker('setTime', this.oldEndAtValue).trigger('change');
                        }
                    }.bind(this)
                });
            }
        }
    });

    return CalendarEventAllDayView;
});
<|endoftext|>