<commit_before>import classNames from 'classnames';
import {Confirm} from 'reactjs-components';
import {Link} from 'react-router';
import moment from 'moment';
import mixin from 'reactjs-mixin';
/* eslint-disable no-unused-vars */
import React from 'react';
/* eslint-enable no-unused-vars */
import {StoreMixin} from 'mesosphere-shared-reactjs';
import {Table} from 'reactjs-components';

import AlertPanel from '../../components/AlertPanel';
import DCOSStore from '../../stores/DCOSStore';
import Icon from '../../components/Icon';
import MarathonActions from '../../events/MarathonActions';
import NestedServiceLinks from '../../components/NestedServiceLinks';
import ResourceTableUtil from '../../utils/ResourceTableUtil';
import StringUtil from '../../utils/StringUtil';

const columnHeading = ResourceTableUtil.renderHeading({
  id: 'AFFECTED SERVICES',
  startTime: 'STARTED',
  location: 'LOCATION',
  status: 'STATUS',
  action: ''
});
const COLLAPSING_COLUMNS = ['location', 'startTime', 'action'];
const METHODS_TO_BIND = [
  'renderAffectedServices',
  'renderAffectedServicesList',
  'renderLocation',
  'renderStartTime',
  'renderStatus',
  'renderAction',
  'handleRollbackClick',
  'handleRollbackCancel',
  'handleRollbackConfirm',
  'onMarathonStoreDeploymentRollbackSuccess',
  'onMarathonStoreDeploymentRollbackError'
];

// collapsing columns are tightly coupled to the left-align caret property;
// this wrapper allows ordinary columns to collapse.
function columnClassNameGetter(prop, sortBy, row) {
  let classSet = ResourceTableUtil.getClassName(prop, sortBy, row);
  if (COLLAPSING_COLUMNS.includes(prop)) {
    return classNames(classSet, 'hidden-mini');
  }
  return classSet;
}

class DeploymentsTab extends mixin(StoreMixin) {

  constructor() {
    super(...arguments);

    this.state = {};
    this.store_listeners = [
      {name: 'dcos', events: ['change']},
      {
        name: 'marathon',
        events: ['deploymentRollbackSuccess', 'deploymentRollbackError']
      }
    ];

    METHODS_TO_BIND.forEach((method) => {
      this[method] = this[method].bind(this);
    }, this);
  }

  onMarathonStoreDeploymentRollbackSuccess(data) {
    let {deploymentToRollback} = this.state;
    if (deploymentToRollback != null &&
        deploymentToRollback.getId() === data.originalDeploymentID) {
      this.setState({
        awaitingRevertDeploymentResponse: false,
        deploymentToRollback: null,
        deploymentRollbackError: null
      });
    }
  }

  onMarathonStoreDeploymentRollbackError(data) {
    let {deploymentToRollback} = this.state;
    if (deploymentToRollback != null &&
        deploymentToRollback.getId() === data.originalDeploymentID) {
      this.setState({
        awaitingRevertDeploymentResponse: false,
        deploymentRollbackError: data.error
      });
    }
  }

  renderAffectedServices(prop, deployment) {
    return (

{deployment.getId()}

        {this.renderAffectedServicesList(deployment.getAffectedServices())}

    );
  }

  renderAffectedServicesList(services) {
    return services.map(function (service, index) {
      const id = encodeURIComponent(service.getId());
      const image = service.getImages()['icon-small'];

      return (

          <Link to="services-detail" params={{id}} className="deployment-service-name">

            {StringUtil.capitalize(service.getName())}
          </Link>

      );
    });
  }

  renderLocation(prop, deployment) {
    const services = deployment.getAffectedServices();
    const items = services.map(function (service, index) {
      return (

          <NestedServiceLinks
            serviceID={service.getId()}
            className="deployment-breadcrumb"
            majorLinkClassName="deployment-breadcrumb-service-id"
            minorLinkWrapperClassName="deployment-breadcrumb-crumb" />

      );
    });

    return (

        {items}

    );
  }

  renderStartTime(prop, deployment) {
    const time = deployment.getStartTime();

    return (
      <time dateTime={time.toISOString()} className="deployment-start-time">
        {moment(time).fromNow()}
      </time>
    );
  }

  renderStatus(prop, deployment) {
    const title = `Step ${deployment.getCurrentStep()} of ${deployment.getTotalSteps()}`;
    const services = deployment.getAffectedServices();
    const items = services.map(function (service, index) {
      return (

          {service.getStatus()}

      );
    });

    return (

        {title}

{items}

    );
  }

  renderAction(prop, deployment) {
    if (deployment != null) {
      let linkText = 'Rollback';
      if (deployment.isStarting()) {
        linkText = linkText + ' & Remove';
      }
      return (

          {linkText}

      );
    }
  }

  handleRollbackClick(deployment) {
    this.setState({deploymentToRollback: deployment});
  }

  handleRollbackCancel() {
    this.setState({
      awaitingRevertDeploymentResponse: false,
      deploymentToRollback: null,
      deploymentRollbackError: null
    });
  }

  handleRollbackConfirm() {
    let {deploymentToRollback} = this.state;
    if (deploymentToRollback != null) {
      this.setState({awaitingRevertDeploymentResponse: true});
      MarathonActions.revertDeployment(deploymentToRollback.getId());
    }
  }

  getColumns() {
    return [
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'id',
        render: this.renderAffectedServices
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'location',
        render: this.renderLocation
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'startTime',
        render: this.renderStartTime
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'status',
        render: this.renderStatus
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'action',
        render: this.renderAction
      }
    ];
  }

  getColGroup() {
    return (
      <colgroup>
        <col style={{width: '300px'}} />
        <col className="hidden-mini" />
        <col className="hidden-mini" style={{width: '120px'}} />
        <col style={{width: '240px'}} />
        <col className="hidden-mini" style={{width: '160px'}} />
      </colgroup>
    );
  }

  renderEmpty() {
    return (
      <AlertPanel
        title="No Deployments"
        icon={<Icon id="services" color="white" size="jumbo" />}>

Active deployments will be shown here.

      </AlertPanel>
    );
  }

  renderPopulated(deploymentsItems) {
    let deploymentsCount = deploymentsItems.length;
    let deploymentsLabel = StringUtil.pluralize('Deployment', deploymentsCount);

    return (

          {deploymentsCount} Active {deploymentsLabel}

        {this.renderRollbackModal()}

    );
  }

  renderRollbackModal() {
    let {
      awaitingRevertDeploymentResponse,
      deploymentToRollback,
      deploymentRollbackError
    } = this.state;

    if (deploymentToRollback != null) {
      return (
        <Confirm
          closeByBackdropClick={true}
          disabled={!!awaitingRevertDeploymentResponse}
          footerContainerClass="container container-pod container-pod-short
            container-pod-fluid flush-top flush-bottom"
          onClose={this.handleRollbackCancel}
          leftButtonCallback={this.handleRollbackCancel}
          leftButtonText="Cancel"
          rightButtonClassName="button button-danger"
          rightButtonCallback={this.handleRollbackConfirm}
          rightButtonText="Continue Rollback">

You're About To Rollback The Deployment

{this.getRollbackModalText(deploymentToRollback)}

            {this.renderRollbackError(deploymentRollbackError)}

        </Confirm>
      );
    }
  }

  getRollbackModalText(deploymentToRollback) {
    let serviceNames = deploymentToRollback.getAffectedServices()
      .map(function (service) {
        return StringUtil.capitalize(service.getName());
      });
    let listOfServiceNames = StringUtil.humanizeArray(serviceNames);
    let serviceCount = serviceNames.length;

    let service = StringUtil.pluralize('service', serviceCount);
    let its = (serviceCount === 1) ? 'its' : 'their';
    let version = StringUtil.pluralize('version', serviceCount);

    if (deploymentToRollback.isStarting()) {
      return `This will stop the current deployment of ${listOfServiceNames}
              and start a new deployment to remove the affected ${service}.`
    }

    return `This will stop the current deployment of ${listOfServiceNames} and
            start a new deployment to revert the affected ${service} to ${its}
            previous ${version}.`
  }

  renderRollbackError(deploymentRollbackError) {
    if (deploymentRollbackError != null) {
      return (

          {deploymentRollbackError}

      );
    }
  }

  render() {
    let deployments = DCOSStore.deploymentsList.getItems();

    if (deployments.length === 0) {
      return this.renderEmpty();
    } else {
      return this.renderPopulated(deployments);
    }
  }

}

module.exports = DeploymentsTab;

<commit_msg>Dont capitalize deployments table<commit_after>import classNames from 'classnames';
import {Confirm} from 'reactjs-components';
import {Link} from 'react-router';
import moment from 'moment';
import mixin from 'reactjs-mixin';
/* eslint-disable no-unused-vars */
import React from 'react';
/* eslint-enable no-unused-vars */
import {StoreMixin} from 'mesosphere-shared-reactjs';
import {Table} from 'reactjs-components';

import AlertPanel from '../../components/AlertPanel';
import DCOSStore from '../../stores/DCOSStore';
import Icon from '../../components/Icon';
import MarathonActions from '../../events/MarathonActions';
import NestedServiceLinks from '../../components/NestedServiceLinks';
import ResourceTableUtil from '../../utils/ResourceTableUtil';
import StringUtil from '../../utils/StringUtil';

const columnHeading = ResourceTableUtil.renderHeading({
  id: 'AFFECTED SERVICES',
  startTime: 'STARTED',
  location: 'LOCATION',
  status: 'STATUS',
  action: ''
});
const COLLAPSING_COLUMNS = ['location', 'startTime', 'action'];
const METHODS_TO_BIND = [
  'renderAffectedServices',
  'renderAffectedServicesList',
  'renderLocation',
  'renderStartTime',
  'renderStatus',
  'renderAction',
  'handleRollbackClick',
  'handleRollbackCancel',
  'handleRollbackConfirm',
  'onMarathonStoreDeploymentRollbackSuccess',
  'onMarathonStoreDeploymentRollbackError'
];

// collapsing columns are tightly coupled to the left-align caret property;
// this wrapper allows ordinary columns to collapse.
function columnClassNameGetter(prop, sortBy, row) {
  let classSet = ResourceTableUtil.getClassName(prop, sortBy, row);
  if (COLLAPSING_COLUMNS.includes(prop)) {
    return classNames(classSet, 'hidden-mini');
  }
  return classSet;
}

class DeploymentsTab extends mixin(StoreMixin) {

  constructor() {
    super(...arguments);

    this.state = {};
    this.store_listeners = [
      {name: 'dcos', events: ['change']},
      {
        name: 'marathon',
        events: ['deploymentRollbackSuccess', 'deploymentRollbackError']
      }
    ];

    METHODS_TO_BIND.forEach((method) => {
      this[method] = this[method].bind(this);
    }, this);
  }

  onMarathonStoreDeploymentRollbackSuccess(data) {
    let {deploymentToRollback} = this.state;
    if (deploymentToRollback != null &&
        deploymentToRollback.getId() === data.originalDeploymentID) {
      this.setState({
        awaitingRevertDeploymentResponse: false,
        deploymentToRollback: null,
        deploymentRollbackError: null
      });
    }
  }

  onMarathonStoreDeploymentRollbackError(data) {
    let {deploymentToRollback} = this.state;
    if (deploymentToRollback != null &&
        deploymentToRollback.getId() === data.originalDeploymentID) {
      this.setState({
        awaitingRevertDeploymentResponse: false,
        deploymentRollbackError: data.error
      });
    }
  }

  renderAffectedServices(prop, deployment) {
    return (

{deployment.getId()}

        {this.renderAffectedServicesList(deployment.getAffectedServices())}

    );
  }

  renderAffectedServicesList(services) {
    return services.map(function (service, index) {
      const id = encodeURIComponent(service.getId());
      const image = service.getImages()['icon-small'];

      return (

          <Link to="services-detail" params={{id}} className="deployment-service-name">

            {service.getName()}
          </Link>

      );
    });
  }

  renderLocation(prop, deployment) {
    const services = deployment.getAffectedServices();
    const items = services.map(function (service, index) {
      return (

          <NestedServiceLinks
            serviceID={service.getId()}
            className="deployment-breadcrumb"
            majorLinkClassName="deployment-breadcrumb-service-id"
            minorLinkWrapperClassName="deployment-breadcrumb-crumb" />

      );
    });

    return (

        {items}

    );
  }

  renderStartTime(prop, deployment) {
    const time = deployment.getStartTime();

    return (
      <time dateTime={time.toISOString()} className="deployment-start-time">
        {moment(time).fromNow()}
      </time>
    );
  }

  renderStatus(prop, deployment) {
    const title = `Step ${deployment.getCurrentStep()} of ${deployment.getTotalSteps()}`;
    const services = deployment.getAffectedServices();
    const items = services.map(function (service, index) {
      return (

          {service.getStatus()}

      );
    });

    return (

        {title}

{items}

    );
  }

  renderAction(prop, deployment) {
    if (deployment != null) {
      let linkText = 'Rollback';
      if (deployment.isStarting()) {
        linkText = linkText + ' & Remove';
      }
      return (

          {linkText}

      );
    }
  }

  handleRollbackClick(deployment) {
    this.setState({deploymentToRollback: deployment});
  }

  handleRollbackCancel() {
    this.setState({
      awaitingRevertDeploymentResponse: false,
      deploymentToRollback: null,
      deploymentRollbackError: null
    });
  }

  handleRollbackConfirm() {
    let {deploymentToRollback} = this.state;
    if (deploymentToRollback != null) {
      this.setState({awaitingRevertDeploymentResponse: true});
      MarathonActions.revertDeployment(deploymentToRollback.getId());
    }
  }

  getColumns() {
    return [
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'id',
        render: this.renderAffectedServices
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'location',
        render: this.renderLocation
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'startTime',
        render: this.renderStartTime
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'status',
        render: this.renderStatus
      },
      {
        className: columnClassNameGetter,
        heading: columnHeading,
        prop: 'action',
        render: this.renderAction
      }
    ];
  }

  getColGroup() {
    return (
      <colgroup>
        <col style={{width: '300px'}} />
        <col className="hidden-mini" />
        <col className="hidden-mini" style={{width: '120px'}} />
        <col style={{width: '240px'}} />
        <col className="hidden-mini" style={{width: '160px'}} />
      </colgroup>
    );
  }

  renderEmpty() {
    return (
      <AlertPanel
        title="No Deployments"
        icon={<Icon id="services" color="white" size="jumbo" />}>

Active deployments will be shown here.

      </AlertPanel>
    );
  }

  renderPopulated(deploymentsItems) {
    let deploymentsCount = deploymentsItems.length;
    let deploymentsLabel = StringUtil.pluralize('Deployment', deploymentsCount);

    return (

          {deploymentsCount} Active {deploymentsLabel}

        {this.renderRollbackModal()}

    );
  }

  renderRollbackModal() {
    let {
      awaitingRevertDeploymentResponse,
      deploymentToRollback,
      deploymentRollbackError
    } = this.state;

    if (deploymentToRollback != null) {
      return (
        <Confirm
          closeByBackdropClick={true}
          disabled={!!awaitingRevertDeploymentResponse}
          footerContainerClass="container container-pod container-pod-short
            container-pod-fluid flush-top flush-bottom"
          onClose={this.handleRollbackCancel}
          leftButtonCallback={this.handleRollbackCancel}
          leftButtonText="Cancel"
          rightButtonClassName="button button-danger"
          rightButtonCallback={this.handleRollbackConfirm}
          rightButtonText="Continue Rollback">

You're About To Rollback The Deployment

{this.getRollbackModalText(deploymentToRollback)}

            {this.renderRollbackError(deploymentRollbackError)}

        </Confirm>
      );
    }
  }

  getRollbackModalText(deploymentToRollback) {
    let serviceNames = deploymentToRollback.getAffectedServices()
      .map(function (service) {
        return StringUtil.capitalize(service.getName());
      });
    let listOfServiceNames = StringUtil.humanizeArray(serviceNames);
    let serviceCount = serviceNames.length;

    let service = StringUtil.pluralize('service', serviceCount);
    let its = (serviceCount === 1) ? 'its' : 'their';
    let version = StringUtil.pluralize('version', serviceCount);

    if (deploymentToRollback.isStarting()) {
      return `This will stop the current deployment of ${listOfServiceNames}
              and start a new deployment to remove the affected ${service}.`
    }

    return `This will stop the current deployment of ${listOfServiceNames} and
            start a new deployment to revert the affected ${service} to ${its}
            previous ${version}.`
  }

  renderRollbackError(deploymentRollbackError) {
    if (deploymentRollbackError != null) {
      return (

          {deploymentRollbackError}

      );
    }
  }

  render() {
    let deployments = DCOSStore.deploymentsList.getItems();

    if (deployments.length === 0) {
      return this.renderEmpty();
    } else {
      return this.renderPopulated(deployments);
    }
  }

}

module.exports = DeploymentsTab;

<|endoftext|>


<commit_before>/*
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(function() {

  var isServer = typeof process === 'object';

  function createLoadBrowser() {
    // Web Worker case // TODO: auto-determine path to core
    if ( typeof document == 'undefined' && typeof importScripts !== 'undefined' ) {
      var path = FOAM_BOOT_PATH;
      return function(file) {
        importScripts(path+file+'.js');
      }
    }

    var path = document.currentScript && document.currentScript.src;

    // document.currentScript isn't supported on all browsers, so the following
    // hack gets the job done on those browsers.
    if ( ! path ) {
      var scripts = document.getElementsByTagName('script');
      for ( var i = 0 ; i < scripts.length ; i++ ) {
        if ( scripts[i].src.match(/\/bootFOAM.js$/) ) {
          path = scripts[i].src;
          break;
        }
      }
    }

    path = path.substring(0, path.lastIndexOf('/')+1);

    return function(filename) {
      document.writeln(
        '<script type="text/javascript" src="' + path + filename + '.js"></script>\n');
    }
  }

  function loadServer(filename) {
    require('./' + filename + '.js');
  }

  [
    "stdlib",
    "array",
    "events",
    "fn",
    "string",
    "compare",
    "date",
    "Context",
    "Boot",
    "Slot",
    "Window",
    "JSON",
    "objects",
    "patterns",
    "debug",
    "types",
    "parse",
    "templates",
    "Action",
    [ "../lib/graphics", ! isServer ],
    "../lib/dao",
    [ "../lib/node/json_dao", isServer ],
  ].
      filter(function (f) { return ! Array.isArray(f) || f[1]; }).
      map(function(f) { return Array.isArray(f) ? f[0] : f; }).
      forEach(isServer ? loadServer : createLoadBrowser());
})();
<commit_msg>Cleanup loading in web worker.<commit_after>/*
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

(function() {

  var isServer = typeof process === 'object';
  var isWorker = typeof importScripts !== 'undefined';

  function createLoadBrowser() {
    var path = document.currentScript && document.currentScript.src;

    // document.currentScript isn't supported on all browsers, so the following
    // hack gets the job done on those browsers.
    if ( ! path ) {
      var scripts = document.getElementsByTagName('script');
      for ( var i = 0 ; i < scripts.length ; i++ ) {
        if ( scripts[i].src.match(/\/foam.js$/) ) {
          path = scripts[i].src;
          break;
        }
      }
    }

    path = path.substring(0, path.lastIndexOf('/')+1);

    return function(filename) {
      document.writeln(
        '<script type="text/javascript" src="' + path + filename + '.js"></script>\n');
    }
  }

  function loadServer(filename) {
    require('./' + filename + '.js');
  }

  function createLoadWorker(filename) {
    var path = FOAM_BOOT_PATH;
    return function(filename) {
      importScripts(path + filename + '.js');
    };
  }

  [
    "stdlib",
    "array",
    "events",
    "fn",
    "string",
    "compare",
    "date",
    "Context",
    "Boot",
    "Slot",
    "Window",
    "JSON",
    "objects",
    "patterns",
    "debug",
    "types",
    "parse",
    "templates",
    "Action",
    [ "../lib/graphics", ! isServer ],
    "../lib/dao",
    [ "../lib/node/json_dao", isServer ],
    "../lib/box",
  ].
      filter(function (f) { return ! Array.isArray(f) || f[1]; }).
      map(function(f) { return Array.isArray(f) ? f[0] : f; }).
      forEach(isServer ? loadServer :
              isWorker ? createLoadWorker() :
              createLoadBrowser());
})();
<|endoftext|>


<commit_before>// Copyright 2002-2012, University of Colorado

/**
 * Basic dragging for a node.
 *
 * TODO: stick node in place if ancestor changes transform (while dragging)
 *
 * @author Jonathan Olson <olsonsjc@gmail.com>
 */

var scenery = scenery || {};

(function(){
  "use strict";

  /*
   * Allowed options: {
   *    allowTouchSnag: false // allow touch swipes across an object to pick it up,
   *    start: null           // if non-null, called when a drag is started. start( finger, trail, event )
   *    end: null             // if non-null, called when a drag is ended.   end( finger, trail, event )
   * }
   */
  scenery.SimpleDragHandler = function( options ) {
    var handler = this;

    this.options = options;

    this.dragging              = false;     // whether a node is being dragged with this handler
    this.finger                = null;      // the finger doing the current dragging
    this.trail                 = null;      // stores the path to the node that is being dragged
    this.transform             = null;      // transform of the trail to our node (but not including our node, so we can prepend the deltas)
    this.node                  = null;      // the node that we are handling the drag for
    this.lastDragPoint         = null;      // the location of the drag at the previous event (so we can calculate a delta)
    this.startTransformMatrix  = null;      // the node's transform at the start of the drag, so we can reset on a touch cancel
    this.mouseButton           = undefined; // tracks which mouse button was pressed, so we can handle that specifically
    // TODO: consider mouse buttons as separate fingers?

    // this listener gets added to the finger when it starts dragging our node
    this.dragListener = {
      // mouse/touch up
      up: function( finger, trail, event ) {
        phet.assert( finger === handler.finger );
        if ( !finger.isMouse || event.button === handler.mouseButton ) {
          handler.endDrag( event );
        }
      },

      // touch cancel
      cancel: function( finger, trail, event ) {
        phet.assert( finger === handler.finger );
        handler.endDrag( event );

        // since it's a cancel event, go back!
        this.node.setMatrix( handler.startTransformMatrix );
      },

      // mouse/touch move
      move: function( finger, trail, event ) {
        phet.assert( finger === handler.finger );
        // move by the delta between the previous point, using the precomputed transform
        // prepend the translation on the node, so we can ignore whatever other transform state the node has
        this.node.translate( handler.transform.inverseDelta2( finger.point.minus( handler.lastDragPoint ) ), true );
        handler.lastDragPoint = finger.point;
      }
    };
  };
  var SimpleDragHandler = scenery.SimpleDragHandler;

  SimpleDragHandler.prototype = {
    constructor: SimpleDragHandler,

    startDrag: function( finger, trail, event, currentTarget ) {
      // set a flag on the finger so it won't pick up other nodes
      finger.dragging = true;
      finger.addInputListener( this.dragListener );

      // set all of our persistent information
      this.dragging = true;
      this.finger = finger;
      this.trail = trail.subtrailTo( currentTarget, true );
      this.transform = this.trail.getTransform();
      this.node = currentTarget;
      this.lastDragPoint = finger.point;
      this.startTransformMatrix = currentTarget.getMatrix();
      this.mouseButton = event.button; // should be undefined for touch events

      if ( this.options.start ) {
        this.options.start( finger, this.trail, event );
      }
    },

    endDrag: function( event ) {
      this.finger.dragging = false;
      this.finger.removeInputListener( this.dragListener );
      this.dragging = false;

      if ( this.options.end ) {
        this.options.end( this.finger, this.trail, event );
      }
    },

    tryToSnag: function( finger, trail, event, currentTarget ) {
      // only start dragging if the finger isn't dragging anything, we aren't being dragged, and if it's a mouse it's button is down
      if ( !this.dragging && !finger.dragging ) {
        this.startDrag( finger, trail, event, currentTarget );
      }
    },

    /*---------------------------------------------------------------------------*
    * events called from the input listener
    *----------------------------------------------------------------------------*/

    // mouse/touch down on this node
    down: function( finger, trail, event, currentTarget ) {
      this.tryToSnag( finger, trail, event, currentTarget );
    },

    // mouse/touch enters this node
    enter: function( finger, trail, event, currentTarget ) {
      // allow touches to start a drag by moving "over" this node
      if ( this.options.allowTouchSnag && !finger.isMouse ) {
        this.tryToSnag( finger, trail, event, currentTarget );
      }
    }
  };

})();

<commit_msg>Drag handler bugfix<commit_after>// Copyright 2002-2012, University of Colorado

/**
 * Basic dragging for a node.
 *
 * TODO: stick node in place if ancestor changes transform (while dragging)
 *
 * @author Jonathan Olson <olsonsjc@gmail.com>
 */

var scenery = scenery || {};

(function(){
  "use strict";

  /*
   * Allowed options: {
   *    allowTouchSnag: false // allow touch swipes across an object to pick it up,
   *    start: null           // if non-null, called when a drag is started. start( finger, trail, event )
   *    end: null             // if non-null, called when a drag is ended.   end( finger, trail, event )
   * }
   */
  scenery.SimpleDragHandler = function( options ) {
    var handler = this;

    this.options = options;

    this.dragging              = false;     // whether a node is being dragged with this handler
    this.finger                = null;      // the finger doing the current dragging
    this.trail                 = null;      // stores the path to the node that is being dragged
    this.transform             = null;      // transform of the trail to our node (but not including our node, so we can prepend the deltas)
    this.node                  = null;      // the node that we are handling the drag for
    this.lastDragPoint         = null;      // the location of the drag at the previous event (so we can calculate a delta)
    this.startTransformMatrix  = null;      // the node's transform at the start of the drag, so we can reset on a touch cancel
    this.mouseButton           = undefined; // tracks which mouse button was pressed, so we can handle that specifically
    // TODO: consider mouse buttons as separate fingers?

    // this listener gets added to the finger when it starts dragging our node
    this.dragListener = {
      // mouse/touch up
      up: function( finger, trail, event ) {
        phet.assert( finger === handler.finger );
        if ( !finger.isMouse || event.button === handler.mouseButton ) {
          handler.endDrag( event );
        }
      },

      // touch cancel
      cancel: function( finger, trail, event ) {
        phet.assert( finger === handler.finger );
        handler.endDrag( event );

        // since it's a cancel event, go back!
        handler.node.setMatrix( handler.startTransformMatrix );
      },

      // mouse/touch move
      move: function( finger, trail, event ) {
        phet.assert( finger === handler.finger );
        // move by the delta between the previous point, using the precomputed transform
        // prepend the translation on the node, so we can ignore whatever other transform state the node has
        handler.node.translate( handler.transform.inverseDelta2( finger.point.minus( handler.lastDragPoint ) ), true );
        handler.lastDragPoint = finger.point;
      }
    };
  };
  var SimpleDragHandler = scenery.SimpleDragHandler;

  SimpleDragHandler.prototype = {
    constructor: SimpleDragHandler,

    startDrag: function( finger, trail, event, currentTarget ) {
      // set a flag on the finger so it won't pick up other nodes
      finger.dragging = true;
      finger.addInputListener( this.dragListener );

      // set all of our persistent information
      this.dragging = true;
      this.finger = finger;
      this.trail = trail.subtrailTo( currentTarget, true );
      this.transform = this.trail.getTransform();
      this.node = currentTarget;
      this.lastDragPoint = finger.point;
      this.startTransformMatrix = currentTarget.getMatrix();
      this.mouseButton = event.button; // should be undefined for touch events

      if ( this.options.start ) {
        this.options.start( finger, this.trail, event );
      }
    },

    endDrag: function( event ) {
      this.finger.dragging = false;
      this.finger.removeInputListener( this.dragListener );
      this.dragging = false;

      if ( this.options.end ) {
        this.options.end( this.finger, this.trail, event );
      }
    },

    tryToSnag: function( finger, trail, event, currentTarget ) {
      // only start dragging if the finger isn't dragging anything, we aren't being dragged, and if it's a mouse it's button is down
      if ( !this.dragging && !finger.dragging ) {
        this.startDrag( finger, trail, event, currentTarget );
      }
    },

    /*---------------------------------------------------------------------------*
    * events called from the input listener
    *----------------------------------------------------------------------------*/

    // mouse/touch down on this node
    down: function( finger, trail, event, currentTarget ) {
      this.tryToSnag( finger, trail, event, currentTarget );
    },

    // mouse/touch enters this node
    enter: function( finger, trail, event, currentTarget ) {
      // allow touches to start a drag by moving "over" this node
      if ( this.options.allowTouchSnag && !finger.isMouse ) {
        this.tryToSnag( finger, trail, event, currentTarget );
      }
    }
  };

})();

<|endoftext|>


<commit_before>import p5 from '../core/main';

/**
 * _globalInit
 *
 * TODO: ???
 * if sketch is on window
 * assume "global" mode
 * and instantiate p5 automatically
 * otherwise do nothing
 *
 * @private
 * @return {Undefined}
 */
const _globalInit = () => {
  if (!window.mocha) {
    // If there is a setup or draw function on the window
    // then instantiate p5 in "global" mode
    if (
      ((window.setup && typeof window.setup === 'function') ||
        (window.draw && typeof window.draw === 'function')) &&
      !p5.instance
    ) {
      new p5();
    }
  }
};

// TODO: ???

// if the page is ready, initialize p5 immediately
if (document.readyState === 'complete') {
  _globalInit();
  // if the page is still loading, add an event listener
  // and initialize p5 as soon as it finishes loading
} else {
  window.addEventListener('load', _globalInit, false);
}
<commit_msg>force loading translations before we init p5<commit_after>import p5 from '../core/main';
import { initialize as initTranslator } from './internationalization';

/**
 * _globalInit
 *
 * TODO: ???
 * if sketch is on window
 * assume "global" mode
 * and instantiate p5 automatically
 * otherwise do nothing
 *
 * @private
 * @return {Undefined}
 */
const _globalInit = () => {
  if (!window.mocha) {
    // If there is a setup or draw function on the window
    // then instantiate p5 in "global" mode
    if (
      ((window.setup && typeof window.setup === 'function') ||
        (window.draw && typeof window.draw === 'function')) &&
      !p5.instance
    ) {
      new p5();
    }
  }
};

// TODO: ???

// make a promise that resolves when the document is ready
const waitForDocumentReady = () =>
  new Promise((resolve, reject) => {
    // if the page is ready, initialize p5 immediately
    if (document.readyState === 'complete') {
      resolve();
      // if the page is still loading, add an event listener
      // and initialize p5 as soon as it finishes loading
    } else {
      window.addEventListener('load', resolve, false);
    }
  });

Promise.all([waitForDocumentReady(), initTranslator()]).then(_globalInit);
<|endoftext|>


<commit_before>export default {
  'hasSection8.label':        'Do you have Section 8 Housing?',
  'hasSection8.hint':         'Section 8 provides rental housing assistance.',
  'hasSnap.label':            'Do you have SNAP?',
  'hasSnap.hint':             'SNAP provides assistance with buying food',
  'hasEarnedIncome.label':    'Do you have earned income?',
  'hasEarnedIncome.hint':     'Earned income is income from wages or self-employment',
  'hasTAFDC.label':           'Do you have TAFDC?',
  'hasTAFDC.hint':            'Transitional Aid to Families with Dependent Children provides short-term financial assistance to families with children',
  'hasSSI.label':             'Do you have SSI?',
  'hasSSI.hint':              'Supplemental Security Income is a federal program that provides financial and health care assistance to people 65 and over, or people who are blind or disabled',
  'hasSSDI.label':            'Do you have SSDI?',
  'hasSSDI.hint':             'Social Security Disability Income is a federal program to help people with disabilities',
  'hasChildSupport.label':    'Do you receive child support?',
  'hasChildSupport.hint':     'Child support is money paid to you by a former spouse to help your child',
  'hasUnemployment.label':    'Do you receive unemployment benefits?',
  'hasUnemployment.hint':     'Unemployment benefits provide income to people who have been laid off',
  'hasWorkersComp.label':     'Do you receive Workers Compensation?',
  'hasWorkersComp.hint':      'Workers Compensation provides assistance for people who have been injured on the job',
  'hasPension.label':         'Do you have a pension?',
  'hasPension.hint':          'A pension provides income to retirees, usually from their former employers',
  'hasSocialSecurity.label':  'Do you have Social Security Income?',
  'hasSocialSecurity.hint':   'Social Security is a federal program that provides assistance to retirees',
  'hasAlimony.label':         'Do you receive alimony?',
  'hasAlimony.hint':          'Alimony is money paid by one spouse to the other after a divorce',
  'hasOtherIncome.label':     'Do you have other income?',
  'hasOtherIncome.hint':      'Please note income you may have from sources that are not listed above',
};
<commit_msg>Runs lint fix on newly merged code<commit_after>export default {
  'hasSection8.label':       'Do you have Section 8 Housing?',
  'hasSection8.hint':        'Section 8 provides rental housing assistance.',
  'hasSnap.label':           'Do you have SNAP?',
  'hasSnap.hint':            'SNAP provides assistance with buying food',
  'hasEarnedIncome.label':   'Do you have earned income?',
  'hasEarnedIncome.hint':    'Earned income is income from wages or self-employment',
  'hasTAFDC.label':          'Do you have TAFDC?',
  'hasTAFDC.hint':           'Transitional Aid to Families with Dependent Children provides short-term financial assistance to families with children',
  'hasSSI.label':            'Do you have SSI?',
  'hasSSI.hint':             'Supplemental Security Income is a federal program that provides financial and health care assistance to people 65 and over, or people who are blind or disabled',
  'hasSSDI.label':           'Do you have SSDI?',
  'hasSSDI.hint':            'Social Security Disability Income is a federal program to help people with disabilities',
  'hasChildSupport.label':   'Do you receive child support?',
  'hasChildSupport.hint':    'Child support is money paid to you by a former spouse to help your child',
  'hasUnemployment.label':   'Do you receive unemployment benefits?',
  'hasUnemployment.hint':    'Unemployment benefits provide income to people who have been laid off',
  'hasWorkersComp.label':    'Do you receive Workers Compensation?',
  'hasWorkersComp.hint':     'Workers Compensation provides assistance for people who have been injured on the job',
  'hasPension.label':        'Do you have a pension?',
  'hasPension.hint':         'A pension provides income to retirees, usually from their former employers',
  'hasSocialSecurity.label': 'Do you have Social Security Income?',
  'hasSocialSecurity.hint':  'Social Security is a federal program that provides assistance to retirees',
  'hasAlimony.label':        'Do you receive alimony?',
  'hasAlimony.hint':         'Alimony is money paid by one spouse to the other after a divorce',
  'hasOtherIncome.label':    'Do you have other income?',
  'hasOtherIncome.hint':     'Please note income you may have from sources that are not listed above',
};
<|endoftext|>


<commit_before>jest.dontMock('../DOMUtils');

var DOMUtils = require('../DOMUtils');

describe('DOMUtils', function () {

  describe('#getComputedWidth', function () {
    function buildElement(style) {
      return `<div style="${style.join(';')}"></div>`;
    }

    beforeEach(function () {
      this.style = [
        'width: 100px'
      ];
    });

    it('calculates left padding', function () {
      this.style.push('padding-left: 1px');
      document.body.innerHTML = buildElement(this.style);

      // jsdom doesn't calculate
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates right padding', function () {
      this.style.push('padding-right: 1px');
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates left border', function () {
      this.style.push('border-left-width: 1px');
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates right border', function () {
      this.style.push('border-right-width: 1px');
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates computed width', function () {
      this.style.push(
        'padding-left: 1px',
        'padding-right: 1px',
        'border-left-width: 1px',
        'border-right-width: 1px'
      );
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 104;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('does not calculate unnecessary properties', function () {
      this.style.push(
        'padding-top: 1px',
        'padding-bottom: 1px',
        'border-top-width: 1px',
        'border-bottom-width: 1px'
      );
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 100;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

  });

  describe('#scrollTo', function () {
    beforeEach(function () {
      this.previousRequest = global.requestAnimationFrame;
      global.requestAnimationFrame = function (func) {
        setTimeout(func, 15);
      };

      this.dateNow = Date.now;
      // Will return 0, 15, 30, 45, 60, etc.
      // adding setTimeout call time each time
      var now = -15;
      Date.now = function () {
        now += 15;
        return now;
      };
    });

    afterEach(function () {
      global.requestAnimationFrame = this.previousRequest;
      Date.now = this.dateNow;
    });

    it('doesn\'t do anything if already scrolled there', function () {
      var container = {scrollTop: 500, scrollHeight: 1500};
      DOMUtils.scrollTo(container, 1000, 500);
      expect(container.scrollTop).toEqual(500);
    });

    it('begins heading towards the target pixel', function () {
      var container = {scrollTop: 500, scrollHeight: 1500};
      DOMUtils.scrollTo(container, 1000, 1000);
      jest.runAllTimers();
      expect(container.scrollTop).toBeGreaterThan(1000);
    });

    it('stops after scrollDuration has passed', function () {
      var container = {scrollTop: 500, scrollHeight: 1500};
      DOMUtils.scrollTo(container, 1500, 1000);
      var callCount = 0;
      global.requestAnimationFrame = function (func) {
        callCount++;
        setTimeout(func, 15);
        // Reset scrollTop to stay in the same spot
        container.scrollTop = 500;
      };
      jest.runAllTimers();
      // We expect the call count to be scrollDuration / timeout call time
      expect(callCount).toEqual(1500 / 15);
    });
  });

  describe('#isElementOnTop', function () {
    beforeEach(function () {
      this.element = {
        getBoundingClientRect: function () {
          return {
            top: 100,
            left: 200,
            height: 20,
            width: 40
          };
        },
        contains: function (el) {
          return this === el;
        }
      }
      this.prevElementFromPoint = global.document.elementFromPoint;
    });

    afterEach(function () {
      global.document.elementFromPoint = this.prevElementFromPoint;
    });

    it('should return false if element is not at coord', function () {
      global.document.elementFromPoint = function () {
        return 'hi';
      };

      let result = DOMUtils.isElementOnTop(this.element);
      expect(result).toEqual(false);
    });

    it('should return true if element is at coord', function () {
      global.document.elementFromPoint = () => {
        return this.element;
      };

      let result = DOMUtils.isElementOnTop(this.element);
      expect(result).toEqual(true);
    });
  });

  describe('#getDistanceFromTopOfParent', function () {
    beforeEach(function () {
      this.element = {
        getBoundingClientRect: function () {
          return {
            top: 300
          };
        },
        parentNode: {
          getBoundingClientRect: function () {
            return {
              top: 200
            };
          }
        }
      }
    });

    it('gets the correct distance from parent top', function () {
      var result = DOMUtils.getDistanceFromTopOfParent(this.element);

      expect(result).toEqual(100);
    });

    it('returns 0 if there is no parentNode', function () {
      let prevParentNode = this.element.parentNode;
      this.element.parentNode = null;

      var result = DOMUtils.getDistanceFromTopOfParent(this.element);
      expect(result).toEqual(0);

      this.element.parentNode = prevParentNode;
    });
  });
});
<commit_msg>Fix domutils test<commit_after>jest.dontMock('../DOMUtils');

var DOMUtils = require('../DOMUtils');

describe('DOMUtils', function () {

  describe('#getComputedWidth', function () {
    function buildElement(style) {
      return `<div style="${style.join(';')}"></div>`;
    }

    beforeEach(function () {
      this.style = [
        'width: 100px'
      ];
    });

    it('calculates left padding', function () {
      this.style.push('padding-left: 1px');
      document.body.innerHTML = buildElement(this.style);

      // jsdom doesn't calculate
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates right padding', function () {
      this.style.push('padding-right: 1px');
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates left border', function () {
      this.style.push('border-left-width: 1px');
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates right border', function () {
      this.style.push('border-right-width: 1px');
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 101;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('calculates computed width', function () {
      this.style.push(
        'padding-left: 1px',
        'padding-right: 1px',
        'border-left-width: 1px',
        'border-right-width: 1px'
      );
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 104;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

    it('does not calculate unnecessary properties', function () {
      this.style.push(
        'padding-top: 1px',
        'padding-bottom: 1px',
        'border-top-width: 1px',
        'border-bottom-width: 1px'
      );
      document.body.innerHTML = buildElement(this.style);
      document.querySelector('div').offsetWidth = 100;

      var width = DOMUtils.getComputedWidth(document.querySelector('div'));
      expect(width).toEqual(100);
    });

  });

  describe('#scrollTo', function () {
    beforeEach(function () {
      this.previousRequest = global.requestAnimationFrame;
      global.requestAnimationFrame = function (func) {
        setTimeout(func, 15);
      };

      this.dateNow = Date.now;
      // Will return 0, 15, 30, 45, 60, etc.
      // adding setTimeout call time each time
      var now = -15;
      Date.now = function () {
        now += 15;
        return now;
      };
    });

    afterEach(function () {
      global.requestAnimationFrame = this.previousRequest;
      Date.now = this.dateNow;
    });

    it('doesn\'t do anything if already scrolled there', function () {
      var container = {scrollTop: 500, scrollHeight: 1500};
      DOMUtils.scrollTo(container, 1000, 500);
      expect(container.scrollTop).toEqual(500);
    });

    it('begins heading towards the target pixel', function () {
      var container = {scrollTop: 500, scrollHeight: 1500};
      DOMUtils.scrollTo(container, 1000, 1000);
      jest.runAllTimers();
      expect(container.scrollTop).toBeGreaterThan(1000);
    });

    it('stops after scrollDuration has passed', function () {
      var container = {scrollTop: 500, scrollHeight: 1500};
      DOMUtils.scrollTo(container, 1500, 1000);
      var callCount = 0;
      global.requestAnimationFrame = function (func) {
        callCount++;
        setTimeout(func, 15);
        // Reset scrollTop to stay in the same spot
        container.scrollTop = 500;
      };
      jest.runAllTimers();
      // We expect the call count to be scrollDuration / timeout call time
      expect(callCount).toEqual(1500 / 15);
    });
  });

  describe('#isElementOnTop', function () {
    beforeEach(function () {
      this.element = {
        getBoundingClientRect: function () {
          return {
            top: 100,
            left: 200,
            height: 20,
            width: 40
          };
        },
        contains: function (el) {
          return this === el;
        }
      }
      this.prevElementFromPoint = global.document.elementFromPoint;
    });

    afterEach(function () {
      global.document.elementFromPoint = this.prevElementFromPoint;
    });

    it('should return false if element is not at coord', function () {
      global.document.elementFromPoint = function () {
        return {
          contains: function () {return false;}
        };
      };

      let result = DOMUtils.isElementOnTop(this.element);
      expect(result).toEqual(false);
    });

    it('should return true if element is at coord', function () {
      global.document.elementFromPoint = () => {
        return this.element;
      };

      let result = DOMUtils.isElementOnTop(this.element);
      expect(result).toEqual(true);
    });
  });

  describe('#getDistanceFromTopOfParent', function () {
    beforeEach(function () {
      this.element = {
        getBoundingClientRect: function () {
          return {
            top: 300
          };
        },
        parentNode: {
          getBoundingClientRect: function () {
            return {
              top: 200
            };
          }
        }
      }
    });

    it('gets the correct distance from parent top', function () {
      var result = DOMUtils.getDistanceFromTopOfParent(this.element);

      expect(result).toEqual(100);
    });

    it('returns 0 if there is no parentNode', function () {
      let prevParentNode = this.element.parentNode;
      this.element.parentNode = null;

      var result = DOMUtils.getDistanceFromTopOfParent(this.element);
      expect(result).toEqual(0);

      this.element.parentNode = prevParentNode;
    });
  });
});
<|endoftext|>


<commit_before>import VideoUtils from '../../util/videoUtils';

module.exports = {
    getBlocks() {
        return {
            learning_title_image: {
                skeleton: 'basic_text',
                color: EntryStatic.colorSet.common.TRANSPARENT,
                params: [
                    {
                        type: 'Text',
                        text: Lang.template.learning_title_image,
                        color: EntryStatic.colorSet.common.TEXT,
                        align: 'center',
                    },
                ],
                def: {
                    type: 'learning_title_image',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_image'],
                events: {},
            },
            learning_title_speech: {
                skeleton: 'basic_text',
                color: EntryStatic.colorSet.common.TRANSPARENT,
                params: [
                    {
                        type: 'Text',
                        text: Lang.template.learning_title_speech,
                        color: EntryStatic.colorSet.common.TEXT,
                        align: 'center',
                    },
                ],
                def: {
                    type: 'learning_title_speech',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_speech'],
                events: {},
            },
            learning_title_text: {
                skeleton: 'basic_text',
                color: EntryStatic.colorSet.common.TRANSPARENT,
                params: [
                    {
                        type: 'Text',
                        text: Lang.template.learning_title_text,
                        color: EntryStatic.colorSet.common.TEXT,
                        align: 'center',
                    },
                ],
                def: {
                    type: 'learning_title_text',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_text'],
                events: {},
            },
            insert_data_for_test: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic',
                statements: [],
                params: [
                    {
                        type: 'Indicator',
                        img: 'block_icon/ai_utilize_icon.svg',
                        size: 11,
                    },
                ],
                events: {},
                def: {
                    params: [
                        null,
                    ],
                    type: 'insert_data_for_test',
                },
                pyHelpDef: {
                    params: [],
                    type: 'insert_data_for_test',
                },
                paramsKeyMap: {
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                func(sprite, script) {
                    if (!script.isStart) {
                        script.isStart = true;
                        Entry.aiLearning.openInputPopup();
                        return script;
                    }
                    if (!Entry.aiLearning.isLoading) {
                        delete script.isStart;
                        return script.callReturn();
                    }
                    return script;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            insert_text_block_for_test: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic',
                statements: [],
                params: [
                    {
                        type: 'Block',
                        accept: 'string',
                    },
                    {
                        type: 'Indicator',
                        img: 'block_icon/ai_utilize_icon.svg',
                        size: 11,
                    },
                ],
                events: {},
                def: {
                    params: [
                        {
                            type: 'text',
                            params: [Lang.Blocks.entry],
                        },
                        null,
                    ],
                    type: 'insert_text_block_for_test',
                },
                pyHelpDef: {
                    params: [],
                    type: 'insert_text_block_for_test',
                },
                paramsKeyMap: {
                    TEXT: 0,
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_text'],
                async func(sprite, script) {
                    const text = script.getStringValue('TEXT', script);
                    await Entry.aiLearning.predict(text);
                    return script;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            test_result: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic_string_field',
                statements: [],
                params: [],
                events: {},
                def: {
                    params: [null],
                    type: 'test_result',
                },
                pyHelpDef: {
                    params: [],
                    type: 'test_result',
                },
                paramsKeyMap: {
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                func(sprite, script) {
                    return Entry.aiLearning.getResult().className;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            accuracy_of_result: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic_string_field',
                statements: [],
                params: [
                    {
                        type: 'DropdownDynamic',
                        value: null,
                        menuName: () => Entry.aiLearning.labels.map((name, index) => [name, index]),
                        needDeepCopy: true,
                        fontSize: 11,
                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,
                        arrowColor: EntryStatic.colorSet.common.WHITE,
                        defaultValue: (value, options) => {
                            if(options[0] && options[0][1]){
                                return options[0][1];
                            }
                            return value || 0;
                        }
                    }
                ],
                events: {},
                def: {
                    params: [0],
                    type: 'accuracy_of_result',
                },
                pyHelpDef: {
                    params: [],
                    type: 'accuracy_of_result',
                },
                paramsKeyMap: {
                    GROUP: 0,
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                func(sprite, script) {
                    const group = script.getNumberValue('GROUP', script);
                    return Entry.aiLearning.getResult(group).probability;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            is_group: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic_boolean_field',
                statements: [],
                params: [
                    {
                        type: 'DropdownDynamic',
                        value: null,
                        menuName: () => Entry.aiLearning.labels.map((name, index) => [name, index]),
                        needDeepCopy: true,
                        fontSize: 11,
                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,
                        arrowColor: EntryStatic.colorSet.common.WHITE,
                        defaultValue: (value, options) => {
                            if(options[0] && options[0][1]){
                                return options[0][1];
                            }
                            return value || 0;
                        }
                    }
                ],
                events: {},
                def: {
                    params: [0],
                    type: 'is_group',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                paramsKeyMap: {
                    GROUP: 0,
                },
                func(sprite, script) {
                    const group = script.getNumberValue('GROUP', script)
                    const {labels} = Entry.aiLearning;
                    const result = Entry.aiLearning.getResult().className;
                    return result === labels[group];
                },
                syntax: {
                    js: [],
                    py: [],
                },
            }
        };
    },
};
<commit_msg>다국어 처리.<commit_after>import VideoUtils from '../../util/videoUtils';

module.exports = {
    getBlocks() {
        return {
            learning_title_image: {
                skeleton: 'basic_text',
                color: EntryStatic.colorSet.common.TRANSPARENT,
                params: [
                    {
                        type: 'Text',
                        text: Lang.template.learning_title_image_str,
                        color: EntryStatic.colorSet.common.TEXT,
                        align: 'center',
                    },
                ],
                def: {
                    type: 'learning_title_image',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_image'],
                events: {},
            },
            learning_title_speech: {
                skeleton: 'basic_text',
                color: EntryStatic.colorSet.common.TRANSPARENT,
                params: [
                    {
                        type: 'Text',
                        text: Lang.template.learning_title_speech_str,
                        color: EntryStatic.colorSet.common.TEXT,
                        align: 'center',
                    },
                ],
                def: {
                    type: 'learning_title_speech',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_speech'],
                events: {},
            },
            learning_title_text: {
                skeleton: 'basic_text',
                color: EntryStatic.colorSet.common.TRANSPARENT,
                params: [
                    {
                        type: 'Text',
                        text: Lang.template.learning_title_text_str,
                        color: EntryStatic.colorSet.common.TEXT,
                        align: 'center',
                    },
                ],
                def: {
                    type: 'learning_title_text',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_text'],
                events: {},
            },
            insert_data_for_test: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic',
                statements: [],
                params: [
                    {
                        type: 'Indicator',
                        img: 'block_icon/ai_utilize_icon.svg',
                        size: 11,
                    },
                ],
                events: {},
                def: {
                    params: [
                        null,
                    ],
                    type: 'insert_data_for_test',
                },
                pyHelpDef: {
                    params: [],
                    type: 'insert_data_for_test',
                },
                paramsKeyMap: {
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                func(sprite, script) {
                    if (!script.isStart) {
                        script.isStart = true;
                        Entry.aiLearning.openInputPopup();
                        return script;
                    }
                    if (!Entry.aiLearning.isLoading) {
                        delete script.isStart;
                        return script.callReturn();
                    }
                    return script;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            insert_text_block_for_test: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic',
                statements: [],
                params: [
                    {
                        type: 'Block',
                        accept: 'string',
                    },
                    {
                        type: 'Indicator',
                        img: 'block_icon/ai_utilize_icon.svg',
                        size: 11,
                    },
                ],
                events: {},
                def: {
                    params: [
                        {
                            type: 'text',
                            params: [Lang.Blocks.entry],
                        },
                        null,
                    ],
                    type: 'insert_text_block_for_test',
                },
                pyHelpDef: {
                    params: [],
                    type: 'insert_text_block_for_test',
                },
                paramsKeyMap: {
                    TEXT: 0,
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning_text'],
                async func(sprite, script) {
                    const text = script.getStringValue('TEXT', script);
                    await Entry.aiLearning.predict(text);
                    return script;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            test_result: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic_string_field',
                statements: [],
                params: [],
                events: {},
                def: {
                    params: [null],
                    type: 'test_result',
                },
                pyHelpDef: {
                    params: [],
                    type: 'test_result',
                },
                paramsKeyMap: {
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                func(sprite, script) {
                    return Entry.aiLearning.getResult().className;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            accuracy_of_result: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic_string_field',
                statements: [],
                params: [
                    {
                        type: 'DropdownDynamic',
                        value: null,
                        menuName: () => Entry.aiLearning.labels.map((name, index) => [name, index]),
                        needDeepCopy: true,
                        fontSize: 11,
                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,
                        arrowColor: EntryStatic.colorSet.common.WHITE,
                        defaultValue: (value, options) => {
                            if(options[0] && options[0][1]){
                                return options[0][1];
                            }
                            return value || 0;
                        }
                    }
                ],
                events: {},
                def: {
                    params: [0],
                    type: 'accuracy_of_result',
                },
                pyHelpDef: {
                    params: [],
                    type: 'accuracy_of_result',
                },
                paramsKeyMap: {
                    GROUP: 0,
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                func(sprite, script) {
                    const group = script.getNumberValue('GROUP', script);
                    return Entry.aiLearning.getResult(group).probability;
                },
                syntax: {
                    js: [],
                    py: [],
                },
            },
            is_group: {
                color: EntryStatic.colorSet.block.default.AI_LEARNING,
                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,
                skeleton: 'basic_boolean_field',
                statements: [],
                params: [
                    {
                        type: 'DropdownDynamic',
                        value: null,
                        menuName: () => Entry.aiLearning.labels.map((name, index) => [name, index]),
                        needDeepCopy: true,
                        fontSize: 11,
                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,
                        arrowColor: EntryStatic.colorSet.common.WHITE,
                        defaultValue: (value, options) => {
                            if(options[0] && options[0][1]){
                                return options[0][1];
                            }
                            return value || 0;
                        }
                    }
                ],
                events: {},
                def: {
                    params: [0],
                    type: 'is_group',
                },
                class: 'ai_learning',
                isNotFor: ['ai_learning'],
                paramsKeyMap: {
                    GROUP: 0,
                },
                func(sprite, script) {
                    const group = script.getNumberValue('GROUP', script)
                    const {labels} = Entry.aiLearning;
                    const result = Entry.aiLearning.getResult().className;
                    return result === labels[group];
                },
                syntax: {
                    js: [],
                    py: [],
                },
            }
        };
    },
};
<|endoftext|>


<commit_before>/**
* Generated by PluginGenerator from webgme on Wed Apr 16 2014 16:05:02 GMT-0500 (Central Daylight Time).
*/

define(['plugin/PluginConfig', 'plugin/PluginBase', 'ejs', 'plugin/FmiExporter/FmiExporter/Templates/Templates'], function (PluginConfig, PluginBase, EJS, TEMPLATES) {
    'use strict';

    /**
    * Initializes a new instance of FmiExporter.
    * @class
    * @augments {PluginBase}
    * @classdesc This class represents the plugin FmiExporter.
    * @constructor
    */
    var FmiExporter = function () {
        // Call base class' constructor.
        PluginBase.call(this);
    };

    // Prototypal inheritance from PluginBase.
    FmiExporter.prototype = Object.create(PluginBase.prototype);
    FmiExporter.prototype.constructor = FmiExporter;

    if (!ejs) {
        ejs = EJS || window.ejs;
    }

    /**
    * Gets the name of the FmiExporter.
    * @returns {string} The name of the plugin.
    * @public
    */
    FmiExporter.prototype.getName = function () {
        return "FMI ModelExchange Exporter";
    };

    /**
    * Gets the description of the FmiExporter.
    * @returns {string} The description of the plugin.
    * @public
    */
    FmiExporter.prototype.getDescription = function () {
        return "Generates a model_exchange_config.json for simulating a FMI system";
    };

    /**
    * Gets the semantic version (semver.org) of the FmiExporter.
    * @returns {string} The version of the plugin.
    * @public
    */
    FmiExporter.prototype.getVersion = function () {
        return "0.1.0";
    };

    /**
    * Gets the configuration structure for the FmiExporter.
    * The ConfigurationStructure defines the configuration for the plugin
    * and will be used to populate the GUI when invoking the plugin from webGME.
    * @returns {object} The version of the plugin.
    * @public
    */
    FmiExporter.prototype.getConfigStructure = function () {
        return [
            {
                'name': 'species',
                'displayName': 'Animal Species',
                'regex': '^[a-zA-Z]+$',
                'regexMessage': 'Name can only contain English characters!',
                'description': 'Which species does the animal belong to.',
                'value': 'Horse',
                'valueType': 'string',
                'readOnly': false
            },
            {
                'name': 'age',
                'displayName': 'Age',
                'description': 'How old is the animal.',
                'value': 3,
                'valueType': 'number',
                'minValue': 0,
                'maxValue': 10000,
                'readOnly': false
            },
            {
                'name': 'carnivor',
                'displayName': 'Carnivor',
                'description': 'Does the animal eat other animals?',
                'value': false,
                'valueType': 'boolean',
                'readOnly': false
            },
            {
                'name': 'classification',
                'displayName': 'Classification',
                'description': '',
                'value': 'Vertebrates',
                'valueType': 'string',
                'valueItems': [
                    'Vertebrates',
                    'Invertebrates',
                    'Unknown'
                ]
            },
            {
                "name": "color",
                "displayName": "Color",
                "description": 'The hex color code for the animal.',
                "readOnly": false,
                "value": '#FF0000',
                "regex": '^#([A-Fa-f0-9]{6})$',
                "valueType": "string"
            }
        ];
    };

    /**
    * Main function for the plugin to execute. This will perform the execution.
    * Notes:
    * - Always log with the provided logger.[error,warning,info,debug].
    * - Do NOT put any user interaction logic UI, etc. inside this method.
    * - callback always have to be called even if error happened.
    *
    * @param {function(string, plugin.PluginResult)} callback - the result callback
    */
    FmiExporter.prototype.main = function (callback) {
        // Use self to access core, project, result, logger etc from PluginBase.
        // These are all instantiated at this point.
        var self = this;
        self.result.setSuccess(true);

        // Using core to create an object.
        var newNode = self.core.createNode({parent: self.rootNode, base: self.META['FCO']});
        self.core.setAttribute(newNode, 'name', 'My new obj');
        self.core.setRegistry(newNode, 'position', {x: 70, y: 70});

        // Using the logger.
        self.logger.info('This is a debug message.');
        self.logger.info('This is an info message.');
        self.logger.warning('This is a warning message.');
        self.logger.error('This is an error message.');

        // To transform ejs file into js file (needed for client-side runs) run combine_templates
        // see instructions in file. You must run this after any modifications to the ejs template.
        // https://github.com/webgme/webgme-domain-tools/blob/master/src/tools/combine_templates.js
        var templatePY = ejs.render(TEMPLATES['Python.py.ejs'], {a: 'a', b: 'b'});
        // TODO: addFile and saveArtifact are asynchronous functions - insert rest of code before callback.
        //var templateFileName = 'generatedFiles/Python.py'
        // self.fs.addFile(templateFileName, templatePY, function (err) {
        //    self.fs.saveArtifact(function (err, hash) {
        //        //FIXME: All code below needs to go here
        //        callback(null, self.result);
        //    });
        // });

        // TODO: These are asynchronous functions - insert rest of code before callback.
        // self.fs works on both client and server side.
        // self.fs.addFile('dir/subdir/file.txt', 'This is a text file.', function (err) {
        //    self.fs.saveArtifact(function (err, hash) {
        //        //FIXME: All code below needs to go here
        //        callback(null, self.result);
        //    });
        // });

        // Obtain the current user configuration.
        var currentConfig = self.getCurrentConfig();
        self.logger.info('Current configuration ' + JSON.stringify(currentConfig, null, 4));

        // This will save the changes. If you don't want to save;
        // exclude self.save and call callback directly from this scope.
        self.save('added obj', function (err) {
            callback(null, self.result);
        });

    };

    /**
    * Checks if the given node is of the given meta-type.
    * Usage: <tt>self.isMetaTypeOf(aNode, self.META['FCO']);</tt>
    * @param node - Node to be check for type.
    * @param metaTypeObj - Node object defining the meta type.
    * @returns {boolean} - True if the given object was of the META type.
    */
    FmiExporter.prototype.isMetaTypeOf = function (node, metaTypeObj) {
        var self = this;
        while (node) {
            if (self.core.getGuid(node) === self.core.getGuid(metaTypeObj)) {
                return true;
            }
            node = self.core.getBase(node);
        }
        return false;
    };

    /**
    * Finds and returns the node object defining the meta type for the given node.
    * @param node - Node to be check for type.
    * @returns {Object} - Node object defining the meta type of node.
    */
    FmiExporter.prototype.getMetaType = function (node) {
        var self = this,
            name;
        while (node) {
            name = self.core.getAttribute(node, 'name');
            if (self.META.hasOwnProperty(name) && self.core.getPath(self.META[name]) === self.core.getPath(node)) {
                break;
            }
            node = self.core.getBase(node);
        }
        return node;
    };

    return FmiExporter;
});<commit_msg>move code I don't need to a comment<commit_after>/**
* Generated by PluginGenerator from webgme on Wed Apr 16 2014 16:05:02 GMT-0500 (Central Daylight Time).
*/

define(['plugin/PluginConfig', 'plugin/PluginBase', 'ejs', 'plugin/FmiExporter/FmiExporter/Templates/Templates'], function (PluginConfig, PluginBase, EJS, TEMPLATES) {
    'use strict';

    /**
    * Initializes a new instance of FmiExporter.
    * @class
    * @augments {PluginBase}
    * @classdesc This class represents the plugin FmiExporter.
    * @constructor
    */
    var FmiExporter = function () {
        // Call base class' constructor.
        PluginBase.call(this);
    };

    // Prototypal inheritance from PluginBase.
    FmiExporter.prototype = Object.create(PluginBase.prototype);
    FmiExporter.prototype.constructor = FmiExporter;

    if (!ejs) {
        ejs = EJS || window.ejs;
    }

    /**
    * Gets the name of the FmiExporter.
    * @returns {string} The name of the plugin.
    * @public
    */
    FmiExporter.prototype.getName = function () {
        return "FMI ModelExchange Exporter";
    };

    /**
    * Gets the description of the FmiExporter.
    * @returns {string} The description of the plugin.
    * @public
    */
    FmiExporter.prototype.getDescription = function () {
        return "Generates a model_exchange_config.json for simulating a FMI system";
    };

    /**
    * Gets the semantic version (semver.org) of the FmiExporter.
    * @returns {string} The version of the plugin.
    * @public
    */
    FmiExporter.prototype.getVersion = function () {
        return "0.1.0";
    };

    /**
    * Gets the configuration structure for the FmiExporter.
    * The ConfigurationStructure defines the configuration for the plugin
    * and will be used to populate the GUI when invoking the plugin from webGME.
    * @returns {object} The version of the plugin.
    * @public
    */
    FmiExporter.prototype.getConfigStructure = function () {
        return [
            {
                'name': 'species',
                'displayName': 'Animal Species',
                'regex': '^[a-zA-Z]+$',
                'regexMessage': 'Name can only contain English characters!',
                'description': 'Which species does the animal belong to.',
                'value': 'Horse',
                'valueType': 'string',
                'readOnly': false
            },
            {
                'name': 'age',
                'displayName': 'Age',
                'description': 'How old is the animal.',
                'value': 3,
                'valueType': 'number',
                'minValue': 0,
                'maxValue': 10000,
                'readOnly': false
            },
            {
                'name': 'carnivor',
                'displayName': 'Carnivor',
                'description': 'Does the animal eat other animals?',
                'value': false,
                'valueType': 'boolean',
                'readOnly': false
            },
            {
                'name': 'classification',
                'displayName': 'Classification',
                'description': '',
                'value': 'Vertebrates',
                'valueType': 'string',
                'valueItems': [
                    'Vertebrates',
                    'Invertebrates',
                    'Unknown'
                ]
            },
            {
                "name": "color",
                "displayName": "Color",
                "description": 'The hex color code for the animal.',
                "readOnly": false,
                "value": '#FF0000',
                "regex": '^#([A-Fa-f0-9]{6})$',
                "valueType": "string"
            }
        ];
    };

    /**
    * Main function for the plugin to execute. This will perform the execution.
    * Notes:
    * - Always log with the provided logger.[error,warning,info,debug].
    * - Do NOT put any user interaction logic UI, etc. inside this method.
    * - callback always have to be called even if error happened.
    *
    * @param {function(string, plugin.PluginResult)} callback - the result callback
    */
    FmiExporter.prototype.main = function (callback) {
        // Use self to access core, project, result, logger etc from PluginBase.
        // These are all instantiated at this point.
        var self = this;
        self.result.setSuccess(true);

        // Obtain the current user configuration.
        var currentConfig = self.getCurrentConfig();
        self.logger.info('Current configuration ' + JSON.stringify(currentConfig, null, 4));

        // This will save the changes. If you don't want to save;
        // exclude self.save and call callback directly from this scope.
        self.save('added obj', function (err) {
            callback(null, self.result);
        });

    };

    /**
    * Checks if the given node is of the given meta-type.
    * Usage: <tt>self.isMetaTypeOf(aNode, self.META['FCO']);</tt>
    * @param node - Node to be check for type.
    * @param metaTypeObj - Node object defining the meta type.
    * @returns {boolean} - True if the given object was of the META type.
    */
    FmiExporter.prototype.isMetaTypeOf = function (node, metaTypeObj) {
        var self = this;
        while (node) {
            if (self.core.getGuid(node) === self.core.getGuid(metaTypeObj)) {
                return true;
            }
            node = self.core.getBase(node);
        }
        return false;
    };

    /**
    * Finds and returns the node object defining the meta type for the given node.
    * @param node - Node to be check for type.
    * @returns {Object} - Node object defining the meta type of node.
    */
    FmiExporter.prototype.getMetaType = function (node) {
        var self = this,
            name;
        while (node) {
            name = self.core.getAttribute(node, 'name');
            if (self.META.hasOwnProperty(name) && self.core.getPath(self.META[name]) === self.core.getPath(node)) {
                break;
            }
            node = self.core.getBase(node);
        }
        return node;
    };

    return FmiExporter;
});

/**
 // Using core to create an object.
 var newNode = self.core.createNode({parent: self.rootNode, base: self.META['FCO']});
 self.core.setAttribute(newNode, 'name', 'My new obj');
 self.core.setRegistry(newNode, 'position', {x: 70, y: 70});

 // Using the logger.
 self.logger.info('This is a debug message.');
 self.logger.info('This is an info message.');
 self.logger.warning('This is a warning message.');
 self.logger.error('This is an error message.');

 // To transform ejs file into js file (needed for client-side runs) run combine_templates
 // see instructions in file. You must run this after any modifications to the ejs template.
 // https://github.com/webgme/webgme-domain-tools/blob/master/src/tools/combine_templates.js
 var templatePY = ejs.render(TEMPLATES['Python.py.ejs'], {a: 'a', b: 'b'});
 // TODO: addFile and saveArtifact are asynchronous functions - insert rest of code before callback.
 //var templateFileName = 'generatedFiles/Python.py'
 // self.fs.addFile(templateFileName, templatePY, function (err) {
        //    self.fs.saveArtifact(function (err, hash) {
        //        //FIXME: All code below needs to go here
        //        callback(null, self.result);
        //    });
        // });

 // TODO: These are asynchronous functions - insert rest of code before callback.
 // self.fs works on both client and server side.
 // self.fs.addFile('dir/subdir/file.txt', 'This is a text file.', function (err) {
        //    self.fs.saveArtifact(function (err, hash) {
        //        //FIXME: All code below needs to go here
        //        callback(null, self.result);
        //    });
        // });
 */<|endoftext|>


<commit_before>namespace('Sy.View');

/**
 * Default implementation of TemplateEngineInterface
 *
 * @package Sy
 * @subpackage View
 * @class
 * @implements {Sy.View.TemplateEngineInterface}
 */

Sy.View.TemplateEngine = function () {
    Sy.View.TemplateEngineInterface.call(this);
    this.registry = null;
    this.generator = null;
};
Sy.View.TemplateEngine.prototype = Object.create(Sy.View.TemplateEngineInterface.prototype, {

    /**
     * Set registry to hold rendered nodes references
     *
     * @param {Sy.RegistryInterface} registry
     *
     * @return {Sy.View.TemplateEngine}
     */

    setRegistry: {
        value: function (registry) {

            if (!(registry instanceof Sy.RegistryInterface)) {
                throw new TypeError('Invalid registry');
            }

            this.registry = registry;

            return this;

        }
    },

    /**
     * Set a generator to identify each rendered node
     *
     * @param {Sy.Lib.Generator.Interface} generator
     *
     * @return {Sy.View.TemplateEngine}
     */

    setGenerator: {
        value: function (generator) {

            if (!(generator instanceof Sy.Lib.Generator.Interface)) {
                throw new TypeError('Invalid generator');
            }

            this.generator = generator;

            return this;

        }
    },

    /**
     * @inheritDoc
     */

    render: {
        value: function (node, data, exempt) {

            if (!node.dataset.syUuid) {
                this.register(node);
            }

            if (node.dataset.syUuid && this.registry.has(node.dataset.syUuid)) {
                this.renderAllAttributes(node, data);
                this.renderContent(node, data, exempt);
            }

            if (node.childElementCount > 0) {
                for (var i = 0, l = node.childElementCount; i < l; i++) {
                    this.render(node.children[i], data, exempt);
                }
            }

            return node;

        }
    },

    /**
     * Set a UUID on the node and set in the registry all the default attributes and text content
     *
     * @private
     * @param {HTMLElement} node
     *
     * @return {Sy.View.TemplateEngine}
     */

    register: {
        value: function (node) {

            var uuid = this.generator.generate(),
                content = {
                    attributes: {},
                    textContent: null,
                    uuid: uuid
                };

            for (var i = 0, l = node.attributes.length; i < l; i++) {
                content.attributes[node.attributes[i].name] = node.getAttribute(node.attributes[i].name);
            }

            content.textContent = node.textContent;
            node.dataset.syUuid = uuid;
            this.registry.set(uuid, content);

            return this;

        }
    },

    /**
     * Loop an all node attributes and render them
     *
     * @private
     * @param {HTMLElement} node
     * @param {Object} data
     *
     * @return {HTMLElement}
     */

    renderAllAttributes: {
        value: function (node, data) {

            for (var i = 0, l = node.attributes.length; i < l; i++) {
                this.renderAttribute(node, node.attributes[i].name, data);
            }

            return node;

        }
    },

    /**
     * Render a specific attribute on a node
     *
     * @private
     * @param {HTMLElement} node
     * @param {String} attribute
     * @param {Object} data
     *
     * @return {HTMLElement}
     */

    renderAttribute: {
        value: function (node, attribute, data) {

            var uuid = node.dataset.syUuid,
                originalContent = this.registry.get(uuid).attributes[attribute],
                text;

            if (!originalContent) {
                return node;
            }

            text = this.replace(originalContent, data);
            node.setAttribute(attribute, text);

            return node;

        }
    },

    /**
     * Replace {{ \w }} with the approriate data
     *
     * @private
     * @param {string} source
     * @param {Object} data
     *
     * @return {string}
     */

    replace: {
        value: function (source, data) {

            while (source.match(this.PATTERN)) {
                var results = this.PATTERN.exec(source);

                if (results !== null && results.length >= 1) {
                    source = source.replace(results[0], reflectedObjectGetter.call(data, results[1]) || '');
                }
            }

            return source;

        }
    },

    /**
     * Replace textContent placeholders by data
     *
     * @private
     * @param {HTMLElement} node
     * @param {Object} data
     * @param {String} exempt CSS selector to exempt nodes of being rendered
     *
     * @return {void}
     */

    renderContent: {
        value: function (node, data, exempt) {

            if (node.childElementCount > 0) {
                return node;
            }

            if (exempt && DOM(node).matches(exempt)) {
                return node;
            }

            var uuid = node.dataset.syUuid,
                originalContent = this.registry.get(uuid).textContent,
                results = this.PATTERN.exec(originalContent),
                d;

            if (results) {
                d = objectGetter.call(data, results[1]);
            }

            if (d instanceof HTMLElement) {
                node.removeChild(node.firstElementChild);
                node.appendChild(d);
            } else {
                node.textContent = this.replace(originalContent, data);
            }

            return node;

        }
    }

});
<commit_msg>do not try to register a document fragment in template engine<commit_after>namespace('Sy.View');

/**
 * Default implementation of TemplateEngineInterface
 *
 * @package Sy
 * @subpackage View
 * @class
 * @implements {Sy.View.TemplateEngineInterface}
 */

Sy.View.TemplateEngine = function () {
    Sy.View.TemplateEngineInterface.call(this);
    this.registry = null;
    this.generator = null;
};
Sy.View.TemplateEngine.prototype = Object.create(Sy.View.TemplateEngineInterface.prototype, {

    /**
     * Set registry to hold rendered nodes references
     *
     * @param {Sy.RegistryInterface} registry
     *
     * @return {Sy.View.TemplateEngine}
     */

    setRegistry: {
        value: function (registry) {

            if (!(registry instanceof Sy.RegistryInterface)) {
                throw new TypeError('Invalid registry');
            }

            this.registry = registry;

            return this;

        }
    },

    /**
     * Set a generator to identify each rendered node
     *
     * @param {Sy.Lib.Generator.Interface} generator
     *
     * @return {Sy.View.TemplateEngine}
     */

    setGenerator: {
        value: function (generator) {

            if (!(generator instanceof Sy.Lib.Generator.Interface)) {
                throw new TypeError('Invalid generator');
            }

            this.generator = generator;

            return this;

        }
    },

    /**
     * @inheritDoc
     */

    render: {
        value: function (node, data, exempt) {

            if (!(node instanceof DocumentFragment)) {
                if (!node.dataset.syUuid) {
                    this.register(node);
                }

                if (node.dataset.syUuid && this.registry.has(node.dataset.syUuid)) {
                    this.renderAllAttributes(node, data);
                    this.renderContent(node, data, exempt);
                }
            }

            if (node.childElementCount > 0) {
                for (var i = 0, l = node.childElementCount; i < l; i++) {
                    this.render(node.children[i], data, exempt);
                }
            }

            return node;

        }
    },

    /**
     * Set a UUID on the node and set in the registry all the default attributes and text content
     *
     * @private
     * @param {HTMLElement} node
     *
     * @return {Sy.View.TemplateEngine}
     */

    register: {
        value: function (node) {

            var uuid = this.generator.generate(),
                content = {
                    attributes: {},
                    textContent: null,
                    uuid: uuid
                };

            for (var i = 0, l = node.attributes.length; i < l; i++) {
                content.attributes[node.attributes[i].name] = node.getAttribute(node.attributes[i].name);
            }

            content.textContent = node.textContent;
            node.dataset.syUuid = uuid;
            this.registry.set(uuid, content);

            return this;

        }
    },

    /**
     * Loop an all node attributes and render them
     *
     * @private
     * @param {HTMLElement} node
     * @param {Object} data
     *
     * @return {HTMLElement}
     */

    renderAllAttributes: {
        value: function (node, data) {

            for (var i = 0, l = node.attributes.length; i < l; i++) {
                this.renderAttribute(node, node.attributes[i].name, data);
            }

            return node;

        }
    },

    /**
     * Render a specific attribute on a node
     *
     * @private
     * @param {HTMLElement} node
     * @param {String} attribute
     * @param {Object} data
     *
     * @return {HTMLElement}
     */

    renderAttribute: {
        value: function (node, attribute, data) {

            var uuid = node.dataset.syUuid,
                originalContent = this.registry.get(uuid).attributes[attribute],
                text;

            if (!originalContent) {
                return node;
            }

            text = this.replace(originalContent, data);
            node.setAttribute(attribute, text);

            return node;

        }
    },

    /**
     * Replace {{ \w }} with the approriate data
     *
     * @private
     * @param {string} source
     * @param {Object} data
     *
     * @return {string}
     */

    replace: {
        value: function (source, data) {

            while (source.match(this.PATTERN)) {
                var results = this.PATTERN.exec(source);

                if (results !== null && results.length >= 1) {
                    source = source.replace(results[0], reflectedObjectGetter.call(data, results[1]) || '');
                }
            }

            return source;

        }
    },

    /**
     * Replace textContent placeholders by data
     *
     * @private
     * @param {HTMLElement} node
     * @param {Object} data
     * @param {String} exempt CSS selector to exempt nodes of being rendered
     *
     * @return {void}
     */

    renderContent: {
        value: function (node, data, exempt) {

            if (node.childElementCount > 0) {
                return node;
            }

            if (exempt && DOM(node).matches(exempt)) {
                return node;
            }

            var uuid = node.dataset.syUuid,
                originalContent = this.registry.get(uuid).textContent,
                results = this.PATTERN.exec(originalContent),
                d;

            if (results) {
                d = objectGetter.call(data, results[1]);
            }

            if (d instanceof HTMLElement) {
                node.removeChild(node.firstElementChild);
                node.appendChild(d);
            } else {
                node.textContent = this.replace(originalContent, data);
            }

            return node;

        }
    }

});
<|endoftext|>