<commit_before>'use strict';
import React, { PropTypes as T } from 'react';
import c from 'classnames';
import _ from 'lodash';
import { hashHistory } from 'react-router';

import { t, getLanguage } from '../../utils/i18n';

import { Modal, ModalHeader, ModalBody, ModalFooter } from '../modal';

const ScenarioCreateModal = React.createClass({
  propTypes: {
    revealed: T.bool,
    onCloseClick: T.func,

    scenarioForm: T.object,
    scenarioList: T.array,
    projectId: T.string,

    saveScenario: T.func,
    resetForm: T.func,
    _showGlobalLoading: T.func,
    _hideGlobalLoading: T.func
  },

  getInitialState: function () {
    return {
      errors: {
        name: null,
        roadNetworkSource: null
      },
      data: {
        name: '',
        description: '',
        roadNetworkSource: 'clone',
        roadNetworkSourceScenario: this.props.scenarioList[0].id,
        roadNetworkSourceFile: {
          file: null,
          size: 0,
          uploaded: 0
        }
      },
      loading: false
    };
  },

  xhr: null,

  componentWillReceiveProps: function (nextProps) {
    if (this.props.scenarioForm.processing && !nextProps.scenarioForm.processing) {
      this.props._hideGlobalLoading();
    }

    if (this.props.scenarioForm.action === 'edit' &&
        this.props.scenarioForm.processing &&
        !nextProps.scenarioForm.processing &&
        !nextProps.scenarioForm.error) {
      //
      let scenarioData = nextProps.scenarioForm.data;
      if (this.state.data.roadNetworkSource === 'new') {
        // Upload file
        this.uploadScenarioFile(scenarioData.roadNetworkUpload.presignedUrl);
      } else {
        hashHistory.push(`${getLanguage()}/projects/${scenarioData.project_id}/scenarios/${scenarioData.id}`);
      }
      return;
    }
  },

  componentWillUnmount: function () {
    this.props.resetForm();
    if (this.xhr) {
      this.xhr.abort();
    }
  },

  onClose: function () {
    if (this.xhr) {
      this.xhr.abort();
    }
    this.props.resetForm();
    this.setState(this.getInitialState());
    this.props.onCloseClick();
  },

  onFileSelected: function (event) {
    // Store file reference
    const file = event.target.files[0];
    let roadNetworkSourceFile = {
      file,
      size: file.size,
      uploaded: 0
    };

    let data = Object.assign({}, this.state.data, {roadNetworkSourceFile});
    this.setState({data});
  },

  onFileUploadComplete: function () {
    this.setState({loading: false});
    let scenarioData = this.props.scenarioForm.data;
    hashHistory.push(`${getLanguage()}/projects/${scenarioData.project_id}/scenarios/${scenarioData.id}`);
  },

  uploadScenarioFile: function (presignedUrl) {
    this.xhr = new window.XMLHttpRequest();
    let file = this.state.data.roadNetworkSourceFile.file;

    this.xhr.upload.addEventListener('progress', (evt) => {
      if (evt.lengthComputable) {
        // I know what I'm doing here.
        let data = this.state.data;
        data.roadNetworkSourceFile.uploaded = evt.loaded;
        this.setState({data});
      }
    }, false);

    this.xhr.onreadystatechange = e => {
      if (this.xhr.readyState === XMLHttpRequest.DONE) {
        this.setState(this.getInitialState());
        this.onFileUploadComplete();
      }
    };

    // start upload
    this.xhr.open('PUT', presignedUrl, true);
    this.xhr.send(file);
  },

  checkErrors: function () {
    let control = true;
    let errors = this.getInitialState().errors;

    if (this.state.data.name === '') {
      errors.name = true;
      control = false;
    }

    if (this.state.data.roadNetworkSource === 'new' && !this.state.data.roadNetworkSourceFile.file) {
      errors.roadNetworkSource = true;
      control = false;
    }

    this.setState({errors});
    return control;
  },

  onSubmit: function (e) {
    e.preventDefault && e.preventDefault();

    if (this.checkErrors()) {
      var payload = {
        name: this.state.data.name,
        description: this.state.data.description || null
      };
      // On create we only want to send properties that were filled in.
      payload = _.pickBy(payload, v => v !== null);

      if (this.state.data.roadNetworkSource === 'clone') {
        this.props._showGlobalLoading();
        payload.roadNetworkSource = 'clone';
        payload.roadNetworkSourceScenario = this.state.data.roadNetworkSourceScenario;
      } else if (this.state.data.roadNetworkSource === 'new') {
        payload.roadNetworkSource = 'new';
        this.setState({loading: true});
      }
      this.props.saveScenario(this.props.projectId, payload);
    }
  },

  onFieldChange: function (field, e) {
    let data = Object.assign({}, this.state.data, {[field]: e.target.value});
    this.setState({data});
  },

  renderError: function () {
    let error = this.props.scenarioForm.error;

    if (!error) {
      return;
    }

    if (error.statusCode === 409) {
      return
The name is already in use.
;
    } else {
      return
{error.message || error.error}
;
    }
  },

  render: function () {
    let processing = this.props.scenarioForm.processing || this.state.loading;

    return (
      <Modal
        id='modal-scenario-metadata'
        className='modal--small'
        onCloseClick={this.onClose}
        revealed={this.props.revealed} >

        <ModalHeader>

{t('Create new scenario')}

{t('Name and describe your new scenario.')}

        </ModalHeader>
        <ModalBody>

          {this.renderError()}

          <form className={c('form', {'disabled': processing})} onSubmit={this.onSubmit}>

              {t('Scenario name')}
              <input type='text' className='form__control form__control--medium' id='scenario-name' name='scenario-name' placeholder={t('Untitled scenario')} value={this.state.data.name} onChange={this.onFieldChange.bind(null, 'name')} />

              {this.state.errors.name ?
{t('A Scenario name is required.')}
 : null }

Keep it short and sweet.

              {t('Description')} ({t('optional')})
              <textarea ref='description' className='form__control' id='scenario-desc' rows='2' placeholder={t('Say something about this scenario')} value={this.state.data.description} onChange={this.onFieldChange.bind(null, 'description')}></textarea>

              Road network

                <input type='radio' name='road-network' id='road-network-clone' value='clone' onChange={this.onFieldChange.bind(null, 'roadNetworkSource')} checked={this.state.data.roadNetworkSource === 'clone'}/>
                {t('Clone from scenario')}

                <input type='radio' name='road-network' id='road-network-new' value='new' onChange={this.onFieldChange.bind(null, 'roadNetworkSource')} checked={this.state.data.roadNetworkSource === 'new'}/>
                {t('Upload new')}

            {this.state.data.roadNetworkSource === 'clone' ? (

              {t('Clone from scenario')}
              <select name='road-network-clone-options' id='road-network-clone-options' className='form__control' value={this.state.data.roadNetworkSourceScenario} onChange={this.onFieldChange.bind(null, 'roadNetworkSourceScenario')}>
                {this.props.scenarioList.map(scenario => <option key={scenario.id} value={scenario.id}>{scenario.name}</option>)}
              </select>

            ) : null}

            {this.state.data.roadNetworkSource === 'new' ? (

              {t('New road network')}
              <input type='file' name='road-network-new-file' id='road-network-new-file' className='form__control--upload' ref='file' onChange={this.onFileSelected} />
              {this.state.errors.roadNetworkSource ?
{t('A file is required.')}
 : null }
              {this.state.data.roadNetworkSourceFile.file !== null
              ?
{Math.round(this.state.data.roadNetworkSourceFile.uploaded / (1024 * 1024))}MB / {Math.round(this.state.data.roadNetworkSourceFile.size / (1024 * 1024))}MB

              : null
             }

            ) : null}

          </form>
        </ModalBody>
        <ModalFooter>
          <button className='mfa-xmark' type='button' onClick={this.onClose}>{t('Cancel')}</button>
          <button className={c('mfa-tick', {'disabled': processing})} type='submit' onClick={this.onSubmit}>{t('Create')}</button>
        </ModalFooter>
      </Modal>
    );
  }
});

export default ScenarioCreateModal;
<commit_msg>Fix form disabled when uploading file. Fix #82<commit_after>'use strict';
import React, { PropTypes as T } from 'react';
import c from 'classnames';
import _ from 'lodash';
import { hashHistory } from 'react-router';

import { t, getLanguage } from '../../utils/i18n';

import { Modal, ModalHeader, ModalBody, ModalFooter } from '../modal';

const ScenarioCreateModal = React.createClass({
  propTypes: {
    revealed: T.bool,
    onCloseClick: T.func,

    scenarioForm: T.object,
    scenarioList: T.array,
    projectId: T.string,

    saveScenario: T.func,
    resetForm: T.func,
    _showGlobalLoading: T.func,
    _hideGlobalLoading: T.func
  },

  getInitialState: function () {
    return {
      errors: {
        name: null,
        roadNetworkSource: null
      },
      data: {
        name: '',
        description: '',
        roadNetworkSource: 'clone',
        roadNetworkSourceScenario: this.props.scenarioList[0].id,
        roadNetworkSourceFile: {
          file: null,
          size: 0,
          uploaded: 0
        }
      },
      loading: false
    };
  },

  xhr: null,

  componentWillReceiveProps: function (nextProps) {
    if (this.props.scenarioForm.processing && !nextProps.scenarioForm.processing) {
      this.props._hideGlobalLoading();
    }

    if (this.props.scenarioForm.action === 'edit' &&
        this.props.scenarioForm.processing &&
        !nextProps.scenarioForm.processing &&
        !nextProps.scenarioForm.error) {
      //
      let scenarioData = nextProps.scenarioForm.data;
      if (this.state.data.roadNetworkSource === 'new') {
        // Upload file
        this.setState({loading: true});
        this.uploadScenarioFile(scenarioData.roadNetworkUpload.presignedUrl);
      } else {
        hashHistory.push(`${getLanguage()}/projects/${scenarioData.project_id}/scenarios/${scenarioData.id}`);
      }
    }
  },

  componentWillUnmount: function () {
    this.props.resetForm();
    if (this.xhr) {
      this.xhr.abort();
    }
  },

  onClose: function () {
    if (this.xhr) {
      this.xhr.abort();
    }
    this.props.resetForm();
    this.setState(this.getInitialState());
    this.props.onCloseClick();
  },

  onFileSelected: function (event) {
    // Store file reference
    const file = event.target.files[0];
    let roadNetworkSourceFile = {
      file,
      size: file.size,
      uploaded: 0
    };

    let data = Object.assign({}, this.state.data, {roadNetworkSourceFile});
    this.setState({data});
  },

  onFileUploadComplete: function () {
    this.setState({loading: false});
    let scenarioData = this.props.scenarioForm.data;
    hashHistory.push(`${getLanguage()}/projects/${scenarioData.project_id}/scenarios/${scenarioData.id}`);
  },

  uploadScenarioFile: function (presignedUrl) {
    this.xhr = new window.XMLHttpRequest();
    let file = this.state.data.roadNetworkSourceFile.file;

    this.xhr.upload.addEventListener('progress', (evt) => {
      if (evt.lengthComputable) {
        // I know what I'm doing here.
        let data = this.state.data;
        data.roadNetworkSourceFile.uploaded = evt.loaded;
        this.setState({data});
      }
    }, false);

    this.xhr.onreadystatechange = e => {
      if (this.xhr.readyState === XMLHttpRequest.DONE) {
        this.setState(this.getInitialState());
        this.onFileUploadComplete();
      }
    };

    // start upload
    this.xhr.open('PUT', presignedUrl, true);
    this.xhr.send(file);
  },

  checkErrors: function () {
    let control = true;
    let errors = this.getInitialState().errors;

    if (this.state.data.name === '') {
      errors.name = true;
      control = false;
    }

    if (this.state.data.roadNetworkSource === 'new' && !this.state.data.roadNetworkSourceFile.file) {
      errors.roadNetworkSource = true;
      control = false;
    }

    this.setState({errors});
    return control;
  },

  onSubmit: function (e) {
    e.preventDefault && e.preventDefault();

    if (this.checkErrors()) {
      var payload = {
        name: this.state.data.name,
        description: this.state.data.description || null
      };
      // On create we only want to send properties that were filled in.
      payload = _.pickBy(payload, v => v !== null);

      if (this.state.data.roadNetworkSource === 'clone') {
        this.props._showGlobalLoading();
        payload.roadNetworkSource = 'clone';
        payload.roadNetworkSourceScenario = this.state.data.roadNetworkSourceScenario;
      } else if (this.state.data.roadNetworkSource === 'new') {
        payload.roadNetworkSource = 'new';
      }
      this.props.saveScenario(this.props.projectId, payload);
    }
  },

  onFieldChange: function (field, e) {
    let data = Object.assign({}, this.state.data, {[field]: e.target.value});
    this.setState({data});
  },

  renderError: function () {
    let error = this.props.scenarioForm.error;

    if (!error) {
      return;
    }

    if (error.statusCode === 409) {
      return
The name is already in use.
;
    } else {
      return
{error.message || error.error}
;
    }
  },

  render: function () {
    let processing = this.props.scenarioForm.processing || this.state.loading;

    return (
      <Modal
        id='modal-scenario-metadata'
        className='modal--small'
        onCloseClick={this.onClose}
        revealed={this.props.revealed} >

        <ModalHeader>

{t('Create new scenario')}

{t('Name and describe your new scenario.')}

        </ModalHeader>
        <ModalBody>

          {this.renderError()}

          <form className={c('form', {'disabled': processing})} onSubmit={this.onSubmit}>

              {t('Scenario name')}
              <input type='text' className='form__control form__control--medium' id='scenario-name' name='scenario-name' placeholder={t('Untitled scenario')} value={this.state.data.name} onChange={this.onFieldChange.bind(null, 'name')} />

              {this.state.errors.name ?
{t('A Scenario name is required.')}
 : null }

Keep it short and sweet.

              {t('Description')} ({t('optional')})
              <textarea ref='description' className='form__control' id='scenario-desc' rows='2' placeholder={t('Say something about this scenario')} value={this.state.data.description} onChange={this.onFieldChange.bind(null, 'description')}></textarea>

              Road network

                <input type='radio' name='road-network' id='road-network-clone' value='clone' onChange={this.onFieldChange.bind(null, 'roadNetworkSource')} checked={this.state.data.roadNetworkSource === 'clone'}/>
                {t('Clone from scenario')}

                <input type='radio' name='road-network' id='road-network-new' value='new' onChange={this.onFieldChange.bind(null, 'roadNetworkSource')} checked={this.state.data.roadNetworkSource === 'new'}/>
                {t('Upload new')}

            {this.state.data.roadNetworkSource === 'clone' ? (

              {t('Clone from scenario')}
              <select name='road-network-clone-options' id='road-network-clone-options' className='form__control' value={this.state.data.roadNetworkSourceScenario} onChange={this.onFieldChange.bind(null, 'roadNetworkSourceScenario')}>
                {this.props.scenarioList.map(scenario => <option key={scenario.id} value={scenario.id}>{scenario.name}</option>)}
              </select>

            ) : null}

            {this.state.data.roadNetworkSource === 'new' ? (

              {t('New road network')}
              <input type='file' name='road-network-new-file' id='road-network-new-file' className='form__control--upload' ref='file' onChange={this.onFileSelected} />
              {this.state.errors.roadNetworkSource ?
{t('A file is required.')}
 : null }
              {this.state.data.roadNetworkSourceFile.file !== null
              ?
{Math.round(this.state.data.roadNetworkSourceFile.uploaded / (1024 * 1024))}MB / {Math.round(this.state.data.roadNetworkSourceFile.size / (1024 * 1024))}MB

              : null
             }

            ) : null}

          </form>
        </ModalBody>
        <ModalFooter>
          <button className='mfa-xmark' type='button' onClick={this.onClose}>{t('Cancel')}</button>
          <button className={c('mfa-tick', {'disabled': processing})} type='submit' onClick={this.onSubmit}>{t('Create')}</button>
        </ModalFooter>
      </Modal>
    );
  }
});

export default ScenarioCreateModal;
<|endoftext|>


<commit_before>/// <reference path="typings/node/node.d.ts"/>
// load plugins
var gulp      = require('gulp'),
    inquirer  = require('inquirer'),
    del       = require('del'),
    iniparser = require('iniparser'),
    conflict  = require('gulp-conflict'),
    install   = require('gulp-install'),
    rename    = require('gulp-rename'),
    template  = require('gulp-template');

var defaults = (function () {
  var homeDir = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE,
      workingDirName = process.cwd().split('/').pop().split('\\').pop(),
      osUserName = homeDir && homeDir.split('/').pop() || 'root',
      configFile = homeDir + '/.gitconfig',
      user = {};

  if (require('fs').existsSync(configFile)) {
    user = iniparser.parseSync(configFile).user;
  } //end if
  return {
    appName    : workingDirName,
    userName   : user.name || osUserName,
    authorEmail: user.email || ''
  };
})();

// Limit the results down to the packages installed
var filterModuleNames = function (val) {
  return val.toLowerCase().replace(/\+(\w)/, function (match, $1) {
    return $1.toUpperCase();
  });
};

// Replace the paths with the specified paths the user gave
var filterPaths = function (val) {
  return val.replace(/(\w)([^\/])$/, '$1$2/');
};

// Replace the normal extension with the one the user gave
var filterExt = function (val) {
  return val.replace(/^([^\.])/, '.$1').replace(/\W+/g, '.');
};

// Does the user want to edit the source folder structure?
var sourceCustomizationWanted = function (answers) {
  return !!answers.sourceCustomization;
};

// Does the user want to edit the distribution folder structure?
var outputCustomizationWanted = function (answers) {
  return !!answers.outputCustomization;
};

// If they don't specify specifics, we need to have defaults ready
var handleDefaults = function (answers) {
  if (!answers.sourceCustomization) {
    answers.sourceBase = defaults.source.base;
    answers.sourceStyles = defaults.source.styles;
    answers.sourceScripts = defaults.source.scripts;
    answers.sourceEsnextExt = defaults.source.esnextExtension;
    answers.sourcePartials = defaults.source.partials;
    answers.sourceTemplates = defaults.source.templates;
  }
  if (!answers.outputCustomization) {
    answers.outputBase = defaults.output.base;
    answers.outputStyles = defaults.output.styles;
    answers.outputScripts = defaults.output.scripts;
  }
  return answers;
};

// The default gulp task is ran when slush is executed
gulp.task('default', function (done) {
  inquirer.prompt([{
      name   : 'name',
      message: 'Give your app a name',
      default: defaults.appName
    }, {
      name   : 'appVersion',
      message: 'What is the version of your project?',
      default: '0.1.0'
    }, {
      name   : 'appDescription',
      message: 'What is a description of your project?',
      default: 'n/a'
    }, {
      name   : 'authorName',
      message: 'What is the author name?',
      default: defaults.userName
    }, {
      name   : 'authorEmail',
      message: 'What is the author email?',
      default: defaults.authorEmail
    }, {
      name   : 'userName',
      message: 'What is the github username?',
      default: defaults.userName
    }, {
      type   : 'confirm',
      name   : 'moveon',
      message: 'Continue?'
    }],
    function (answers) {
      if (!answers.moveon) return done();
      answers.file = { relative: '<%= file.relative %>' };
      answers = handleDefaults(answers);
      answers.year = (new Date()).getFullYear();
      gulp.src([
        __dirname + '/templates/app/**'
      ])
        .pipe(template(answers, {
          interpolate: /<%=\s([\s\S]+?)%>/g
        }))
        .pipe(rename(function (file) {
          if (file.basename[0] === '_' && file.basename[1] === '_'){
            file.basename = file.basename.slice(1);
          } else if (file.basename[0] === '_') {
            file.basename = '.' + file.basename.slice(1);
          } //end if
        }))
        .pipe(conflict('./'))
        .pipe(gulp.dest('./'))
        .pipe(install())
        .on('finish', function () {
          del(dirs, done);
        });
    });
});
<commit_msg>removed deprecated default setup .<commit_after>/// <reference path="typings/node/node.d.ts"/>
// load plugins
var gulp      = require('gulp'),
    inquirer  = require('inquirer'),
    del       = require('del'),
    iniparser = require('iniparser'),
    conflict  = require('gulp-conflict'),
    install   = require('gulp-install'),
    rename    = require('gulp-rename'),
    template  = require('gulp-template');

var defaults = (function () {
  var homeDir = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE,
      workingDirName = process.cwd().split('/').pop().split('\\').pop(),
      osUserName = homeDir && homeDir.split('/').pop() || 'root',
      configFile = homeDir + '/.gitconfig',
      user = {};

  if (require('fs').existsSync(configFile)) {
    user = iniparser.parseSync(configFile).user;
  } //end if
  return {
    appName    : workingDirName,
    userName   : user.name || osUserName,
    authorEmail: user.email || ''
  };
})();

// Limit the results down to the packages installed
var filterModuleNames = function (val) {
  return val.toLowerCase().replace(/\+(\w)/, function (match, $1) {
    return $1.toUpperCase();
  });
};

// Replace the paths with the specified paths the user gave
var filterPaths = function (val) {
  return val.replace(/(\w)([^\/])$/, '$1$2/');
};

// Replace the normal extension with the one the user gave
var filterExt = function (val) {
  return val.replace(/^([^\.])/, '.$1').replace(/\W+/g, '.');
};

// Does the user want to edit the source folder structure?
var sourceCustomizationWanted = function (answers) {
  return !!answers.sourceCustomization;
};

// Does the user want to edit the distribution folder structure?
var outputCustomizationWanted = function (answers) {
  return !!answers.outputCustomization;
};

// If they don't specify specifics, we need to have defaults ready
var handleDefaults = function (answers) {
  return answers;
};

// The default gulp task is ran when slush is executed
gulp.task('default', function (done) {
  inquirer.prompt([{
      name   : 'name',
      message: 'Give your app a name',
      default: defaults.appName
    }, {
      name   : 'appVersion',
      message: 'What is the version of your project?',
      default: '0.1.0'
    }, {
      name   : 'appDescription',
      message: 'What is a description of your project?',
      default: 'n/a'
    }, {
      name   : 'authorName',
      message: 'What is the author name?',
      default: defaults.userName
    }, {
      name   : 'authorEmail',
      message: 'What is the author email?',
      default: defaults.authorEmail
    }, {
      name   : 'userName',
      message: 'What is the github username?',
      default: defaults.userName
    }, {
      type   : 'confirm',
      name   : 'moveon',
      message: 'Continue?'
    }],
    function (answers) {
      if (!answers.moveon) return done();
      answers.file = { relative: '<%= file.relative %>' };
      answers = handleDefaults(answers);
      answers.year = (new Date()).getFullYear();
      gulp.src([
        __dirname + '/templates/app/**'
      ])
        .pipe(template(answers, {
          interpolate: /<%=\s([\s\S]+?)%>/g
        }))
        .pipe(rename(function (file) {
          if (file.basename[0] === '_' && file.basename[1] === '_'){
            file.basename = file.basename.slice(1);
          } else if (file.basename[0] === '_') {
            file.basename = '.' + file.basename.slice(1);
          } //end if
        }))
        .pipe(conflict('./'))
        .pipe(gulp.dest('./'))
        .pipe(install())
        .on('finish', function () {
          del(dirs, done);
        });
    });
});
<|endoftext|>


<commit_before>const Reactor = require('reactor')

const logger = require('prolific.logger').createLogger('compassion.networked')

const coalesce = require('extant')

const Serialize = require('avenue/serialize')

class Networked {
    constructor (destructible, colleagues) {
        this._destructible = destructible
        this._colleagues = colleagues
        this.reactor = new Reactor([{
            path: '/',
            method: 'get',
            f: this.index.bind(this)
        }, {
            path: '/island/:island/islanders',
            method: 'get',
            f: this.islanders.bind(this)
        }, {
            path: '/island/:island/islander/:id/embark',
            method: 'post',
            f: this.embark.bind(this)
        }, {
            path: '/island/:island/islander/:id/kibitz',
            method: 'post',
            f: this.kibits.bind(this)
        }, {
            path: '/island/:island/islander/:id/broadcasts',
            method: 'post',
            f: this.broadcasts.bind(this)
        }, {
            path: '/island/:island/islander/:id/snapshot',
            method: 'post',
            f: this.snapshot.bind(this)
        }])
    }

    index () {
        return 'Compassion Networked API\n'
    }

    _getColleague (island, id) {
        if (this._colleagues.island[island] == null || this._colleagues.island[island][id] == null) {
            throw 404
        }
        return this._colleagues.island[island][id]
    }

    embark (request) {
        const { island, id } = request.params
        const colleague = this._getColleague(island, id)
        return colleague.kibitzer.embark(request.body.republic, request.body.id, request.body.cookie, request.body.properties)
    }

    kibitz (request) {
        const { island, id } = request.params
        logger.info('recorded', {
            source: 'middleware',
            method: request.body.method,
            url: request.url,
            $body: request.body
        })
        return this._getColleague(island, id).kibitzer.request(request.body)
    }

    async broadcasts (request, island, id) {
        return await this._getColleague(island, id).conduit.request({
            method: 'broadcasts',
            promise: request.body.promise
        })
    }

    async snapshot (request, reply) {
        const { queue } = this._getColleague(reply.params.island, reply.params.id).conduit.request({
            method: 'snapshot',
            promise: request.body.promise,
            inbox: true
        })
        const through = new stream.PassThrough
        reply.code(200)
        reply.header('content-type', 'application/octet-stream')
        reply.send(through)
        await Serialize(queue, through)
    }

    islanders (request, name) {
        const islanders = []
        const island = this._colleagues.island[name]
        if (island != null) {
            for (const id in island) {
                const colleague = island[id]
                islanders.push({
                    id: colleague.id,
                    government: colleague.kibitzer.paxos.government,
                    cookie: coalesce(colleague.kibitzer.paxos.cookie),
                    createdAt: colleague.createdAt
                })
            }
        }
        return islanders
    }
}

module.exports = Networked
<commit_msg>Tidy parameter handling.<commit_after>const Reactor = require('reactor')

const logger = require('prolific.logger').createLogger('compassion.networked')

const coalesce = require('extant')

const Serialize = require('avenue/serialize')

class Networked {
    constructor (destructible, colleagues) {
        this._destructible = destructible
        this._colleagues = colleagues
        this.reactor = new Reactor([{
            path: '/',
            method: 'get',
            f: this.index.bind(this)
        }, {
            path: '/island/:island/islanders',
            method: 'get',
            f: this.islanders.bind(this)
        }, {
            path: '/island/:island/islander/:id/embark',
            method: 'post',
            f: this.embark.bind(this)
        }, {
            path: '/island/:island/islander/:id/kibitz',
            method: 'post',
            f: this.kibits.bind(this)
        }, {
            path: '/island/:island/islander/:id/broadcasts',
            method: 'post',
            f: this.broadcasts.bind(this)
        }, {
            path: '/island/:island/islander/:id/snapshot',
            method: 'post',
            f: this.snapshot.bind(this)
        }])
    }

    index () {
        return 'Compassion Networked API\n'
    }

    _getColleague (island, id) {
        if (this._colleagues.island[island] == null || this._colleagues.island[island][id] == null) {
            throw 404
        }
        return this._colleagues.island[island][id]
    }

    embark (request) {
        const { island, id } = request.params
        const colleague = this._getColleague(island, id)
        return colleague.kibitzer.embark(request.body.republic, request.body.id, request.body.cookie, request.body.properties)
    }

    kibitz (request) {
        const { island, id } = request.params
        logger.info('recorded', {
            source: 'middleware',
            method: request.body.method,
            url: request.url,
            $body: request.body
        })
        return this._getColleague(island, id).kibitzer.request(request.body)
    }

    async broadcasts (request) {
        const { island, id } = request.params
        return await this._getColleague(island, id).conduit.request({
            method: 'broadcasts',
            promise: request.body.promise
        })
    }

    async snapshot (request, reply) {
        const { queue } = this._getColleague(reply.params.island, reply.params.id).conduit.request({
            method: 'snapshot',
            promise: request.body.promise,
            inbox: true
        })
        const through = new stream.PassThrough
        reply.code(200)
        reply.header('content-type', 'application/octet-stream')
        reply.send(through)
        await Serialize(queue, through)
    }

    islanders (request, name) {
        const { name } = request.params
        const islanders = []
        const island = this._colleagues.island[name]
        if (island != null) {
            for (const id in island) {
                const colleague = island[id]
                islanders.push({
                    id: colleague.id,
                    government: colleague.kibitzer.paxos.government,
                    cookie: coalesce(colleague.kibitzer.paxos.cookie),
                    createdAt: colleague.createdAt
                })
            }
        }
        return islanders
    }
}

module.exports = Networked
<|endoftext|>


<commit_before>/**
 * __          __   _ _   _                  _
 * \ \        / /  (_) | | |                | |
 *  \ \  /\  / / __ _| |_| |__    _ __   ___| |_
 *   \ \/  \/ / '__| | __| '_ \  | '_ \ / _ \ __|
 *    \  /\  /| |  | | |_| | | |_| | | |  __/ |_
 *     \/  \/ |_|  |_|\__|_| |_(_)_| |_|\___|\__|
 *
 * @created     2012-02-08
 * @edited      2013-01-16
 * @package     Libraries
 * @see         https://github.com/Writh/classical
 *
 * Copyright (C) 2012-2013 Kevin Kragenbrink <kevin@writh.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.I
 */
var b = function(global, require, module) {
    if (typeof module.exports == 'undefined') { module.exports = {}; }

    /**
     * Defines a new Class.
     *
     * @global
     * @constructor
     */
    module.exports.Class = function(fn) { return defineClass(fn); };

    /**
     * Defines a new Class using a non-Classical class as the baseclass.
     *
     * @global
     * @constructor
     */
    module.exports.Extend = function(ancestor, fn) { return defineClass(fn, undefined, ancestor); };

    /**
     * Creates a public member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Public = function Public(member) { return setVisibility(member); };

    /**
     * Creates a private member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Private = function Private(member) { return setVisibility(member); };

    /**
     * Creates a protected member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Protected = function Protected(member) { return setVisibility(member); };

    /**
     * Creates a static member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Static = function Static(member) { return setStatic(member); };

    /**
     * The base class prototype.
     * @constructor
     */
    module.exports.BaseClass = function BaseClass() {};

    /***************************************
     * INTERNALS
     *
     * The following code is not a part of the public API for Classical, and
     * should not be altered or exposed to external scripts.
     ***************************************/
    var BaseClass                       = module.exports.BaseClass;

    /**
     * Implements Classical inheritance by wrapping prototypal inheritance.
     *
     * @param   {Function}      fn
     * @param   {Object}        _super
     * @param   {Function}      ancestor
     * @return  {ClassFactory}
     * @constructor
     * @global
     */
    var defineClass = function(fn, _super, ancestor) {
        var member;

        // Get a _preInstance.
        var _preInstance                = new fn;

        // Extend the _preInstance with members from the inheritted class, if any.
        if (typeof ancestor == 'function'
            ||  (typeof ancestor == 'object' && Object.prototype.toString.call(ancestor) == '[object Object]')) {

            if (typeof ancestor._classical_extend == 'function') {
                return ancestor._classical_extend(fn);
            }
            else {
                var AncestralClass      = (typeof ancestor == 'function') ? new ancestor : dereference(ancestor);

                for (member in AncestralClass) {
                    // WARNING: Not using hasOwnProperty here because Node EventEmitter does not have its
                    //          methods as its own properties. This creates a pretty big opening if
                    //          someone foolishly modifies the Object prototype.
                    AncestralClass[member]                  = Public(AncestralClass[member]);
                    if (typeof _preInstance[member] == 'undefined') {
                        _preInstance[member]                = AncestralClass[member];
                    }
                }
            }
        }

        // Create a copy of the SuperClass to set the prototype.
        initializing                    = true;
        var SuperClass                  = (typeof this == 'function') ? this : BaseClass;
        if (typeof ancestor == 'function') {
            SuperClass.prototype        = AncestralClass;
        }
        var prototype                   = new SuperClass;
        initializing                    = false;

        // Establish a baseline prototype chain.
        var base                        = function() {};
        base.prototype                  = prototype;

        // Extend the _preInstance with the members from the SuperClass
        if (_super !== undefined) {
            for (member in _super) {
                if (member != 'constructor' && _super.hasOwnProperty(member)) {
                    if ((_super[member]._visibility == 'Public' || _super[member]._visibility == 'Protected')
                        && typeof _preInstance[member] == 'undefined') {

                        _preInstance[member]                = _super[member];
                    }
                }
            }

            // Add the _super to the _preInstance, for construction and this._super purposes.
            _preInstance._super         = _super;
        }
        else if (AncestralClass !== undefined) {
            _preInstance._super         = AncestralClass;
        }

        return getClassFactory(base, prototype, _preInstance, arguments.callee);
    };

    var getClassFactory = function(base, prototype, _preInstance, extend) {
        var member;

        // Set up the ClassFactory.  This is what actually gets instantiated.
        var ClassFactory = function Class() {
            var _instance               = new base;
            var _public                 = new base;

            _instance._classical_public= _public;

            if (!initializing) {
                assemble(_instance, _instance, _public, _preInstance);
                construct(_instance, _instance, arguments);
            }

            return _public;
        };

        // Bind the ClassFactory to the prototype (for the inheritance chain).
        ClassFactory.prototype          = prototype;

        // Set up static methods.
        for (member in _preInstance) {
            if (member != '_super' && _preInstance.hasOwnProperty(member)) {
                // While we're at it, let's also make sure visibility has been set.
                if (!_preInstance[member].hasOwnProperty('_visibility')) {
                    _preInstance[member]                    = Public(_preInstance[member]);
                }

                if (_preInstance[member]._static === true && _preInstance[member]._visibility == 'Public') {
                    ClassFactory[member]                    = copyValue(_preInstance[member]._value, ClassFactory, _preInstance[member]._static);
                }
            }
        }

        // Setup a method to extend the base class.
        ClassFactory._classical_extend = function(newfn) {
            return extend.call(ClassFactory, newfn, _preInstance);
        };

        // Assembles the instance and its public accessors.
        var assemble = function(_context, _instance, _public, _preInstance) {
            var member;

            if (typeof _preInstance != 'undefined' && typeof _preInstance._super != 'undefined') {
                _instance._super                            = new base;
                assemble(_context, _instance._super, {}, _preInstance._super);
            }

            for (member in _preInstance) {
                if (member != '_super' && _preInstance.hasOwnProperty(member)) {
                    if (_preInstance[member]._visibility != 'Private' || _context === _instance) {
                        _instance[member]                   = copyValue(_preInstance[member]._value, _context,
                                                                        _preInstance[member]._static);

                        if (_preInstance[member]._visibility == 'Public') {
                            _public[member]                 = _instance[member];
                        }
                    }
                }
            }
        };

        // Recursively calls the constructors for the class, starting with the ancestor
        // and working towards the instance.
        var construct = function(context, target, arguments) {
            // Call the SuperClass constructors first.
            if (target._super instanceof BaseClass) {
                construct(context, target._super, arguments);
            }

            // Call the instance constructor.
            if (typeof target.constructor == 'function' && target.hasOwnProperty('constructor')) {
                target.constructor.apply(context, arguments);
            }
        };

        return ClassFactory;
    };

    /**
     * Performs a deep clone to dereference an object.
     *
     * @param   {*}     source
     * @return  {*}
     */
    var dereference = function(source) {
        var target;

        if (typeof source == 'object' && source !== null) {
            target = (typeof source.length == 'number') ? [] : {};

            for (var i in source) {
                if (source.hasOwnProperty(i)) {
                    target[i]           = dereference(source[i]);
                }
            }
        }
        else {
            target                      = source;
        }

        return target;
    };

    /**
     * Used to prevent calling the constructor during ClassFactory creation.
     * @type    {Boolean}
     */
    var initializing = false;

    /**
     * Returns a dereferenced copy of a value, bound to the target if it is a function.
     *
     * @param   {*}         member
     * @param   {Object}    target
     * @param   {Boolean}   _static
     * @return  {*}
     */
    var copyValue = function(member, target, _static) {
        if (typeof member == 'function') {
            return member.bind(target);
        }
        else {
            return (!_static ? dereference(member) : member);
        }
    };

    /**
     * A common interface for the Public, Private, and Protected APIs.
     * @param   {*}         member
     * @return  {Object}
     */
    var setVisibility = function(member) {
        return {
            _value                      : member,
            _visibility                 : arguments.callee.caller.name,
            _static                     : false
        }
    };

    /**
     * A wrapper around the Public, Private, and Protected APIs to make a method static.
     * @param   {Object}    member
     * @return  {Object}
     */
    var setStatic = function(member) {
        member._static                  = true;
        return member;
    };

    // Set up the global Classical variables.
    global.Classical                    = global.Classical || {};
    global.Classical.Class              = module.exports.Class;
    global.Classical.Extend             = module.exports.Extend;
    global.Classical.Public             = module.exports.Public;
    global.Classical.Private            = module.exports.Private;
    global.Classical.Protected          = module.exports.Protected;
    global.Classical.Static             = module.exports.Static;

    // Register classical globals.
    if ((typeof process != 'undefined' && typeof process.env != 'undefined' && process.env.CLASSICAL_PROTECTGLOBALS !== true)
        ||  (typeof window != 'undefined' && window.CLASSICAL_PROTECTGLOBALS !== true)
        ||  (typeof global != 'undefined' && global.CLASSICAL_PROTECTGLOBALS !== true)) {
        global.Class                    = global.Classical.Class;
        global.Extend                   = global.Classical.Extend;
        global.Public                   = global.Classical.Public;
        global.Private                  = global.Classical.Private;
        global.Protected                = global.Classical.Protected;
        global.Static                   = global.Classical.Static;
    }

    return module.exports;
};

if (typeof window != 'undefined') {
    // requirejs
    define(['require', 'module', 'Classical'], b.bind(this, window));
}
else if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
    // nodejs
    b(global, require, module);
}
else {
    // web workers
    b(this, null, this);
}
<commit_msg>IE fix<commit_after>/**
 * __          __   _ _   _                  _
 * \ \        / /  (_) | | |                | |
 *  \ \  /\  / / __ _| |_| |__    _ __   ___| |_
 *   \ \/  \/ / '__| | __| '_ \  | '_ \ / _ \ __|
 *    \  /\  /| |  | | |_| | | |_| | | |  __/ |_
 *     \/  \/ |_|  |_|\__|_| |_(_)_| |_|\___|\__|
 *
 * @created     2012-02-08
 * @edited      2013-01-16
 * @package     Libraries
 * @see         https://github.com/Writh/classical
 *
 * Copyright (C) 2012-2013 Kevin Kragenbrink <kevin@writh.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.I
 */
var b = function(global, require, module) {
    if (typeof module.exports == 'undefined') { module.exports = {}; }

    /**
     * Defines a new Class.
     *
     * @global
     * @constructor
     */
    module.exports.Class = function(fn) { return defineClass(fn); };

    /**
     * Defines a new Class using a non-Classical class as the baseclass.
     *
     * @global
     * @constructor
     */
    module.exports.Extend = function(ancestor, fn) { return defineClass(fn, undefined, ancestor); };

    /**
     * Creates a public member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Public = function Public(member) { return setVisibility(member, 'Public'); };

    /**
     * Creates a private member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Private = function Private(member) { return setVisibility(member, 'Private'); };

    /**
     * Creates a protected member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Protected = function Protected(member) { return setVisibility(member, 'Protected'); };

    /**
     * Creates a static member of a Class.
     *
     * @global
     * @param   member
     * @return  {Object}
     * @constructor
     */
    module.exports.Static = function Static(member) { return setStatic(member); };

    /**
     * The base class prototype.
     * @constructor
     */
    module.exports.BaseClass = function BaseClass() {};

    /***************************************
     * INTERNALS
     *
     * The following code is not a part of the public API for Classical, and
     * should not be altered or exposed to external scripts.
     ***************************************/
    var BaseClass                       = module.exports.BaseClass;

    /**
     * Implements Classical inheritance by wrapping prototypal inheritance.
     *
     * @param   {Function}      fn
     * @param   {Object}        _super
     * @param   {Function}      ancestor
     * @return  {ClassFactory}
     * @constructor
     * @global
     */
    var defineClass = function(fn, _super, ancestor) {
        var member;

        // Get a _preInstance.
        var _preInstance                = new fn;

        // Extend the _preInstance with members from the inheritted class, if any.
        if (typeof ancestor == 'function'
            ||  (typeof ancestor == 'object' && Object.prototype.toString.call(ancestor) == '[object Object]')) {

            if (typeof ancestor._classical_extend == 'function') {
                return ancestor._classical_extend(fn);
            }
            else {
                var AncestralClass      = (typeof ancestor == 'function') ? new ancestor : dereference(ancestor);

                for (member in AncestralClass) {
                    // WARNING: Not using hasOwnProperty here because Node EventEmitter does not have its
                    //          methods as its own properties. This creates a pretty big opening if
                    //          someone foolishly modifies the Object prototype.
                    AncestralClass[member]                  = Public(AncestralClass[member]);
                    if (typeof _preInstance[member] == 'undefined') {
                        _preInstance[member]                = AncestralClass[member];
                    }
                }
            }
        }

        // Create a copy of the SuperClass to set the prototype.
        initializing                    = true;
        var SuperClass                  = (typeof this == 'function') ? this : BaseClass;
        if (typeof ancestor == 'function') {
            SuperClass.prototype        = AncestralClass;
        }
        var prototype                   = new SuperClass;
        initializing                    = false;

        // Establish a baseline prototype chain.
        var base                        = function() {};
        base.prototype                  = prototype;

        // Extend the _preInstance with the members from the SuperClass
        if (_super !== undefined) {
            for (member in _super) {
                if (member != 'constructor' && _super.hasOwnProperty(member)) {
                    if ((_super[member]._visibility == 'Public' || _super[member]._visibility == 'Protected')
                        && typeof _preInstance[member] == 'undefined') {

                        _preInstance[member]                = _super[member];
                    }
                }
            }

            // Add the _super to the _preInstance, for construction and this._super purposes.
            _preInstance._super         = _super;
        }
        else if (AncestralClass !== undefined) {
            _preInstance._super         = AncestralClass;
        }

        return getClassFactory(base, prototype, _preInstance, arguments.callee);
    };

    var getClassFactory = function(base, prototype, _preInstance, extend) {
        var member;

        // Set up the ClassFactory.  This is what actually gets instantiated.
        var ClassFactory = function Class() {
            var _instance               = new base;
            var _public                 = new base;

            _instance._classical_public= _public;

            if (!initializing) {
                assemble(_instance, _instance, _public, _preInstance);
                construct(_instance, _instance, arguments);
            }

            return _public;
        };

        // Bind the ClassFactory to the prototype (for the inheritance chain).
        ClassFactory.prototype          = prototype;

        // Set up static methods.
        for (member in _preInstance) {
            if (member != '_super' && _preInstance.hasOwnProperty(member)) {
                // While we're at it, let's also make sure visibility has been set.
                if (!_preInstance[member].hasOwnProperty('_visibility')) {
                    _preInstance[member]                    = Public(_preInstance[member]);
                }

                if (_preInstance[member]._static === true && _preInstance[member]._visibility == 'Public') {
                    ClassFactory[member]                    = copyValue(_preInstance[member]._value, ClassFactory, _preInstance[member]._static);
                }
            }
        }

        // Setup a method to extend the base class.
        ClassFactory._classical_extend = function(newfn) {
            return extend.call(ClassFactory, newfn, _preInstance);
        };

        // Assembles the instance and its public accessors.
        var assemble = function(_context, _instance, _public, _preInstance) {
            var member;

            if (typeof _preInstance != 'undefined' && typeof _preInstance._super != 'undefined') {
                _instance._super                            = new base;
                assemble(_context, _instance._super, {}, _preInstance._super);
            }

            for (member in _preInstance) {
                if (member != '_super' && _preInstance.hasOwnProperty(member)) {
                    if (_preInstance[member]._visibility != 'Private' || _context === _instance) {
                        _instance[member]                   = copyValue(_preInstance[member]._value, _context,
                                                                        _preInstance[member]._static);

                        if (_preInstance[member]._visibility == 'Public') {
                            _public[member]                 = _instance[member];
                        }
                    }
                }
            }
        };

        // Recursively calls the constructors for the class, starting with the ancestor
        // and working towards the instance.
        var construct = function(context, target, arguments) {
            // Call the SuperClass constructors first.
            if (target._super instanceof BaseClass) {
                construct(context, target._super, arguments);
            }

            // Call the instance constructor.
            if (typeof target.constructor == 'function' && target.hasOwnProperty('constructor')) {
                target.constructor.apply(context, arguments);
            }
        };

        return ClassFactory;
    };

    /**
     * Performs a deep clone to dereference an object.
     *
     * @param   {*}     source
     * @return  {*}
     */
    var dereference = function(source) {
        var target;

        if (typeof source == 'object' && source !== null) {
            target = (typeof source.length == 'number') ? [] : {};

            for (var i in source) {
                if (source.hasOwnProperty(i)) {
                    target[i]           = dereference(source[i]);
                }
            }
        }
        else {
            target                      = source;
        }

        return target;
    };

    /**
     * Used to prevent calling the constructor during ClassFactory creation.
     * @type    {Boolean}
     */
    var initializing = false;

    /**
     * Returns a dereferenced copy of a value, bound to the target if it is a function.
     *
     * @param   {*}         member
     * @param   {Object}    target
     * @param   {Boolean}   _static
     * @return  {*}
     */
    var copyValue = function(member, target, _static) {
        if (typeof member == 'function') {
            return member.bind(target);
        }
        else {
            return (!_static ? dereference(member) : member);
        }
    };

    /**
     * A common interface for the Public, Private, and Protected APIs.
     * @param   {*}         member
     * @return  {Object}
     */
    var setVisibility = function(member, visibility) {
        return {
            _value                      : member,
            _visibility                 : visibility,
            _static                     : false
        }
    };

    /**
     * A wrapper around the Public, Private, and Protected APIs to make a method static.
     * @param   {Object}    member
     * @return  {Object}
     */
    var setStatic = function(member) {
        member._static                  = true;
        return member;
    };

    // Set up the global Classical variables.
    global.Classical                    = global.Classical || {};
    global.Classical.Class              = module.exports.Class;
    global.Classical.Extend             = module.exports.Extend;
    global.Classical.Public             = module.exports.Public;
    global.Classical.Private            = module.exports.Private;
    global.Classical.Protected          = module.exports.Protected;
    global.Classical.Static             = module.exports.Static;

    // Register classical globals.
    if ((typeof process != 'undefined' && typeof process.env != 'undefined' && process.env.CLASSICAL_PROTECTGLOBALS !== true)
        ||  (typeof window != 'undefined' && window.CLASSICAL_PROTECTGLOBALS !== true)
        ||  (typeof global != 'undefined' && global.CLASSICAL_PROTECTGLOBALS !== true)) {
        global.Class                    = global.Classical.Class;
        global.Extend                   = global.Classical.Extend;
        global.Public                   = global.Classical.Public;
        global.Private                  = global.Classical.Private;
        global.Protected                = global.Classical.Protected;
        global.Static                   = global.Classical.Static;
    }

    return module.exports;
};

if (typeof window != 'undefined') {
    // requirejs
    define(['require', 'module', 'Classical'], b.bind(this, window));
}
else if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
    // nodejs
    b(global, require, module);
}
else {
    // web workers
    b(this, null, this);
}
<|endoftext|>


<commit_before>define( [ 'collection/Map' ], function( _Map ) {

  var instance = null;

  var Event = function( type, handler ) {
    this.type = type;
    this.handler = handler;
  };

  var Message = function( from, to, type, message, handler ) {
    this.from = from;
    this.to = to;
    this.type = type;
    this.message = message;
    this.handler = handler;
  };

  var EventManager = function() {
    this.listeners = new _Map();
    this.iterator = this.listeners.iterator();
  }

  EventManager.prototype.addListener = function( id, eventType, handler ) {
    this.listeners.put( id, new Event( eventType, handler ) );
  };

  EventManager.prototype.notify = function( eventType, params ) {
    this.iterator.first();
    var evt;

    // iterate through listeners that observe that eventType
    while ( this.iterator.hasNext() ) {
      evt = this.iterator.next();

      if ( evt.type === eventType ) {
        evt.handler( params );
      }
    }
  };

  EventManager.prototype.removeListener = function( id ) {
    this.listeners.remove( id );
  };

  EventManager.getInstance = function() {
    if ( instance === null ) {
      instance = new EventManager();
    }
    return instance;
  };

  return EventManager.getInstance();
} );
<commit_msg>Minor fix on EventManager to avoid redundant parameters<commit_after>define( [ 'collection/Map' ], function( _Map ) {

  var instance = null;

  var Event = function( type, handler ) {
    this.type = type;
    this.handler = handler;
  };

  var Message = function( from, to, type, message, handler ) {
    this.from = from;
    this.to = to;
    this.type = type;
    this.message = message;
    this.handler = handler;
  };

  var EventManager = function() {
    this.listeners = new _Map();
    this.iterator = this.listeners.iterator();
  }

  EventManager.prototype.addListener = function( eventType, handler ) {
    this.listeners.put( eventType, new Event( eventType, handler ) );
  };

  EventManager.prototype.notify = function( eventType, params ) {
    this.iterator.first();
    var evt;

    // iterate through listeners that observe that eventType
    while ( this.iterator.hasNext() ) {
      evt = this.iterator.next();

      if ( evt.type === eventType ) {
        evt.handler( params );
      }
    }
  };

  EventManager.prototype.removeListener = function( eventType ) {
    this.listeners.remove( eventType );
  };

  EventManager.getInstance = function() {
    if ( instance === null ) {
      instance = new EventManager();
    }
    return instance;
  };

  return EventManager.getInstance();
} );
<|endoftext|>


<commit_before>define([
	"../var/support"
], function( support ) {

(function () {
	var fragment = document.createDocumentFragment(),
		div = document.createElement("div"),
		input = document.createElement("input");

	input.type = "checkbox";

	// Setup
	div.setAttribute( "className", "t" );
	div.innerHTML = "  <link/>

a";

	// IE strips leading whitespace when .innerHTML is used
	support.leadingWhitespace = div.firstChild.nodeType === 3;

	// Make sure that tbody elements aren't automatically inserted
	// IE will insert them into empty tables
	support.tbody = !div.getElementsByTagName( "tbody" ).length;

	// Make sure that link elements get serialized correctly by innerHTML
	// This requires a wrapper element in IE
	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;

	// Makes sure cloning an html5 element does not cause problems
	// Where outerHTML is undefined, this still works
	support.html5Clone =
		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";

	// Make sure checked status is properly cloned
	input.checked = true;
	support.noCloneChecked = input.cloneNode( true ).checked;

	// Check if a disconnected checkbox will retain its checked
	// value of true after appended to the DOM (IE6/7)
	fragment.appendChild( input );
	support.appendChecked = input.checked;

	// #11217 - WebKit loses check when the name is after the checked attribute
	fragment.appendChild( div );
	div.innerHTML = "<input type='radio' checked name='t'/>";

	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
	// old WebKit doesn't clone checked state correctly in fragments
	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Support: IE<9
	// Opera does not clone events (and typeof div.attachEvent === undefined).
	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
	support.noCloneEvent = true;
	if ( div.attachEvent ) {
		div.attachEvent( "onclick", function() {
			support.noCloneEvent = false;
		});

		div.cloneNode( true ).click();
	}

	// Execute the test only if not already executed in another module.
	if (support.deleteExpando == null) {
		// Support: IE<9
		support.deleteExpando = true;
		try {
			delete div.test;
		} catch( e ) {
			support.deleteExpando = false;
		}
	}

	// Null elements to avoid leaks in IE.
	fragment = div = input = null;
})();

return support;

});
<commit_msg>No ticket: Fix XHTML regression. Close gh-1376.<commit_after>define([
	"../var/support"
], function( support ) {

(function () {
	var fragment = document.createDocumentFragment(),
		div = document.createElement("div"),
		input = document.createElement("input");

	input.type = "checkbox";

	// Setup
	div.setAttribute( "className", "t" );
	div.innerHTML = "  <link/>

a";

	// IE strips leading whitespace when .innerHTML is used
	support.leadingWhitespace = div.firstChild.nodeType === 3;

	// Make sure that tbody elements aren't automatically inserted
	// IE will insert them into empty tables
	support.tbody = !div.getElementsByTagName( "tbody" ).length;

	// Make sure that link elements get serialized correctly by innerHTML
	// This requires a wrapper element in IE
	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;

	// Makes sure cloning an html5 element does not cause problems
	// Where outerHTML is undefined, this still works
	support.html5Clone =
		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";

	// Make sure checked status is properly cloned
	input.checked = true;
	support.noCloneChecked = input.cloneNode( true ).checked;

	// Check if a disconnected checkbox will retain its checked
	// value of true after appended to the DOM (IE6/7)
	fragment.appendChild( input );
	support.appendChecked = input.checked;

	// #11217 - WebKit loses check when the name is after the checked attribute
	fragment.appendChild( div );
	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";

	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
	// old WebKit doesn't clone checked state correctly in fragments
	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;

	// Support: IE<9
	// Opera does not clone events (and typeof div.attachEvent === undefined).
	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
	support.noCloneEvent = true;
	if ( div.attachEvent ) {
		div.attachEvent( "onclick", function() {
			support.noCloneEvent = false;
		});

		div.cloneNode( true ).click();
	}

	// Execute the test only if not already executed in another module.
	if (support.deleteExpando == null) {
		// Support: IE<9
		support.deleteExpando = true;
		try {
			delete div.test;
		} catch( e ) {
			support.deleteExpando = false;
		}
	}

	// Null elements to avoid leaks in IE.
	fragment = div = input = null;
})();

return support;

});
<|endoftext|>


<commit_before>var keys = $('.keys');
var allNotes = [];
var allEvents = [];
var pxPerMillis = 0;
var millisPerTick = 0;
var endTime = 0;

for(var pitch=108; pitch>=21; pitch--) { // A0 to C8
  var note = noteFromMidiPitch(pitch);
  var keyClass = note.indexOf('#')>-1 ? 'key sharp':'key';
  var keyHtml = '
'+note+'
';
  keys.append('
'+keyHtml+'

');
}
keys.scrollTop(keys.offset().top + (keys.height() / 2));

function noteFromMidiPitch(p) {
  var noteDict = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
  var octave = Math.floor((p-12)/12);
  var note = noteDict[p-octave*12-12];
  return note+octave;
}

function drawSong() {
  allEvents = [];
  allNotes = [];
  endTime = 0;
  var openNotes = [];
  song.tracks.forEach(function(track) {
    var time = 0;
    track.forEach(function(event) {
      time += parseInt(event.deltaTime*millisPerTick);
      if(event.subtype === 'noteOn') {
        var pitch = event.noteNumber;
        openNotes[pitch] = time;
      }
      else if(event.subtype === 'noteOff') {
        var pitch = event.noteNumber;
        var channel = event.channel;
        var startTime = openNotes[pitch];
        openNotes[pitch] = null;
        var newNote = {
          pitch: pitch,
          startTime: startTime,
          deltaTime: time-startTime,
          channel: channel
        };
        allNotes.push(newNote);
      }
      else if(event.subtype === 'setTempo') {
        millisPerTick = event.microsecondsPerBeat/(1000*song.header.ticksPerBeat);
      }
      allEvents.push({
        subtype:event.subtype,
        pitch:event.noteNumber,
        channel:event.channel,
        velocity:event.velocity,
        time:time
      });
    });
    if(endTime<time) endTime = time;
  });

  pxPerMillis = 10000/endTime;
  $('.keys li .notes').html('');
  allNotes.forEach(function(note) {
    var notePos = ~~(pxPerMillis*note.startTime);
    var noteWidth = ~~(pxPerMillis*note.deltaTime);
    var noteStyle = 'left:'+notePos+'px; width:'+noteWidth+'px;';
    var noteHtml = '

';
    $('.keys li[pitch="'+note.pitch+'"] .notes').append(noteHtml);
  });
  allEvents = allEvents.sort(function(a, b) {
    return a.time-b.time;
  });
}

function playSong() {
  var time = 0;
  var currentTransform = 0;
  MIDI.loadPlugin({
    soundfontUrl: "./soundfont/",
    instrument: 0,
    callback: function() {
      $('.notes').css('transform', 'translate(-10000px)');
      $('.notes').css('transition', 'linear all ' + endTime + 'ms');
      nextEvent(0, 0, Date.now());
    }
  });

  function nextEvent(i, prevTime, startTime) {
    var event = allEvents[i];
    var time = event.time;
    var dt = Date.now()-startTime;
    if(dt > time) {
      time -= dt-time; // adjust for time delay
    }
    setTimeout(function() {
      if(event.subtype === 'noteOn') {
        $('.keys li[pitch="'+event.pitch+'"] .key').addClass('active');
        MIDI.noteOn(event.channel, event.pitch, event.velocity, 0);
      }
      else if(event.subtype === 'noteOff') {
        $('.keys li[pitch="'+event.pitch+'"] .key').removeClass('active');
        MIDI.noteOff(event.channel, event.pitch, 0);
      }
      if(i<allEvents.length-1)
        nextEvent(i+1, event.time, startTime);
    }, time-prevTime);
  }
}
<commit_msg>fix playback bug<commit_after>var keys = $('.keys');
var allNotes = [];
var allEvents = [];
var pxPerMillis = 0;
var millisPerTick = 0;
var endTime = 0;

for(var pitch=108; pitch>=21; pitch--) { // A0 to C8
  var note = noteFromMidiPitch(pitch);
  var keyClass = note.indexOf('#')>-1 ? 'key sharp':'key';
  var keyHtml = '
'+note+'
';
  keys.append('
'+keyHtml+'

');
}
keys.scrollTop(keys.offset().top + (keys.height() / 2));

function noteFromMidiPitch(p) {
  var noteDict = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
  var octave = Math.floor((p-12)/12);
  var note = noteDict[p-octave*12-12];
  return note+octave;
}

function drawSong() {
  allEvents = [];
  allNotes = [];
  endTime = 0;
  var openNotes = [];
  song.tracks.forEach(function(track) {
    var time = 0;
    track.forEach(function(event) {
      time += parseInt(event.deltaTime*millisPerTick);
      if(event.subtype === 'noteOn') {
        var pitch = event.noteNumber;
        openNotes[pitch] = time;
      }
      else if(event.subtype === 'noteOff') {
        var pitch = event.noteNumber;
        var channel = event.channel;
        var startTime = openNotes[pitch];
        openNotes[pitch] = null;
        var newNote = {
          pitch: pitch,
          startTime: startTime,
          deltaTime: time-startTime,
          channel: channel
        };
        allNotes.push(newNote);
      }
      else if(event.subtype === 'setTempo') {
        millisPerTick = event.microsecondsPerBeat/(1000*song.header.ticksPerBeat);
      }
      allEvents.push({
        subtype:event.subtype,
        pitch:event.noteNumber,
        channel:event.channel,
        velocity:event.velocity,
        time:time
      });
    });
    if(endTime<time) endTime = time;
  });

  pxPerMillis = 10000/endTime;
  $('.keys li .notes').html('');
  allNotes.forEach(function(note) {
    var notePos = ~~(pxPerMillis*note.startTime);
    var noteWidth = ~~(pxPerMillis*note.deltaTime);
    var noteStyle = 'left:'+notePos+'px; width:'+noteWidth+'px;';
    var noteHtml = '

';
    $('.keys li[pitch="'+note.pitch+'"] .notes').append(noteHtml);
  });
  allEvents = allEvents.sort(function(a, b) {
    if(a.time === b.time) {
      if(a.subtype === 'noteOff') {
        return -1;
      }
      else {
        return 1;
      }
    }
    return a.time-b.time;
  });
}

function playSong() {
  var time = 0;
  var currentTransform = 0;
  MIDI.loadPlugin({
    soundfontUrl: "./soundfont/",
    instrument: 0,
    callback: function() {
      $('.notes').css('transform', 'translate(-10000px)');
      $('.notes').css('transition', 'linear all ' + endTime + 'ms');
      nextEvent(0, 0, Date.now());
    }
  });

  function nextEvent(i, prevTime, startTime) {
    var event = allEvents[i];
    var time = event.time;
    var dt = Date.now()-startTime;
    if(dt > time) {
      time -= dt-time; // adjust for time delay
    }
    setTimeout(function() {
      if(event.subtype === 'noteOn') {
        $('.keys li[pitch="'+event.pitch+'"] .key').addClass('active');
        MIDI.noteOn(event.channel, event.pitch, event.velocity, 0);
      }
      else if(event.subtype === 'noteOff') {
        $('.keys li[pitch="'+event.pitch+'"] .key').removeClass('active');
        MIDI.noteOff(event.channel, event.pitch, 0);
      }
      if(i<allEvents.length-1)
        nextEvent(i+1, event.time, startTime);
    }, time-prevTime);
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 */

/* eslint-disable lint/no-value-import */
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import {useLatestVersion, useVersions} from '@theme/hooks/useDocs';
import Layout from '@theme/Layout';
import React from 'react';
/* eslint-enable lint/no-value-import */

function Version() {
  const {siteConfig} = useDocusaurusContext();
  const versions = useVersions();
  const latestVersion = useLatestVersion();
  const currentVersion = versions.find(version => version.name === 'current');
  const pastVersions = versions.filter(
    version =>
      version !== latestVersion.name && version !== currentVersion.name,
  );
  const repoUrl = `https://github.com/${siteConfig.organizationName}/${siteConfig.projectName}`;

  return (
    <Layout
      title="Versions"
      description="Relay Versions page listing all documented site versions">

Relay documentation versions

        {latestVersion && (

Current version (Stable)

              Here you can find the documentation for current released version.

                  {latestVersion.label}

                    <Link to={latestVersion.path}>Documentation</Link>

                    <a href={`${repoUrl}/releases/tag/v${latestVersion.name}`}>
                      Release Notes

        )}

        {currentVersion !== latestVersion && (

Next version (Unreleased)

              Here you can find the documentation for work-in-process unreleased
              version.

                  {currentVersion.label}

                    <Link to={currentVersion.path}>Documentation</Link>

        )}

        {pastVersions.length > 0 && (

Past versions

              Here you can find documentation for previous versions of Relay.

                {pastVersions.map(version => (

                    {version.label}

                      <Link to={version.path}>Documentation</Link>

                      {version.name.startsWith('v') ? (
                        <a href={`${repoUrl}/releases/tag/${version.name}`}>
                          Release Notes

                      ) : null}

                ))}

        )}

    </Layout>
  );
}

export default Version;
<commit_msg>fix(website): Broken link on versions page (#3996)<commit_after>/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @format
 */

/* eslint-disable lint/no-value-import */
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import {useLatestVersion, useVersions} from '@theme/hooks/useDocs';
import Layout from '@theme/Layout';
import React from 'react';
/* eslint-enable lint/no-value-import */

function Version() {
  const {siteConfig} = useDocusaurusContext();
  const versions = useVersions();
  const latestVersion = useLatestVersion();
  const currentVersion = versions.find(version => version.name === 'current');
  const pastVersions = versions.filter(
    version =>
      version !== latestVersion.name && version !== currentVersion.name,
  );
  const repoUrl = `https://github.com/${siteConfig.organizationName}/${siteConfig.projectName}`;

  return (
    <Layout
      title="Versions"
      description="Relay Versions page listing all documented site versions">

Relay documentation versions

        {latestVersion && (

Current version (Stable)

              Here you can find the documentation for current released version.

                  {latestVersion.label}

                    <Link to={latestVersion.path}>Documentation</Link>

                    <a href={`${repoUrl}/releases/tag/${latestVersion.name}`}>
                      Release Notes

        )}

        {currentVersion !== latestVersion && (

Next version (Unreleased)

              Here you can find the documentation for work-in-process unreleased
              version.

                  {currentVersion.label}

                    <Link to={currentVersion.path}>Documentation</Link>

        )}

        {pastVersions.length > 0 && (

Past versions

              Here you can find documentation for previous versions of Relay.

                {pastVersions.map(version => (

                    {version.label}

                      <Link to={version.path}>Documentation</Link>

                      {version.name.startsWith('v') ? (
                        <a href={`${repoUrl}/releases/tag/${version.name}`}>
                          Release Notes

                      ) : null}

                ))}

        )}

    </Layout>
  );
}

export default Version;
<|endoftext|>


<commit_before>define(["sugar-web/activity/activity","webL10n","sugar-web/graphics/palette","sugar-web/graphics/presencepalette","sugar-web/datastore","sugar-web/graphics/journalchooser"], function (activity,wl10n, palette,presencepalette,datastore,chooser) {
    var activity = requirejs("sugar-web/activity/activity");

    // Manipulate the DOM only when it is ready.
    requirejs(['domReady!'], function (doc) {

        // Initialize the activity.
		activity.setup();

		var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
		//sanitize html messages
		var tagOrComment = new RegExp(
			'<(?:'
			// Comment body.
			+ '!--(?:(?:-*[^->])*--+|-?)'
			// Special "raw text" elements whose content should be elided.
			+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
			+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
			// Regular name
			+ '|/?[a-z]'
			+ tagBody
			+ ')>',
			'gi');
		function removeTags(html) {
			var oldHtml;
			do {
				oldHtml = html;
				html = html.replace(tagOrComment, '');
			} while (html !== oldHtml);
		return html.replace(/</g, '<');
		}

        var form = document.getElementById('message-form');
        var messageField = document.getElementById('message');
        var messagesList = document.getElementById('messages');
        var socketStatus = document.getElementById('status');
        var messageContent = document.getElementById('content');
        var imageUpload = document.getElementById('image-upload');

	document.getElementById("status").innerHTML = l10n_s.get("status");
	messageField.placeholder = l10n_s.get("WriteYourMessage");

	    var userSettings = null;

		// Connect to network
        var presenceObject;
		function shareActivity() {
			presenceObject = activity.getPresenceObject(function (error, presence) {
				// Unable to join
				if (error)  {
					socketStatus.innerHTML = l10n_s.get('Error');
					socketStatus.className = 'error';
					return;
				}

				// Store settings
				userSettings = presence.getUserInfo();
				socketStatus.innerHTML = l10n_s.get('Connected');
				socketStatus.className = 'open';
				messageField.readOnly = false;

				// Not found, create a new shared activity
				if (!window.top.sugar.environment.sharedId) {
					presence.createSharedActivity('org.sugarlabs.ChatPrototype', function (groupId) {
					});
				}

				// Show a disconnected message when the WebSocket is closed.
				presence.onConnectionClosed(function (event) {
					console.log(l10n_s.get("ConnectionClosed"));
					socketStatus.innerHTML = l10n_s.get('DisconnectedFromWebSocket');
					socketStatus.className = 'closed';
				});

				// Display connection changed
				presence.onSharedActivityUserChanged(function (msg) {
					var userName = msg.user.name.replace('<','<').replace('>','>');
					messagesList.innerHTML += '
' + userName + ' ' + (msg.move>0?l10n_s.get('Join'):l10n_s.get('Leave')) + ' '+l10n_s.get('Chat')+'
';
					imageUpload.style.visibility = "visible";
				});

				// Handle messages received
				presence.onDataReceived(function (msg) {

					if(msg.type=='text' || typeof(msg.type) == 'undefined'){
						var text = msg.content;
						var author = msg.user.name.replace('<','<').replace('>','>');
						var colour = msg.user.colorvalue;

						var authorElem = '' + author + '';

						myElem = document.createElement('li');
						myElem.class = 'received';
						myElem.style.background = colour.fill;
						myElem.innerHTML = authorElem + text;
						myElem.style.color = colour.stroke;

						messagesList.appendChild(myElem);
						messageContent.scrollTop = messageContent.scrollHeight;
					}
					else if(msg.type == "image"){
						var source = msg.content;
						var author = msg.user.name.replace('<','<').replace('>','>');
						var colour = msg.user.colorvalue;

						var authorElem = '' + author + '';
						myElem = document.createElement('li');
						myElem.class = 'received';
						myElem.style.background = colour.fill;
						myElem.innerHTML = authorElem + "";
						myElem.style.color = colour.stroke;

						messagesList.appendChild(myElem);
						messageContent.scrollTop = messageContent.scrollHeight;

					}
				});
			});
		}

		function senddata(data,mediatype){
			var toSend = {user: userSettings, content: data , type:mediatype};
			presenceObject.sendMessage(presenceObject.getSharedInfo().id, toSend);
		}

		// Create network palette
        var networkButton = document.getElementById("network-button");
		presencepalette = new presencepalette.PresencePalette(networkButton, undefined);
		presencepalette.addEventListener('shared', shareActivity);

		// Launched with a shared id, activity is already shared
		if (window.top.sugar.environment.sharedId) {
			shareActivity();
			presencepalette.setShared(true);
		}

		// Handle message text update
        messageField.onkeydown = function (e) {
            if (e.keyCode === 13) {
				var message = removeTags(messageField.value);
				senddata(message,'text');

				// Send the message through the WebSocket.

                // Clear out the message field
				messageField.placeholder = l10n_s.get("WriteYourMessage");
                messageField.value = "";
				messageField.setSelectionRange(0,0);
				return false;
            }
        };

		imageUpload.addEventListener('click', function (e) {
			chooser.show(function (entry) {
				// No selection
				if (!entry) {
					return;
				}
				// Get object content
				var dataentry = new datastore.DatastoreObject(entry.objectId);
				dataentry.loadAsText(function (err, metadata, data) {
					senddata(data,'image');
				});
			}, { mimetype: 'image/png' }, { mimetype: 'image/jpeg' });
		});

	    //Smiley Emoji options
        var selectSmiley = document.getElementById('smiley-button')
        var smileyOption;
        var smileyRange = [
          [128513, 128515], [128517, 128519], [128521, 128528] //Array of happy emojis
        ];

        for (var i = 0; i < smileyRange.length; i++) {
          var range = smileyRange[i];
          for (var x = range[0]; x < range[1]; x++) {

            smileyOption = document.createElement('option');
            smileyOption.value = x;
            smileyOption.innerHTML = "&#" + x + ";";
            selectSmiley.appendChild(smileyOption);
          }

        }

        //Sad Emoji options
          var selectSad = document.getElementById('sad-button')
          var sadOption;
          var sadRange = [
            [128531, 128533], [128545, 128551], [128555, 128558] //Array of sad or upset emojis
          ];

          for (var i = 0; i < sadRange.length; i++) {
            var range = sadRange[i];
            for (var x = range[0]; x < range[1]; x++) {

              sadOption = document.createElement('option');
              sadOption.value = x;
              sadOption.innerHTML = "&#" + x + ";";
              selectSad.appendChild(sadOption);
            }

          }

          //Others Emoji options
            var selectOthers = document.getElementById('others-button')
            var otherOption;
            var otherRange = [
              [128568, 128573], [128582, 128588] //Array of other emojis
            ];

            for (var i = 0; i < otherRange.length; i++) {
              var range = otherRange[i];
              for (var x = range[0]; x < range[1]; x++) {

                otherOption = document.createElement('option');
                otherOption.value = x;
                otherOption.innerHTML = "&#" + x + ";";
                selectOthers.appendChild(otherOption);
              }

            }
    });

});
<commit_msg>Fix Long name Issue #383<commit_after>define(["sugar-web/activity/activity","webL10n","sugar-web/graphics/palette","sugar-web/graphics/presencepalette","sugar-web/datastore","sugar-web/graphics/journalchooser"], function (activity,wl10n, palette,presencepalette,datastore,chooser) {
    var activity = requirejs("sugar-web/activity/activity");

    // Manipulate the DOM only when it is ready.
    requirejs(['domReady!'], function (doc) {

        // Initialize the activity.
		activity.setup();

		var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
		//sanitize html messages
		var tagOrComment = new RegExp(
			'<(?:'
			// Comment body.
			+ '!--(?:(?:-*[^->])*--+|-?)'
			// Special "raw text" elements whose content should be elided.
			+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
			+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
			// Regular name
			+ '|/?[a-z]'
			+ tagBody
			+ ')>',
			'gi');
		function removeTags(html) {
			var oldHtml;
			do {
				oldHtml = html;
				html = html.replace(tagOrComment, '');
			} while (html !== oldHtml);
		return html.replace(/</g, '<');
		}

        var form = document.getElementById('message-form');
        var messageField = document.getElementById('message');
        var messagesList = document.getElementById('messages');
        var socketStatus = document.getElementById('status');
        var messageContent = document.getElementById('content');
        var imageUpload = document.getElementById('image-upload');

	document.getElementById("status").innerHTML = l10n_s.get("status");
	messageField.placeholder = l10n_s.get("WriteYourMessage");

	    var userSettings = null;

		// Connect to network
        var presenceObject;
		function shareActivity() {
			presenceObject = activity.getPresenceObject(function (error, presence) {
				// Unable to join
				if (error)  {
					socketStatus.innerHTML = l10n_s.get('Error');
					socketStatus.className = 'error';
					return;
				}

				// Store settings
				userSettings = presence.getUserInfo();
				socketStatus.innerHTML = l10n_s.get('Connected');
				socketStatus.className = 'open';
				messageField.readOnly = false;

				// Not found, create a new shared activity
				if (!window.top.sugar.environment.sharedId) {
					presence.createSharedActivity('org.sugarlabs.ChatPrototype', function (groupId) {
					});
				}

				// Show a disconnected message when the WebSocket is closed.
				presence.onConnectionClosed(function (event) {
					console.log(l10n_s.get("ConnectionClosed"));
					socketStatus.innerHTML = l10n_s.get('DisconnectedFromWebSocket');
					socketStatus.className = 'closed';
				});

				// Display connection changed
				presence.onSharedActivityUserChanged(function (msg) {
					var userName = msg.user.name.replace('<','<').replace('>','>');
					messagesList.innerHTML += '
' + userName + ' ' + (msg.move>0?l10n_s.get('Join'):l10n_s.get('Leave')) + ' '+l10n_s.get('Chat')+'
';
					imageUpload.style.visibility = "visible";
				});

				// Handle messages received
				presence.onDataReceived(function (msg) {

					if(msg.type=='text' || typeof(msg.type) == 'undefined'){
						var text = msg.content;
						var author = msg.user.name.replace('<','<').replace('>','>');
						var colour = msg.user.colorvalue;

						var authorElem = '' + author + '';

						myElem = document.createElement('li');
						myElem.class = 'received';
						myElem.style.background = colour.fill;
						myElem.innerHTML = authorElem + text;
						myElem.style.color = colour.stroke;

						messagesList.appendChild(myElem);
						messageContent.scrollTop = messageContent.scrollHeight;
					}
					else if(msg.type == "image"){
						var source = msg.content;
						var author = msg.user.name.replace('<','<').replace('>','>');
						var colour = msg.user.colorvalue;

						var authorElem = '' + author + '';
						myElem = document.createElement('li');
						myElem.class = 'received';
						myElem.style.background = colour.fill;
						myElem.innerHTML = authorElem + "";
						myElem.style.color = colour.stroke;

						messagesList.appendChild(myElem);
						messageContent.scrollTop = messageContent.scrollHeight;

					}
				});
			});
		}

		function senddata(data,mediatype){
			var toSend = {user: userSettings, content: data , type:mediatype};
			presenceObject.sendMessage(presenceObject.getSharedInfo().id, toSend);
		}

		// Create network palette
        var networkButton = document.getElementById("network-button");
		presencepalette = new presencepalette.PresencePalette(networkButton, undefined);
		presencepalette.addEventListener('shared', shareActivity);

		// Launched with a shared id, activity is already shared
		if (window.top.sugar.environment.sharedId) {
			shareActivity();
			presencepalette.setShared(true);
		}

		// Handle message text update
        messageField.onkeydown = function (e) {
            if (e.keyCode === 13) {
				var message = removeTags(messageField.value);
				senddata(message,'text');

				// Send the message through the WebSocket.

                // Clear out the message field
				messageField.placeholder = l10n_s.get("WriteYourMessage");
                messageField.value = "";
				messageField.setSelectionRange(0,0);
				return false;
            }
        };

		imageUpload.addEventListener('click', function (e) {
			chooser.show(function (entry) {
				// No selection
				if (!entry) {
					return;
				}
				// Get object content
				var dataentry = new datastore.DatastoreObject(entry.objectId);
				dataentry.loadAsText(function (err, metadata, data) {
					senddata(data,'image');
				});
			}, { mimetype: 'image/png' }, { mimetype: 'image/jpeg' });
		});

	    //Smiley Emoji options
        var selectSmiley = document.getElementById('smiley-button')
        var smileyOption;
        var smileyRange = [
          [128513, 128515], [128517, 128519], [128521, 128528] //Array of happy emojis
        ];

        for (var i = 0; i < smileyRange.length; i++) {
          var range = smileyRange[i];
          for (var x = range[0]; x < range[1]; x++) {

            smileyOption = document.createElement('option');
            smileyOption.value = x;
            smileyOption.innerHTML = "&#" + x + ";";
            selectSmiley.appendChild(smileyOption);
          }

        }

        //Sad Emoji options
          var selectSad = document.getElementById('sad-button')
          var sadOption;
          var sadRange = [
            [128531, 128533], [128545, 128551], [128555, 128558] //Array of sad or upset emojis
          ];

          for (var i = 0; i < sadRange.length; i++) {
            var range = sadRange[i];
            for (var x = range[0]; x < range[1]; x++) {

              sadOption = document.createElement('option');
              sadOption.value = x;
              sadOption.innerHTML = "&#" + x + ";";
              selectSad.appendChild(sadOption);
            }

          }

          //Others Emoji options
            var selectOthers = document.getElementById('others-button')
            var otherOption;
            var otherRange = [
              [128568, 128573], [128582, 128588] //Array of other emojis
            ];

            for (var i = 0; i < otherRange.length; i++) {
              var range = otherRange[i];
              for (var x = range[0]; x < range[1]; x++) {

                otherOption = document.createElement('option');
                otherOption.value = x;
                otherOption.innerHTML = "&#" + x + ";";
                selectOthers.appendChild(otherOption);
              }

            }
    });

});
<|endoftext|>