<commit_before>function _extends() {
  _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  return _extends.apply(this, arguments);
}

var defer = function defer() {
  var state = false; // Resolved or not

  var callbacks = [];

  var resolve = function resolve(val) {
    if (state) {
      return;
    }

    state = true;

    for (var i = 0, len = callbacks.length; i < len; i++) {
      callbacks[i](val);
    }
  };

  var then = function then(cb) {
    if (!state) {
      callbacks.push(cb);
      return;
    }

    cb();
  };

  var deferred = {
    resolved: function resolved() {
      return state;
    },
    resolve: resolve,
    promise: {
      then: then
    }
  };
  return deferred;
};

var ownProp = Object.prototype.hasOwnProperty;
function createRecaptcha() {
  var deferred = defer();
  return {
    notify: function notify() {
      deferred.resolve();
    },
    wait: function wait() {
      return deferred.promise;
    },
    render: function render(ele, options, cb) {
      this.wait().then(function () {
        cb(window.grecaptcha.render(ele, options));
      });
    },
    reset: function reset(widgetId) {
      if (typeof widgetId === 'undefined') {
        return;
      }

      this.assertLoaded();
      this.wait().then(function () {
        return window.grecaptcha.reset(widgetId);
      });
    },
    execute: function execute(widgetId) {
      if (typeof widgetId === 'undefined') {
        return;
      }

      this.assertLoaded();
      this.wait().then(function () {
        return window.grecaptcha.execute(widgetId);
      });
    },
    checkRecaptchaLoad: function checkRecaptchaLoad() {
      if (ownProp.call(window, 'grecaptcha') && ownProp.call(window.grecaptcha, 'render')) {
        this.notify();
      }
    },
    assertLoaded: function assertLoaded() {
      if (!deferred.resolved()) {
        throw new Error('ReCAPTCHA has not been loaded');
      }
    }
  };
}
var recaptcha = createRecaptcha();

if (typeof window !== 'undefined') {
  window.vueRecaptchaApiLoaded = recaptcha.notify;
}

var VueRecaptcha = {
  name: 'VueRecaptcha',
  props: {
    sitekey: {
      type: String,
      required: true
    },
    theme: {
      type: String
    },
    badge: {
      type: String
    },
    type: {
      type: String
    },
    size: {
      type: String
    },
    tabindex: {
      type: String
    },
    loadRecaptchaScript: {
      type: Boolean,
      "default": false
    },
    recaptchaScriptId: {
      type: String,
      "default": '__RECAPTCHA_SCRIPT'
    },
    recaptchaHost: {
      type: String,
      "default": 'www.google.com'
    },
    language: {
      type: String,
      "default": ''
    }
  },
  beforeMount: function beforeMount() {
    if (this.loadRecaptchaScript) {
      if (!document.getElementById(this.recaptchaScriptId)) {
        // Note: vueRecaptchaApiLoaded load callback name is per the latest documentation
        var script = document.createElement('script');
        script.id = this.recaptchaScriptId;
        script.src = "https://" + this.recaptchaHost + "/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit&hl=" + this.language;
        script.async = true;
        script.defer = true;
        document.head.appendChild(script);
      }
    }
  },
  mounted: function mounted() {
    var _this = this;

    recaptcha.checkRecaptchaLoad();

    var opts = _extends({}, this.$props, {
      callback: this.emitVerify,
      'expired-callback': this.emitExpired,
      'error-callback': this.emitError
    });

    var container = this.$slots["default"] ? this.$el.children[0] : this.$el;
    recaptcha.render(container, opts, function (id) {
      _this.$widgetId = id;

      _this.$emit('render', id);
    });
  },
  methods: {
    reset: function reset() {
      recaptcha.reset(this.$widgetId);
    },
    execute: function execute() {
      recaptcha.execute(this.$widgetId);
    },
    emitVerify: function emitVerify(response) {
      this.$emit('verify', response);
    },
    emitExpired: function emitExpired() {
      this.$emit('expired');
    },
    emitError: function emitError() {
      this.$emit('error');
    }
  },
  render: function render(h) {
    return h('div', {}, this.$slots["default"]);
  }
};

export default VueRecaptcha;
<commit_msg>ci: Compile [skip ci]<commit_after>function _extends() {
  _extends = Object.assign || function (target) {
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];

      for (var key in source) {
        if (Object.prototype.hasOwnProperty.call(source, key)) {
          target[key] = source[key];
        }
      }
    }

    return target;
  };

  return _extends.apply(this, arguments);
}

var defer = function defer() {
  var state = false; // Resolved or not

  var callbacks = [];

  var resolve = function resolve(val) {
    if (state) {
      return;
    }

    state = true;

    for (var i = 0, len = callbacks.length; i < len; i++) {
      callbacks[i](val);
    }
  };

  var then = function then(cb) {
    if (!state) {
      callbacks.push(cb);
      return;
    }

    cb();
  };

  var deferred = {
    resolved: function resolved() {
      return state;
    },
    resolve: resolve,
    promise: {
      then: then
    }
  };
  return deferred;
};

var ownProp = Object.prototype.hasOwnProperty;
function createRecaptcha() {
  var deferred = defer();
  return {
    notify: function notify() {
      deferred.resolve();
    },
    wait: function wait() {
      return deferred.promise;
    },
    render: function render(ele, options, cb) {
      this.wait().then(function () {
        cb(window.grecaptcha.render(ele, options));
      });
    },
    reset: function reset(widgetId) {
      if (typeof widgetId === 'undefined') {
        return;
      }

      this.assertLoaded();
      this.wait().then(function () {
        return window.grecaptcha.reset(widgetId);
      });
    },
    execute: function execute(widgetId) {
      if (typeof widgetId === 'undefined') {
        return;
      }

      this.assertLoaded();
      this.wait().then(function () {
        return window.grecaptcha.execute(widgetId);
      });
    },
    checkRecaptchaLoad: function checkRecaptchaLoad() {
      if (ownProp.call(window, 'grecaptcha') && ownProp.call(window.grecaptcha, 'render')) {
        this.notify();
      }
    },
    assertLoaded: function assertLoaded() {
      if (!deferred.resolved()) {
        throw new Error('ReCAPTCHA has not been loaded');
      }
    }
  };
}
var recaptcha = createRecaptcha();

if (typeof window !== 'undefined') {
  window.vueRecaptchaApiLoaded = recaptcha.notify;
}

var VueRecaptcha = {
  name: 'VueRecaptcha',
  props: {
    sitekey: {
      type: String,
      required: true
    },
    theme: {
      type: String
    },
    badge: {
      type: String
    },
    type: {
      type: String
    },
    size: {
      type: String
    },
    tabindex: {
      type: String
    },
    loadRecaptchaScript: {
      type: Boolean,
      "default": false
    },
    recaptchaScriptId: {
      type: String,
      "default": '__RECAPTCHA_SCRIPT'
    },
    recaptchaHost: {
      type: String,
      "default": 'www.google.com'
    },
    language: {
      type: String,
      "default": ''
    }
  },
  beforeMount: function beforeMount() {
    if (this.loadRecaptchaScript) {
      if (!document.getElementById(this.recaptchaScriptId)) {
        // Note: vueRecaptchaApiLoaded load callback name is per the latest documentation
        var script = document.createElement('script');
        script.id = this.recaptchaScriptId;
        script.src = "https://" + this.recaptchaHost + "/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit&hl=" + this.language;
        script.async = true;
        script.defer = true;
        document.head.appendChild(script);
      }
    }
  },
  mounted: function mounted() {
    var _this = this;

    recaptcha.checkRecaptchaLoad();

    var opts = _extends({}, this.$props, {
      callback: this.emitVerify,
      'expired-callback': this.emitExpired,
      'error-callback': this.emitError
    });

    var container = this.$slots["default"] ? this.$el.children[0] : this.$el;
    recaptcha.render(container, opts, function (id) {
      _this.$widgetId = id;

      _this.$emit('render', id);
    });
  },
  methods: {
    reset: function reset() {
      recaptcha.reset(this.$widgetId);
    },
    execute: function execute() {
      recaptcha.execute(this.$widgetId);
    },
    emitVerify: function emitVerify(response) {
      this.$emit('verify', response);
    },
    emitExpired: function emitExpired() {
      this.$emit('expired');
    },
    emitError: function emitError() {
      this.$emit('error');
    }
  },
  render: function render(h) {
    return h('div', {}, this.$slots["default"]);
  }
};

export { VueRecaptcha as default };
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { View, Keyboard } from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import TextInputField from '../fields/textInput';
import PickerField from '../fields/picker';
import SwitchField from '../fields/switch';
import DateField from '../fields/date';
import SelectField from '../fields/select';
import FormField from '../fields/form';
import baseTheme from '../theme';
import { autoValidate, getInitState, getDefaultValue, getResetValue } from '../utils/methods';

export default class FormBuilder extends Component {
  static propTypes = {
    fields: React.PropTypes.array,
    theme: React.PropTypes.object,
    customComponents: React.PropTypes.object,
    formData: React.PropTypes.object,
    autoValidation: React.PropTypes.bool,
    customValidation: React.PropTypes.func,
    onValueChange: React.PropTypes.func,
  }
  constructor(props) {
    super(props);
    const initialState = getInitState(props.fields);
    this.state = {
      ...initialState,
      errorStatus: false,
    };
    // Supports Nested
    this.getValues = this.getValues.bind(this);
    // Invoked every time whenever any fields's value changes
    this.onValueChange = this.onValueChange.bind(this);
    // Generate fields
    this.generateFields = this.generateFields.bind(this);
    // forcefully set values for particular fields
    this.setValues = this.setValues.bind(this);
    // forcefully set default values for particular fields
    this.setToDefault = this.setToDefault.bind(this);
    /*
     forcefully set errors for a particular field
    this.setErrors = this.setErrors.bind(this);
     reset errors to default for all fields
    this.resetErrors = this.resetErrors.bind(this);
     reset values to default for all fields
    this.resetValues = this.resetValues.bind(this);
    Currently Not needed but can be added in future
    */
    //  reset form values to default as well as errors
    this.resetForm = this.resetForm.bind(this);
    // Manages textInput Focus
    this.onSummitTextInput = this.onSummitTextInput.bind(this);
  }
  componentDidMount() {
    const { formData } = this.props;
    this.setValues(formData);
  }
  onSummitTextInput(name) {
    const index = Object.keys(this.state).indexOf(name);
    if (index !== -1 && this[Object.keys(this.state)[index + 1]]
    && this[Object.keys(this.state)[index + 1]].textInput) {
      this[Object.keys(this.state)[index + 1]].textInput._root.focus();
    } else {
      Keyboard.dismiss();
    }
  }
  onValueChange(name, value) {
    const valueObj = this.state[name];
    if (valueObj) {
      valueObj.value = value;
      // Not Validate fields only when autoValidation prop is false
      if (this.props.autoValidation === undefined || this.props.autoValidation) {
        Object.assign(valueObj, autoValidate(valueObj));
      }
      // Validate through customValidation if it is present in props
      if (this.props.customValidation
         && typeof this.props.customValidation === 'function') {
        Object.assign(valueObj, this.props.customValidation(valueObj));
      }
      const newField = {};
      newField[valueObj.name] = valueObj;
      // this.props.customValidation(valueObj);
      if (this.props.onValueChange &&
        typeof this.props.onValueChange === 'function') {
        this.setState({ ...newField }, () => this.props.onValueChange());
      } else {
        this.setState({ ...newField });
      }
    }
  }
  // Returns the values of the fields
  getValues() {
    const values = {};
    Object.keys(this.state).forEach((fieldName) => {
      const field = this.state[fieldName];
      if (field) {
        values[field.name] = field.value;
      }
    });
    return values;
  }
  // Helper function fro setToDefault
  getFieldDefaultValue(fieldObj) {
    const field = fieldObj;
    if (field.type === 'group') {
      const allFields = [];
      this.state[field.name].fields.forEach((item) => {
        allFields.push(item.name);
      });
      this[field.name].group.setToDefault(allFields);
      field.value = this[field.name].group.getValues();
    } else {
      field.value = getDefaultValue(field);
    }
    return field;
  }
  /* Set particular field value to default SUPPORTS NESTED FORMS
  Required Form
   For multiple Fields
   [fieldName1, fieldName2, fieldName3 .....]
   For Single Field
  (fieldName1)
  */
  setToDefault(...args) {
    if (args && args.length) {
      if (typeof args[0] === 'object') {
        const newFields = {};
        args[0].forEach((item) => {
          const field = this.state[item];
          if (field) {
            field.value = getDefaultValue(field);
            newFields[field.name] = this.getFieldDefaultValue(field);
          }
        });
        this.setState({ ...newFields });
      } else {
        const field = this.state[args[0]];
        if (field) {
          const newField = {};
          newField[field.name] = this.getFieldDefaultValue(field);
          this.setState({ ...newField });
        }
      }
    }
  }
  // Helper function for setValues
  getFieldValue(fieldObj, value) {
    const field = fieldObj;
    if (field.type === 'group') {
      const subFields = {};
      Object.keys(value).forEach((fieldName) => {
        subFields[fieldName] = value[fieldName];
      });
      this[field.name].group.setValues(subFields);
      field.value = this[field.name].group.getValues();
      // Remaing thing is error Handling Here
    } else {
      field.value = value;
        // also check for errors
      if (this.props.autoValidation === undefined || this.props.autoValidation) {
        Object.assign(field, autoValidate(field));
      }
        // Validate through customValidation if it is present in props
      if (this.props.customValidation
           && typeof this.props.customValidation === 'function') {
        Object.assign(field, this.props.customValidation(field));
      }
    }
    return field;
  }
  setValues(...args) {
    if (args && args.length && args[0]) {
      const newFields = {};
      Object.keys(args[0]).forEach((fieldName) => {
        const field = this.state[fieldName];
        if (field) {
          newFields[field.name] = this.getFieldValue(field, args[0][fieldName]);
        }
      });
      this.setState({ ...newFields });
    }
  }
  // Reset Form values & errors NESTED SUPPORTED
  resetForm() {
    const newFields = {};
    Object.keys(this.state).forEach((fieldName) => {
      const field = this.state[fieldName];
      if (field) {
        field.value = (field.editable !== undefined && !field.editable) ?
          getDefaultValue(field) :
          getResetValue(field);
        field.error = false;
        field.errorMsg = '';
        if (field.type === 'group') {
          this[field.name].group.resetForm();
        }
        newFields[field.name] = field;
      }
    });
    this.setState({ ...newFields });
  }
  generateFields() {
    const theme = Object.assign(baseTheme, this.props.theme);
    const { customComponents } = this.props;
    const renderFields = Object.keys(this.state).map((fieldName, index) => {
      const field = this.state[fieldName];
      if (!field.hidden) {
        if (customComponents) {
          const CustomComponent = customComponents[field.type];
          if (CustomComponent) {
            return (
              <CustomComponent
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                onSummitTextInput={this.onSummitTextInput}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          }
        }
        switch (field.type) {
          case 'text':
          case 'email':
          case 'number':
          case 'url':
          case 'password':
            return (
              <TextInputField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                onSummitTextInput={this.onSummitTextInput}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'picker':
            return (
              <PickerField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'select':
            return (
              <SelectField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'switch':
            return (
              <SwitchField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'date':
            return (
              <DateField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'group':
            return (
              <FormField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
                {...this.props}
              />
            );
          default:
            return null;
        }
      }
    });
    return renderFields;
  }
  render() {
    return (
      <KeyboardAwareScrollView
        keyboardShouldPersistTaps="always"
      >
        <View>
          {this.generateFields() || <View />}
        </View>
      </KeyboardAwareScrollView>

    );
  }
}
<commit_msg>Fixed header issue<commit_after>import React, { Component } from 'react';
import { View, Keyboard } from 'react-native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import TextInputField from '../fields/textInput';
import PickerField from '../fields/picker';
import SwitchField from '../fields/switch';
import DateField from '../fields/date';
import SelectField from '../fields/select';
import FormField from '../fields/form';
import baseTheme from '../theme';
import { autoValidate, getInitState, getDefaultValue, getResetValue } from '../utils/methods';

export default class FormBuilder extends Component {
  static propTypes = {
    fields: React.PropTypes.array,
    theme: React.PropTypes.object,
    customComponents: React.PropTypes.object,
    formData: React.PropTypes.object,
    autoValidation: React.PropTypes.bool,
    customValidation: React.PropTypes.func,
    onValueChange: React.PropTypes.func,
  }
  constructor(props) {
    super(props);
    const initialState = getInitState(props.fields);
    this.state = {
      ...initialState,
      errorStatus: false,
    };
    // Supports Nested
    this.getValues = this.getValues.bind(this);
    // Invoked every time whenever any fields's value changes
    this.onValueChange = this.onValueChange.bind(this);
    // Generate fields
    this.generateFields = this.generateFields.bind(this);
    // forcefully set values for particular fields
    this.setValues = this.setValues.bind(this);
    // forcefully set default values for particular fields
    this.setToDefault = this.setToDefault.bind(this);
    /*
     forcefully set errors for a particular field
    this.setErrors = this.setErrors.bind(this);
     reset errors to default for all fields
    this.resetErrors = this.resetErrors.bind(this);
     reset values to default for all fields
    this.resetValues = this.resetValues.bind(this);
    Currently Not needed but can be added in future
    */
    //  reset form values to default as well as errors
    this.resetForm = this.resetForm.bind(this);
    // Manages textInput Focus
    this.onSummitTextInput = this.onSummitTextInput.bind(this);
  }
  componentDidMount() {
    const { formData } = this.props;
    this.setValues(formData);
  }
  onSummitTextInput(name) {
    const index = Object.keys(this.state).indexOf(name);
    if (index !== -1 && this[Object.keys(this.state)[index + 1]]
    && this[Object.keys(this.state)[index + 1]].textInput) {
      this[Object.keys(this.state)[index + 1]].textInput._root.focus();
    } else {
      Keyboard.dismiss();
    }
  }
  onValueChange(name, value) {
    const valueObj = this.state[name];
    if (valueObj) {
      valueObj.value = value;
      // Not Validate fields only when autoValidation prop is false
      if (this.props.autoValidation === undefined || this.props.autoValidation) {
        Object.assign(valueObj, autoValidate(valueObj));
      }
      // Validate through customValidation if it is present in props
      if (this.props.customValidation
         && typeof this.props.customValidation === 'function') {
        Object.assign(valueObj, this.props.customValidation(valueObj));
      }
      const newField = {};
      newField[valueObj.name] = valueObj;
      // this.props.customValidation(valueObj);
      if (this.props.onValueChange &&
        typeof this.props.onValueChange === 'function') {
        this.setState({ ...newField }, () => this.props.onValueChange());
      } else {
        this.setState({ ...newField });
      }
    }
  }
  // Returns the values of the fields
  getValues() {
    const values = {};
    Object.keys(this.state).forEach((fieldName) => {
      const field = this.state[fieldName];
      if (field) {
        values[field.name] = field.value;
      }
    });
    return values;
  }
  // Helper function fro setToDefault
  getFieldDefaultValue(fieldObj) {
    const field = fieldObj;
    if (field.type === 'group') {
      const allFields = [];
      this.state[field.name].fields.forEach((item) => {
        allFields.push(item.name);
      });
      this[field.name].group.setToDefault(allFields);
      field.value = this[field.name].group.getValues();
    } else {
      field.value = getDefaultValue(field);
    }
    return field;
  }
  /* Set particular field value to default SUPPORTS NESTED FORMS
  Required Form
   For multiple Fields
   [fieldName1, fieldName2, fieldName3 .....]
   For Single Field
  (fieldName1)
  */
  setToDefault(...args) {
    if (args && args.length) {
      if (typeof args[0] === 'object') {
        const newFields = {};
        args[0].forEach((item) => {
          const field = this.state[item];
          if (field) {
            field.value = getDefaultValue(field);
            newFields[field.name] = this.getFieldDefaultValue(field);
          }
        });
        this.setState({ ...newFields });
      } else {
        const field = this.state[args[0]];
        if (field) {
          const newField = {};
          newField[field.name] = this.getFieldDefaultValue(field);
          this.setState({ ...newField });
        }
      }
    }
  }
  // Helper function for setValues
  getFieldValue(fieldObj, value) {
    const field = fieldObj;
    if (field.type === 'group') {
      const subFields = {};
      Object.keys(value).forEach((fieldName) => {
        subFields[fieldName] = value[fieldName];
      });
      this[field.name].group.setValues(subFields);
      field.value = this[field.name].group.getValues();
      // Remaing thing is error Handling Here
    } else {
      field.value = value;
        // also check for errors
      if (this.props.autoValidation === undefined || this.props.autoValidation) {
        Object.assign(field, autoValidate(field));
      }
        // Validate through customValidation if it is present in props
      if (this.props.customValidation
           && typeof this.props.customValidation === 'function') {
        Object.assign(field, this.props.customValidation(field));
      }
    }
    return field;
  }
  // Set Values
  // Params Format:
  // {name1: value1, name2: value2, ......}
  setValues(...args) {
    if (args && args.length && args[0]) {
      const newFields = {};
      Object.keys(args[0]).forEach((fieldName) => {
        const field = this.state[fieldName];
        if (field) {
          newFields[field.name] = this.getFieldValue(field, args[0][fieldName]);
        }
      });
      this.setState({ ...newFields });
    }
  }
  // Reset Form values & errors NESTED SUPPORTED
  resetForm() {
    const newFields = {};
    Object.keys(this.state).forEach((fieldName) => {
      const field = this.state[fieldName];
      if (field) {
        field.value = (field.editable !== undefined && !field.editable) ?
          getDefaultValue(field) :
          getResetValue(field);
        field.error = false;
        field.errorMsg = '';
        if (field.type === 'group') {
          this[field.name].group.resetForm();
        }
        newFields[field.name] = field;
      }
    });
    this.setState({ ...newFields });
  }
  generateFields() {
    const theme = Object.assign(baseTheme, this.props.theme);
    const { customComponents } = this.props;
    const renderFields = Object.keys(this.state).map((fieldName, index) => {
      const field = this.state[fieldName];
      if (!field.hidden) {
        if (customComponents) {
          const CustomComponent = customComponents[field.type];
          if (CustomComponent) {
            return (
              <CustomComponent
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                onSummitTextInput={this.onSummitTextInput}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          }
        }
        switch (field.type) {
          case 'text':
          case 'email':
          case 'number':
          case 'url':
          case 'password':
            return (
              <TextInputField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                onSummitTextInput={this.onSummitTextInput}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'picker':
            return (
              <PickerField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'select':
            return (
              <SelectField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'switch':
            return (
              <SwitchField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'date':
            return (
              <DateField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
              />
            );
          case 'group':
            return (
              <FormField
                key={index}
                theme={theme}
                ref={(c) => { this[field.name] = c; }}
                attributes={this.state[field.name]}
                updateValue={this.onValueChange}
                {...this.props}
              />
            );
          default:
            return null;
        }
      }
    });
    return renderFields;
  }
  render() {
    return (
      <KeyboardAwareScrollView
        keyboardShouldPersistTaps="always"
      >
        <View>
          {this.generateFields() || <View />}
        </View>
      </KeyboardAwareScrollView>

    );
  }
}
<|endoftext|>


<commit_before>exports.sortByName = (a, b) => {
  const aName = (a.properties != null ? a.properties.name : undefined) || a.name || a.id || 'Unknown';
  const bName = (b.properties != null ? b.properties.name : undefined) || b.name || b.id || 'Unknown';
  return aName.localeCompare(bName);
};

exports.sortBySeen = (ain, bin) => {
  const a = ain;
  const b = bin;
  if (!a.seen) {
    return 1;
  }
  if (!b.seen) {
    return -1;
  }
  a.seen = typeof a.seen === 'object' ? a.seen : new Date(a.seen);
  b.seen = typeof b.seen === 'object' ? b.seen : new Date(b.seen);
  if (a.seen > b.seen) {
    return -1;
  }
  if (b.seen > a.seen) {
    return 1;
  }
  return 0;
};

exports.addToList = (list, entity, sort = exports.sortByName) => {
  let found = false;
  list.forEach((existing) => {
    if (existing === entity) {
      // Entity is already in list as-is, skip
      found = true;
      return;
    }
    const existingId = (existing.properties != null ? existing.properties.id : undefined)
      || existing.id || existing.name;
    const entityId = (entity.properties != null ? entity.properties.id : undefined)
      || entity.id || entity.name;
    if (existingId === entityId) {
      // id match, replace
      const exists = existing;
      Object.keys(entity).forEach((key) => {
        exists[key] = entity[key];
      });
      found = true;
    }
  });
  if (found) { return; }
  list.push(entity);
  // Sort the list on desired criteria
  list.sort(sort);
};

exports.removeFromList = (list, entity) => {
  const matched = list.find((existing) => {
    if (existing === entity) {
      return true;
    }
    const existingId = (existing.properties != null ? existing.properties.id : undefined)
      || existing.id;
    const entityId = (entity.properties != null ? entity.properties.id : undefined) || entity.id;
    return (existingId === entityId);
  });
  if (!matched) {
    return;
  }
  list.splice(list.indexOf(matched), 1);
};
<commit_msg>Normalize namespace handling in collections<commit_after>const { basename } = require('path');

exports.sortByName = (a, b) => {
  const aName = exports.unnamespace(exports.getName(a));
  const bName = exports.unnamespace(exports.getName(b));
  return aName.localeCompare(bName);
};

exports.getName = (obj, allowUnknown = true) => {
  const name = (obj.properties != null ? obj.properties.name : undefined) || obj.name || obj.id;
  if (!name && allowUnknown) {
    return 'Unknown';
  }
  return name;
};

exports.unnamespace = (name) => {
  if (name.indexOf('/') === -1) {
    return name;
  }
  return basename(name);
};

exports.namespace = (name, namespace) => {
  if (name.indexOf('/') !== -1) {
    return name;
  }
  return `${namespace}/${name}`;
};

exports.sortBySeen = (ain, bin) => {
  const a = ain;
  const b = bin;
  if (!a.seen) {
    return 1;
  }
  if (!b.seen) {
    return -1;
  }
  a.seen = typeof a.seen === 'object' ? a.seen : new Date(a.seen);
  b.seen = typeof b.seen === 'object' ? b.seen : new Date(b.seen);
  if (a.seen > b.seen) {
    return -1;
  }
  if (b.seen > a.seen) {
    return 1;
  }
  return 0;
};

exports.addToList = (list, entity, sort = exports.sortByName) => {
  let found = false;
  list.forEach((existing) => {
    if (existing === entity) {
      // Entity is already in list as-is, skip
      found = true;
      return;
    }
    const existingId = exports.unnamespace(exports.getName(existing, false));
    const entityId = exports.unnamespace(exports.getName(entity, false));
    if (existingId === entityId) {
      // id match, replace
      const exists = existing;
      Object.keys(entity).forEach((key) => {
        exists[key] = entity[key];
      });
      found = true;
    }
  });
  if (found) { return; }
  list.push(entity);
  // Sort the list on desired criteria
  list.sort(sort);
};

exports.removeFromList = (list, entity) => {
  const matched = list.find((existing) => {
    if (existing === entity) {
      return true;
    }
    const existingId = exports.unnamespace(exports.getName(existing, false));
    const entityId = exports.unnamespace(exports.getName(entity, false));
    return (existingId === entityId);
  });
  if (!matched) {
    return;
  }
  list.splice(list.indexOf(matched), 1);
};
<|endoftext|>


<commit_before>/**
 * calculates schema of a collection by sampling some of the documents
 *
 * @param {Array} documents
 * @param {Object} options currently only supports one option: {flat: true}
 *
 * @returns {Object} the schema document with counts ($c), types ($t),
 *                   an array flag ($a) and probability of occurrence
 *                   given the parent field ($p).
 */
 function schema(documents, options) {
    /**
     * right-aligned string split
     *
     * @param {String} str string to split
     * @param {String} sep character to use for split, or null for any whitespace
     * @param {Number} maxsplit maximum number of splits (from the end of the string)
     *
     * @returns {Array} an array with (if provided, at most maxsplit) elements
     *
     * @example
     * // returns ["foo.bar", "baz"]
     * _rsplit( "foo.bar.baz", ".", 1 )
     */
    function _rsplit(str, sep, maxsplit) {
        var split = str.split(sep || /\s+/);
        return maxsplit ? [ split.slice(0, -maxsplit).join(sep) ].concat(split.slice(-maxsplit)) : split;
    }

    /**
     * flattens an object and results in an object with only top-level properties with dot-notation
     *
     * @param {Object} obj object to flatten
     *
     * @return {Number} maxsplit maximum number of splits (from the end of the string)
     *
     * @example
     * // returns {"a.b" 1, "a.c": false}
     * _flatten( {a: {b: 1, c: false}} )
     */
    var _flatten = function(obj) {
        function recursive(obj) {
            var result = {};

            for (var o in obj) {
                if (!obj.hasOwnProperty(o)) continue;
                if ((typeof obj[o]) == 'object') {
                    var flatObject = recursive(obj[o]);
                    for (var x in flatObject) {
                        if (!flatObject.hasOwnProperty(x)) continue;

                        result[o + '.' + x] = flatObject[x];
                    }
                } else {
                    result[o] = obj[o];
                }
            }
            return result;
        }

        // first flatten completely
        var flatobj = recursive(obj);

        // now fold back in $-prefixed leaves
        var finalobj = {};

        for (var f in flatobj) {
            // only own proerties
            if (!flatobj.hasOwnProperty(f)) continue;

            if (f.indexOf('.') !== -1) {
                split = _rsplit(f, '.', 1);
                if (!(split[0] in finalobj)) {
                    finalobj[split[0]] = {};
                }
                finalobj[split[0]][split[1]] = flatobj[f];
            } else {
                finalobj[f] = flatobj[f];
            }
        }

        return finalobj;
    };

    /**
     * recursively infers a schema of an object, keeping track of counts, types of nested objects
     *
     * @mixin {Object} schema resulting schema, initially {}
     * @param {Object} obj object to infer schema
     *
     */
    function _infer(schema, obj) {
        schema['$c'] = ('$c' in schema) ? schema['$c'] + 1 : 1;

        if (!('$t' in schema)) {
            schema['$t'] = {};
        }

        // special case: ObjectId, it's an object but we don't want to reach into it
        if (typeof ObjectId !== 'undefined' && obj instanceof ObjectId) {
            type = 'ObjectId';
            schema['$t'][type] = (type in schema['$t']) ? schema['$t'][type] + 1 : 1;
            return schema;
        }

        var type = typeof obj;
        schema['$t'][type] = (type in schema['$t']) ? schema['$t'][type] + 1 : 1;

        if (obj && typeof obj == 'object') {

            Object.keys(obj).forEach(function(key) {
                var val = obj[key];
                if (!(key in schema)) {
                    schema[key] = {};
                }

                if (val instanceof Array) {
                    // special case: lists, here collapse
                    val.forEach(function (el) {
                        _infer(schema[key], el);
                    });
                    schema[key]['$a'] = true;
                } else {
                    // objects need to be handled recursively
                    _infer(schema[key], val)
                }
            });

        }
        return schema;
    }

    /**
     * clean up the output of _infer, collapsing single types and calculating
     * probabilities (stored in "$p" field)
     *
     * @param {Object} schema
     * @param {Number} count keep track of count in recursive calls
     *
     * @returns {Object} cleaned up schema
     */
    function _cleanup(schema, count) {
        if (typeof schema !== 'object') {
            return schema;
        }
        Object.keys(schema).forEach( function(key) {
            // remove sole object types
            if (key === '$t') {
                var type_keys = Object.keys(schema[key]);
                if (type_keys.length == 1) {
                    if (type_keys[0] == 'object') {
                        delete schema[key];
                    } else {
                        schema[key] = type_keys[0];
                    }
                }
            }
            if (key === '$c') {
                if (count) {
                    schema['$p'] = schema['$c'] / count;
                }
                count = schema['$c'];
            }
            _cleanup(schema[key], count);
        });

        return schema;
    }

    // define defaults
    var options = options || {};
    options.flat = options.flat || false;

    // infer schema of each document
    var schema = {};
    documents.forEach(function (doc) {
        schema = _infer(schema, doc);
    });

    // clean up schema
    schema = _cleanup(schema);

    // return deep or flat version
    if (options.flat) {
        return _flatten(schema);
    } else {
        return schema;
    }
}

/**
 * extend the DBCollection object to provide the schema method
 *
 * @param {Object} options supports two options: {numSamples: 123, flat: true}
 *
 * @returns {Object} the schema document with counts ($c), types ($t),
 *                   an array flag ($a) and probability of occurrence
 *                   given the parent field ($p).
 */
if (typeof DBCollection !== 'undefined') {
    DBCollection.prototype.schema = function(options) {
        // default options
        var options = options || {};
        options.numSamples = options.numSamples || 100;

        // get documents
        var cursor = this.find({}, null, options.numSamples /* limit */, 0 /* skip*/, 0 /* batchSize */);

        return schema(cursor, options);
    }
}

// export for node.js if module is defined
if (typeof module !== 'undefined') {
    module.exports = schema;
}<commit_msg>$t is no longer flattened if it is an object.<commit_after>/**
 * calculates schema of a collection by sampling some of the documents
 *
 * @param {Array} documents
 * @param {Object} options currently only supports one option: {flat: true}
 *
 * @returns {Object} the schema document with counts ($c), types ($t),
 *                   an array flag ($a) and probability of occurrence
 *                   given the parent field ($p).
 */
 function schema(documents, options) {
    /**
     * right-aligned string split
     *
     * @param {String} str string to split
     * @param {String} sep character to use for split, or null for any whitespace
     * @param {Number} maxsplit maximum number of splits (from the end of the string)
     *
     * @returns {Array} an array with (if provided, at most maxsplit) elements
     *
     * @example
     * // returns ["foo.bar", "baz"]
     * _rsplit( "foo.bar.baz", ".", 1 )
     */
    function _rsplit(str, sep, maxsplit) {
        var split = str.split(sep || /\s+/);
        return maxsplit ? [ split.slice(0, -maxsplit).join(sep) ].concat(split.slice(-maxsplit)) : split;
    }

    /**
     * flattens an object and results in an object with only top-level properties with dot-notation
     *
     * @param {Object} obj object to flatten
     *
     * @return {Number} maxsplit maximum number of splits (from the end of the string)
     *
     * @example
     * // returns {"a.b" 1, "a.c": false}
     * _flatten( {a: {b: 1, c: false}} )
     */
    var _flatten = function(obj) {
        function recursive(obj) {
            var result = {};

            for (var o in obj) {
                if (!obj.hasOwnProperty(o)) continue;
                if ((typeof obj[o]) == 'object' && (!o === '$t')) {
                    var flatObject = recursive(obj[o]);
                    for (var x in flatObject) {
                        if (!flatObject.hasOwnProperty(x)) continue;

                        result[o + '.' + x] = flatObject[x];
                    }
                } else {
                    result[o] = obj[o];
                }
            }
            return result;
        }

        // first flatten completely
        var flatobj = recursive(obj);

        // now fold back in $-prefixed leaves
        var finalobj = {};

        for (var f in flatobj) {
            // only own proerties
            if (!flatobj.hasOwnProperty(f)) continue;

            if (f.indexOf('.') !== -1) {
                split = _rsplit(f, '.', 1);
                if (!(split[0] in finalobj)) {
                    finalobj[split[0]] = {};
                }
                finalobj[split[0]][split[1]] = flatobj[f];
            } else {
                finalobj[f] = flatobj[f];
            }
        }

        return finalobj;
    };

    /**
     * recursively infers a schema of an object, keeping track of counts, types of nested objects
     *
     * @mixin {Object} schema resulting schema, initially {}
     * @param {Object} obj object to infer schema
     *
     */
    function _infer(schema, obj) {
        schema['$c'] = ('$c' in schema) ? schema['$c'] + 1 : 1;

        if (!('$t' in schema)) {
            schema['$t'] = {};
        }

        // special case: ObjectId, it's an object but we don't want to reach into it
        if (typeof ObjectId !== 'undefined' && obj instanceof ObjectId) {
            type = 'ObjectId';
            schema['$t'][type] = (type in schema['$t']) ? schema['$t'][type] + 1 : 1;
            return schema;
        }

        var type = typeof obj;
        schema['$t'][type] = (type in schema['$t']) ? schema['$t'][type] + 1 : 1;

        if (obj && typeof obj == 'object') {

            Object.keys(obj).forEach(function(key) {
                var val = obj[key];
                if (!(key in schema)) {
                    schema[key] = {};
                }

                if (val instanceof Array) {
                    // special case: lists, here collapse
                    val.forEach(function (el) {
                        _infer(schema[key], el);
                    });
                    schema[key]['$a'] = true;
                } else {
                    // objects need to be handled recursively
                    _infer(schema[key], val)
                }
            });

        }
        return schema;
    }

    /**
     * clean up the output of _infer, collapsing single types and calculating
     * probabilities (stored in "$p" field)
     *
     * @param {Object} schema
     * @param {Number} count keep track of count in recursive calls
     *
     * @returns {Object} cleaned up schema
     */
    function _cleanup(schema, count) {
        if (typeof schema !== 'object') {
            return schema;
        }
        Object.keys(schema).forEach( function(key) {
            // remove sole object types
            if (key === '$t') {
                var type_keys = Object.keys(schema[key]);
                if (type_keys.length == 1) {
                    if (type_keys[0] == 'object') {
                        delete schema[key];
                    } else {
                        schema[key] = type_keys[0];
                    }
                }
            }
            if (key === '$c') {
                if (count) {
                    schema['$p'] = schema['$c'] / count;
                }
                count = schema['$c'];
            }
            _cleanup(schema[key], count);
        });

        return schema;
    }

    // define defaults
    var options = options || {};
    options.flat = options.flat || false;

    // infer schema of each document
    var schema = {};
    documents.forEach(function (doc) {
        schema = _infer(schema, doc);
    });

    // clean up schema
    schema = _cleanup(schema);

    // return deep or flat version
    if (options.flat) {
        return _flatten(schema);
    } else {
        return schema;
    }
}

/**
 * extend the DBCollection object to provide the schema method
 *
 * @param {Object} options supports two options: {numSamples: 123, flat: true}
 *
 * @returns {Object} the schema document with counts ($c), types ($t),
 *                   an array flag ($a) and probability of occurrence
 *                   given the parent field ($p).
 */
if (typeof DBCollection !== 'undefined') {
    DBCollection.prototype.schema = function(options) {
        // default options
        var options = options || {};
        options.numSamples = options.numSamples || 100;

        // get documents
        var cursor = this.find({}, null, options.numSamples /* limit */, 0 /* skip*/, 0 /* batchSize */);

        return schema(cursor, options);
    }
}

// export for node.js if module is defined
if (typeof module !== 'undefined') {
    module.exports = schema;
}<|endoftext|>


<commit_before>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved.
 */

var Color = this.Color = Base.extend(new function() {

	var colorCache = {},
		colorContext;

	function nameToRGBColor(name) {
		var color = colorCache[name];
		if (color)
			return color; // TODO: return a clone of the color
		// Use a canvas to draw to with the given name and then retrieve rgb
		// values from. Build a cache for all the used colors.
		if (!colorContext) {
			var canvas = CanvasProvider.getCanvas(Size.create(1, 1));
			colorContext = canvas.getContext('2d');
			colorContext.globalCompositeOperation = 'copy';
		}
		// Set the current fillStyle to transparent, so that it will be
		// transparent instead of the previously set color in case the new color
		// can not be interpreted.
		colorContext.fillStyle = 'rgba(0, 0, 0, 0)';
		// Set the fillStyle of the context to the passed name and fill the
		// canvas with it, then retrieve the data for the drawn pixel:
		colorContext.fillStyle = name;
		colorContext.fillRect(0, 0, 1, 1);
		var data = colorContext.getImageData(0, 0, 1, 1).data,
			rgb = [data[0] / 255, data[1] / 255, data[2] / 255];
		return colorCache[name] = RGBColor.read(rgb); // TODO: return a clone
	}

	function hexToRGBColor(string) {
		var hex = string.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		if (hex.length >= 4) {
			var rgb = new Array(3);
			for (var i = 0; i < 3; i++) {
				var channel = hex[i + 1];
				rgb[i] = parseInt(channel.length == 1
						? channel + channel : channel, 16) / 255;
			}
			return RGBColor.read(rgb);
		}
	};

	return {
		beans: true,
		_readNull: true,

		initialize: function(arg) {
			var isArray = Array.isArray(arg);
			if (typeof arg === 'object' && !isArray) {
				if (!this._colorType) {
					// Called on the abstract Color class. Guess color type
					// from arg
					return arg.red !== undefined
						? new RGBColor(arg.red, arg.green, arg.blue, arg.alpha)
						: arg.gray !== undefined
						? new GrayColor(arg.gray, arg.alpha)
						: arg.hue !== undefined
						? new HSBColor(arg.hue, arg.saturation, arg.brightness,
								arg.alpha)
						: new RGBColor(); // Fallback

				} else {
					// Called on a subclass instance. Return the converted
					// color.
					var color = Color.read(arguments, 0, 1);
					return this._colorType
							? color.convert(this._colorType)
							: color;
				}
			} else if (typeof arg === 'string') {
				var rgbColor = arg.match(/^#[0-9a-f]{3,6}$/i)
						? hexToRGBColor(arg)
						: nameToRGBColor(arg);
				return this._colorType
						? rgbColor.convert(this._colorType)
						: rgbColor;
			} else {
				var components = isArray ? arg
						: arguments;//Array.prototype.slice.call(arguments);
				if (!this._colorType) {
					// Called on the abstract Color class. Guess color type
					// from arg
					//if (components.length >= 4)
					//	return new CMYKColor(components);
					if (components.length >= 3)
						return new RGBColor(components);
					return new GrayColor(components);
				} else {
					// Called on a subclass instance. Just copy over
					// components.
					Base.each(this._components,
						function(name, i) {
							var value = components[i];
							// TODO: Should we call the setter?
							// this['set' + name.capitalize()]
							this[name] = value !== undefined
									? value
									// TODO: Is this correct?
									// Shouldn't alpha be set to -1?
									: name === 'alpha' ? 1 : null;
						}, this);
				}
			}
		},

		getType: function() {
			return this._colorType;
		},

		getComponents: function() {
			var l = this._components.length;
			var components = new Array(l);
			for (var i = 0; i < l; i++) {
				components[i] = this['_' + this._components[i]];
			}
			return components;
		},

		/**
		 * A value between 0 and 1 that specifies the color's alpha value.
		 * All colors of the different subclasses support alpha values.
		 */
		getAlpha: function() {
			return this._alpha != null ? this._alpha : 1;
		},

		setAlpha: function(alpha) {
			this._alpha = Math.min(Math.max(alpha, 0), 1);
			this._cssString = null;
		},

		/**
		 * Checks if the color has an alpha value.
		 *
		 * @return {@true if the color has an alpha value}
		 */
		hasAlpha: function() {
			return this._alpha != null;
		},

		/**
		 * Checks if the component color values of the color are the
		 * same as those of the supplied one.
		 *
		 * @param obj the GrayColor to compare with
		 * @return {@true if the GrayColor is the same}
		 */
		equals: function(color) {
			if (color && color._colorType === this._colorType) {
				for (var i = 0, l = this._components.length; i < l; i++) {
					var component = '_' + this._components[i];
					if (this[component] !== color[component])
						return false;
				}
				return true;
			}
			return false;
		},

		toString: function() {
			var parts = [],
				format = Base.formatNumber;
			for (var i = 0, l = this._components.length; i < l; i++) {
				var component = this._components[i],
					value = this['_' + component];
				if (component === 'alpha' && value == null)
					value = 1;
				parts.push(component + ': ' + format(value));
			}
			return '{ ' + parts.join(', ') + ' }';
		},

		toCssString: function() {
			if (!this._cssString) {
				var color = this._colorType === 'rgb'
						? this
						: this.convert('rgb');
				var alpha = color.getAlpha();
				var components = [
					Math.round(color.getRed() * 255),
					Math.round(color.getGreen() * 255),
					Math.round(color.getBlue() * 255),
					alpha != null ? this.alpha : 1
				];
				this._cssString = 'rgba(' + components.join(', ') + ')';
			}
			return this._cssString;
		},

		getCanvasStyle: function() {
			return this.toCssString();
		}
	};
}, new function() {
	var converters = {
		'rgb-hsb': function(color) {
			var r = color._red,
				g = color._green,
				b = color._blue,
				alpha = color._alpha,
				max = Math.max(r, g, b),
				min = Math.min(r, g, b),
				delta = max - min,
				hue,
				saturation = (max != 0) ? delta / max : 0,
				brightness = max;
			if (saturation == 0) {
				hue = 0;
			} else {
				var rr = (max - r) / delta,
					gr = (max - g) / delta,
					br = (max - b) / delta;
				hue = r == max
					? br - gr
					: g == max
						? 2 + rr - br
						: 4 + gr - rr;
				hue /= 6;
				if (hue < 0)
					hue++;
			}
			return new HSBColor(hue * 360, saturation, brightness, alpha);
		},

		'hsb-rgb': function(color) {
			var h = color._hue,
				s = color._saturation,
				b = color._brightness,
				a = color._alpha,
				f = h % 60,
				p = (b * (1 - s)) / 1,
				q = (b * (60 - s * f)) / 60,
				t = (b * (60 - s * (60 - f))) / 60;
			switch (Math.floor(h / 60)) {
				case 0: return new RGBColor(b, t, p, a);
				case 1: return new RGBColor(q, b, p, a);
				case 2: return new RGBColor(p, b, t, a);
				case 3: return new RGBColor(p, q, b, a);
				case 4: return new RGBColor(t, p, b, a);
				case 5: return new RGBColor(b, p, q, a);
			}
		},

		'rgb-gray': function(color) {
			// Using the standard NTSC conversion formula that is used for
			// calculating the effective luminance of an RGB color:
			// http://www.mathworks.com/support/solutions/en/data/1-1ASCU/index.html?solution=1-1ASCU
			return new GrayColor(1 -
					(color._red * 0.2989
					+ color._green * 0.587
					+ color._blue * 0.114),
					color._alpha
				);
		},

		'gray-rgb': function(color) {
			var component = 1 - color.getGray();
			return new RGBColor(component, component, component, color._alpha);
		},

		'hsb-gray': function(color) {
			var rgbColor = converters['hsb-rgb'](color);
			return converters['rgb-gray'](rgbColor);
		},

		'gray-hsb': function(color) {
			return new HSBColor(0, 0, 1 - color._gray, color._alpha);
		}
	};

	return {
		convert: function(type) {
			return this._colorType == type
				? this
				: converters[this._colorType + '-' + type](this);
		}
	};
}, new function() {
	return Base.each({
		rgb: ['red', 'green', 'blue'],
		hsb: ['hue', 'saturation', 'brightness'],
		gray: ['gray']
	}, function(components, colorType) {
		Base.each(components, function(component) {
			this['get' + Base.capitalize(component)] = function() {
				return this.convert(colorType)[component];
			};
			this['set' + Base.capitalize(component)] = function(value) {
				var color = this.convert(colorType);
				color[component] = value;
				color = color.convert(this._colorType);
				for (var i = 0, l = this._components.length; i < l; i++) {
					this[this._components[i]] = color[this._components[i]];
				}
			};
		}, this);
	}, { beans: true });
});
<commit_msg>Fix mistake in earlier commit.<commit_after>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * All rights reserved.
 */

var Color = this.Color = Base.extend(new function() {

	var colorCache = {},
		colorContext;

	function nameToRGBColor(name) {
		var color = colorCache[name];
		if (color)
			return color; // TODO: return a clone of the color
		// Use a canvas to draw to with the given name and then retrieve rgb
		// values from. Build a cache for all the used colors.
		if (!colorContext) {
			var canvas = CanvasProvider.getCanvas(Size.create(1, 1));
			colorContext = canvas.getContext('2d');
			colorContext.globalCompositeOperation = 'copy';
		}
		// Set the current fillStyle to transparent, so that it will be
		// transparent instead of the previously set color in case the new color
		// can not be interpreted.
		colorContext.fillStyle = 'rgba(0, 0, 0, 0)';
		// Set the fillStyle of the context to the passed name and fill the
		// canvas with it, then retrieve the data for the drawn pixel:
		colorContext.fillStyle = name;
		colorContext.fillRect(0, 0, 1, 1);
		var data = colorContext.getImageData(0, 0, 1, 1).data,
			rgb = [data[0] / 255, data[1] / 255, data[2] / 255];
		return colorCache[name] = RGBColor.read(rgb); // TODO: return a clone
	}

	function hexToRGBColor(string) {
		var hex = string.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
		if (hex.length >= 4) {
			var rgb = new Array(3);
			for (var i = 0; i < 3; i++) {
				var channel = hex[i + 1];
				rgb[i] = parseInt(channel.length == 1
						? channel + channel : channel, 16) / 255;
			}
			return RGBColor.read(rgb);
		}
	};

	return {
		beans: true,
		_readNull: true,

		initialize: function(arg) {
			var isArray = Array.isArray(arg);
			if (typeof arg === 'object' && !isArray) {
				if (!this._colorType) {
					// Called on the abstract Color class. Guess color type
					// from arg
					return arg.red !== undefined
						? new RGBColor(arg.red, arg.green, arg.blue, arg.alpha)
						: arg.gray !== undefined
						? new GrayColor(arg.gray, arg.alpha)
						: arg.hue !== undefined
						? new HSBColor(arg.hue, arg.saturation, arg.brightness,
								arg.alpha)
						: new RGBColor(); // Fallback

				} else {
					// Called on a subclass instance. Return the converted
					// color.
					var color = Color.read(arguments, 0, 1);
					return this._colorType
							? color.convert(this._colorType)
							: color;
				}
			} else if (typeof arg === 'string') {
				var rgbColor = arg.match(/^#[0-9a-f]{3,6}$/i)
						? hexToRGBColor(arg)
						: nameToRGBColor(arg);
				return this._colorType
						? rgbColor.convert(this._colorType)
						: rgbColor;
			} else {
				var components = isArray ? arg
						: Array.prototype.slice.call(arguments);
				if (!this._colorType) {
					// Called on the abstract Color class. Guess color type
					// from arg
					//if (components.length >= 4)
					//	return new CMYKColor(components);
					if (components.length >= 3)
						return new RGBColor(components);
					return new GrayColor(components);
				} else {
					// Called on a subclass instance. Just copy over
					// components.
					Base.each(this._components,
						function(name, i) {
							var value = components[i];
							// TODO: Should we call the setter?
							// this['set' + name.capitalize()]
							this[name] = value !== undefined
									? value
									// TODO: Is this correct?
									// Shouldn't alpha be set to -1?
									: name === 'alpha' ? 1 : null;
						}, this);
				}
			}
		},

		getType: function() {
			return this._colorType;
		},

		getComponents: function() {
			var l = this._components.length;
			var components = new Array(l);
			for (var i = 0; i < l; i++) {
				components[i] = this['_' + this._components[i]];
			}
			return components;
		},

		/**
		 * A value between 0 and 1 that specifies the color's alpha value.
		 * All colors of the different subclasses support alpha values.
		 */
		getAlpha: function() {
			return this._alpha != null ? this._alpha : 1;
		},

		setAlpha: function(alpha) {
			this._alpha = Math.min(Math.max(alpha, 0), 1);
			this._cssString = null;
		},

		/**
		 * Checks if the color has an alpha value.
		 *
		 * @return {@true if the color has an alpha value}
		 */
		hasAlpha: function() {
			return this._alpha != null;
		},

		/**
		 * Checks if the component color values of the color are the
		 * same as those of the supplied one.
		 *
		 * @param obj the GrayColor to compare with
		 * @return {@true if the GrayColor is the same}
		 */
		equals: function(color) {
			if (color && color._colorType === this._colorType) {
				for (var i = 0, l = this._components.length; i < l; i++) {
					var component = '_' + this._components[i];
					if (this[component] !== color[component])
						return false;
				}
				return true;
			}
			return false;
		},

		toString: function() {
			var parts = [],
				format = Base.formatNumber;
			for (var i = 0, l = this._components.length; i < l; i++) {
				var component = this._components[i],
					value = this['_' + component];
				if (component === 'alpha' && value == null)
					value = 1;
				parts.push(component + ': ' + format(value));
			}
			return '{ ' + parts.join(', ') + ' }';
		},

		toCssString: function() {
			if (!this._cssString) {
				var color = this._colorType === 'rgb'
						? this
						: this.convert('rgb');
				var alpha = color.getAlpha();
				var components = [
					Math.round(color.getRed() * 255),
					Math.round(color.getGreen() * 255),
					Math.round(color.getBlue() * 255),
					alpha != null ? this.alpha : 1
				];
				this._cssString = 'rgba(' + components.join(', ') + ')';
			}
			return this._cssString;
		},

		getCanvasStyle: function() {
			return this.toCssString();
		}
	};
}, new function() {
	var converters = {
		'rgb-hsb': function(color) {
			var r = color._red,
				g = color._green,
				b = color._blue,
				alpha = color._alpha,
				max = Math.max(r, g, b),
				min = Math.min(r, g, b),
				delta = max - min,
				hue,
				saturation = (max != 0) ? delta / max : 0,
				brightness = max;
			if (saturation == 0) {
				hue = 0;
			} else {
				var rr = (max - r) / delta,
					gr = (max - g) / delta,
					br = (max - b) / delta;
				hue = r == max
					? br - gr
					: g == max
						? 2 + rr - br
						: 4 + gr - rr;
				hue /= 6;
				if (hue < 0)
					hue++;
			}
			return new HSBColor(hue * 360, saturation, brightness, alpha);
		},

		'hsb-rgb': function(color) {
			var h = color._hue,
				s = color._saturation,
				b = color._brightness,
				a = color._alpha,
				f = h % 60,
				p = (b * (1 - s)) / 1,
				q = (b * (60 - s * f)) / 60,
				t = (b * (60 - s * (60 - f))) / 60;
			switch (Math.floor(h / 60)) {
				case 0: return new RGBColor(b, t, p, a);
				case 1: return new RGBColor(q, b, p, a);
				case 2: return new RGBColor(p, b, t, a);
				case 3: return new RGBColor(p, q, b, a);
				case 4: return new RGBColor(t, p, b, a);
				case 5: return new RGBColor(b, p, q, a);
			}
		},

		'rgb-gray': function(color) {
			// Using the standard NTSC conversion formula that is used for
			// calculating the effective luminance of an RGB color:
			// http://www.mathworks.com/support/solutions/en/data/1-1ASCU/index.html?solution=1-1ASCU
			return new GrayColor(1 -
					(color._red * 0.2989
					+ color._green * 0.587
					+ color._blue * 0.114),
					color._alpha
				);
		},

		'gray-rgb': function(color) {
			var component = 1 - color.getGray();
			return new RGBColor(component, component, component, color._alpha);
		},

		'hsb-gray': function(color) {
			var rgbColor = converters['hsb-rgb'](color);
			return converters['rgb-gray'](rgbColor);
		},

		'gray-hsb': function(color) {
			return new HSBColor(0, 0, 1 - color._gray, color._alpha);
		}
	};

	return {
		convert: function(type) {
			return this._colorType == type
				? this
				: converters[this._colorType + '-' + type](this);
		}
	};
}, new function() {
	return Base.each({
		rgb: ['red', 'green', 'blue'],
		hsb: ['hue', 'saturation', 'brightness'],
		gray: ['gray']
	}, function(components, colorType) {
		Base.each(components, function(component) {
			this['get' + Base.capitalize(component)] = function() {
				return this.convert(colorType)[component];
			};
			this['set' + Base.capitalize(component)] = function(value) {
				var color = this.convert(colorType);
				color[component] = value;
				color = color.convert(this._colorType);
				for (var i = 0, l = this._components.length; i < l; i++) {
					this[this._components[i]] = color[this._components[i]];
				}
			};
		}, this);
	}, { beans: true });
});
<|endoftext|>


<commit_before>const util = require('util');

const Type   = require('./type').Type;
const Random = require('./random').Random;
const _ = require('./helpers');

//TODO: Eventually, have API for both NPCs and Players.

/**
* The purpose of this class is to standardize
* the realtime combat API between players & NPCs.
*/

/**
* Generic func to apply all mods to a stat,
* starting with the base stat.
*/
const applyMod  = (stat, modifier) => modifier(stat)
const applyMods = (base, modsObj)  => _
  .reduceValues(modsObj, applyMod, base);

function CombatHelper(entity) {
  this._entity = entity;

  /*
   * Example modifier: {
      name: 'berserk',
      effect: damage => damage * 2
    }
   * Speed mods will affect time in between attacks
   * in milliseconds. So, doubling it will half attack speed.
   */
  this.speedMods   = {};
  this.damageMods  = {};
  this.toHitMods   = {};
  this.defenseMods = {};
  this.dodgeMods   = {};

  this.addMod = type =>
    modifier => this[type][modifier.name] = modifier.effect;

  this.addSpeedMod   = this.addMod('speedMods');
  this.addDamageMod  = this.addMod('damageMods');
  this.addToHitMod   = this.addMod('toHitMods');
  this.addDefenseMod = this.addMod('defenseMods');
  this.addDodgeMod   = this.addMod('dodgeMods');

  this.deleteMod = type =>
    name => delete this[type][name];

  this.removeSpeedMod   = this.deleteMod('speedMods');
  this.removeDamageMod  = this.deleteMod('damageMods');
  this.removeToHitMod   = this.deleteMod('toHitMods');
  this.removeDefenseMod = this.deleteMod('defenseMods');
  this.removeDodgeMod   = this.deleteMod('dodgeMods');

  this.deleteAllMods = name => {
    if (!name) { return false; } //TODO: Eventually, remove all mods?
    this.removeSpeedMod(name);
    this.removeDamageMod(name);
    this.removeToHitMod(name);
  };

  /**
   * Get hydrated primary or offhand weapon of player/npc.
   */
  this.getWeapon  = location => this._entity
    .getEquipped(location || 'wield', true);

  this.getOffhand = () => this.getWeapon('offhand');

  /**
   * Get just the name of the attack.
   */
  this.getAttackName = location => this
    .getWeapon(location)
    .getShortDesc('en');

  this.getPrimaryAttackName   = () => this.getAttackName('wield');
  this.getSecondaryAttackName = () => this.getAttackName('offhand');

  /**
  * Gets damage range from weapon obj
  * @param   Weapon obj
  * @param   Base possible damage for hand-to-hand
  * @return  Array of [min, max] damage range
  */
  const getWeaponDamage = (weapon, base) => weapon ?
    (weapon.getAttribute('damage') ?
      weapon.getAttribute('damage')
        .split('-')
        .map(dmg => parseInt(dmg, 10)) :
        base) :
      base;

  /**
   * Get the damage a player can do
   * @return int
   */
  this.getDamage = location => {
    location = location || 'wield';

    const self   = this._entity;
    const weapon = self.getEquipped(location, true);
    const base   = [ 1, self.getAttribute('stamina') + 5 ];

    const damageRange = getWeaponDamage(weapon, base);

    const damageRoll = Random.inRange(...damageRange);

    const min = damageRange[0];
    const modifiedDamageRoll = applyMods(damageRoll, this.damageMods);

    const damageWithinBounds = _.setBounds(min, Infinity);
    const damageDealt = damageWithinBounds(modifiedDamageRoll);

    util.log('Deals damage: ', damageDealt);

    return damageDealt;
  };

  const getWeaponSpeed = (weapon, base, factor) => (weapon ?
    weapon.getAttribute('speed') : base) * factor;

  /**
   * Get attack speed of a player
   * @return float milliseconds between attacks
   */
  this.getAttackSpeed = Type.isNpc(this._entity) ?
    this._entity.getAttackSpeed :
    secondAttack => {
      const weapon  = secondAttack ? this.getWeapon() : this.getOffhand();

      const minimum = secondAttack ? 750 : 500;
      const maximum = 10 * 1000;

      const speedWithinBounds = _.setBounds(minimum, maximum);

      const unarmedSpeed    = this._entity.getAttribute('quickness');
      const weaponSpeed     = getWeaponSpeed(weapon, unarmedSpeed, 500);
      const attributesSpeed = unarmedSpeed * 500
        + this._entity.getAttribute('cleverness') * 250;

      const baseSpeed = maximum - weaponSpeed - attributesSpeed;

      util.log("Their base speed is ", baseSpeed);

      const speed = applyMods(baseSpeed, this.speedMods);

      util.log("Their modified speed is ", speed);

      return speedWithinBounds(speed);
    };

  this.getDodgeChance = () => {
    const dodgeSkill = this._entity.getSkills('dodge') + Random.roll();
    const dodgeBonus = this._entity.getAttribute('quickness')
      + Math.round(this._entity.getAttribute('cleverness') / 2);
    const dodgeChance = applyMods(dodgeSkill + dodgeBonus, this.dodgeMods);
    const dodgeWithinBounds = _.setBounds(5, 90);
    util.log('Dodge chance is ', dodgeChance);
    return dodgeWithinBounds(dodgeChance);
  }

  return this;
}

this.getDesc = () => Type.isPlayer(this._entity) ?
  this._entity.getName() : this._entity.getShortDesc('en');

this.getToHitChance = () => {
  //TODO: Weapon skills related to weapon type?
  //TODO: General combat skills?
  // Replace 1 with skill get.
  const toHitSkill = this._entity.getAttribute('level') + Random.roll(); //For now, 1-20.
  const toHitBonus = this._entity.getAttribute('cleverness')
    + Math.round(this._entity.getAttribute('quickness') / 2);
  const toHitChance = applyMods(toHitSkill + toHitBonus, this.toHitMods);
  const toHitWithinBounds = _.setBounds(5, 90);
  util.log('To hit chance is ', toHitChance);
  return toHitWithinBounds(toHitChance);
}

this.getDefense = () => {
  //TODO: Replace with defense func from player.
  return this._entity.getAttribute('level') * 2;
}

this.getTarget = () => Type.isPlayer(this._entity) ?
  this._entity.getPreference('target') :

function getHelper(entity) {
  return new CombatHelper(entity);
}

exports.CombatUtil   = { getHelper };
exports.CombatHelper = CombatHelper;
<commit_msg>Finish standardizing target getter.<commit_after>const util = require('util');

const Type   = require('./type').Type;
const Random = require('./random').Random;
const _ = require('./helpers');

//TODO: Eventually, have API for both NPCs and Players.

/**
* The purpose of this class is to standardize
* the realtime combat API between players & NPCs.
*/

/**
* Generic func to apply all mods to a stat,
* starting with the base stat.
*/
const applyMod  = (stat, modifier) => modifier(stat)
const applyMods = (base, modsObj)  => _
  .reduceValues(modsObj, applyMod, base);

function CombatHelper(entity) {
  this._entity = entity;

  /*
   * Example modifier: {
      name: 'berserk',
      effect: damage => damage * 2
    }
   * Speed mods will affect time in between attacks
   * in milliseconds. So, doubling it will half attack speed.
   */
  this.speedMods   = {};
  this.damageMods  = {};
  this.toHitMods   = {};
  this.defenseMods = {};
  this.dodgeMods   = {};

  this.addMod = type =>
    modifier => this[type][modifier.name] = modifier.effect;

  this.addSpeedMod   = this.addMod('speedMods');
  this.addDamageMod  = this.addMod('damageMods');
  this.addToHitMod   = this.addMod('toHitMods');
  this.addDefenseMod = this.addMod('defenseMods');
  this.addDodgeMod   = this.addMod('dodgeMods');

  this.deleteMod = type =>
    name => delete this[type][name];

  this.removeSpeedMod   = this.deleteMod('speedMods');
  this.removeDamageMod  = this.deleteMod('damageMods');
  this.removeToHitMod   = this.deleteMod('toHitMods');
  this.removeDefenseMod = this.deleteMod('defenseMods');
  this.removeDodgeMod   = this.deleteMod('dodgeMods');

  this.deleteAllMods = name => {
    if (!name) { return false; } //TODO: Eventually, remove all mods?
    this.removeSpeedMod(name);
    this.removeDamageMod(name);
    this.removeToHitMod(name);
  };

  /**
   * Get hydrated primary or offhand weapon of player/npc.
   */
  this.getWeapon  = location => this._entity
    .getEquipped(location || 'wield', true);

  this.getOffhand = () => this.getWeapon('offhand');

  /**
   * Get just the name of the attack.
   */
  this.getAttackName = location => this
    .getWeapon(location)
    .getShortDesc('en');

  this.getPrimaryAttackName   = () => this.getAttackName('wield');
  this.getSecondaryAttackName = () => this.getAttackName('offhand');

  /**
  * Gets damage range from weapon obj
  * @param   Weapon obj
  * @param   Base possible damage for hand-to-hand
  * @return  Array of [min, max] damage range
  */
  const getWeaponDamage = (weapon, base) => weapon ?
    (weapon.getAttribute('damage') ?
      weapon.getAttribute('damage')
        .split('-')
        .map(dmg => parseInt(dmg, 10)) :
        base) :
      base;

  /**
   * Get the damage a player can do
   * @return int
   */
  this.getDamage = location => {
    location = location || 'wield';

    const self   = this._entity;
    const weapon = self.getEquipped(location, true);
    const base   = [ 1, self.getAttribute('stamina') + 5 ];

    const damageRange = getWeaponDamage(weapon, base);

    const damageRoll = Random.inRange(...damageRange);

    const min = damageRange[0];
    const modifiedDamageRoll = applyMods(damageRoll, this.damageMods);

    const damageWithinBounds = _.setBounds(min, Infinity);
    const damageDealt = damageWithinBounds(modifiedDamageRoll);

    util.log('Deals damage: ', damageDealt);

    return damageDealt;
  };

  const getWeaponSpeed = (weapon, base, factor) => (weapon ?
    weapon.getAttribute('speed') : base) * factor;

  /**
   * Get attack speed of a player
   * @return float milliseconds between attacks
   */
  this.getAttackSpeed = Type.isNpc(this._entity) ?
    this._entity.getAttackSpeed :
    secondAttack => {
      const weapon  = secondAttack ? this.getWeapon() : this.getOffhand();

      const minimum = secondAttack ? 750 : 500;
      const maximum = 10 * 1000;

      const speedWithinBounds = _.setBounds(minimum, maximum);

      const unarmedSpeed    = this._entity.getAttribute('quickness');
      const weaponSpeed     = getWeaponSpeed(weapon, unarmedSpeed, 500);
      const attributesSpeed = unarmedSpeed * 500
        + this._entity.getAttribute('cleverness') * 250;

      const baseSpeed = maximum - weaponSpeed - attributesSpeed;

      util.log("Their base speed is ", baseSpeed);

      const speed = applyMods(baseSpeed, this.speedMods);

      util.log("Their modified speed is ", speed);

      return speedWithinBounds(speed);
    };

  this.getDodgeChance = () => {
    const dodgeSkill = this._entity.getSkills('dodge') + Random.roll();
    const dodgeBonus = this._entity.getAttribute('quickness')
      + Math.round(this._entity.getAttribute('cleverness') / 2);
    const dodgeChance = applyMods(dodgeSkill + dodgeBonus, this.dodgeMods);
    const dodgeWithinBounds = _.setBounds(5, 90);
    util.log('Dodge chance is ', dodgeChance);
    return dodgeWithinBounds(dodgeChance);
  }

  return this;
}

this.getDesc = () => Type.isPlayer(this._entity) ?
  this._entity.getName() : this._entity.getShortDesc('en');

this.getToHitChance = () => {
  //TODO: Weapon skills related to weapon type?
  //TODO: General combat skills?
  // Replace 1 with skill get.
  const toHitSkill = this._entity.getAttribute('level') + Random.roll(); //For now, 1-20.
  const toHitBonus = this._entity.getAttribute('cleverness')
    + Math.round(this._entity.getAttribute('quickness') / 2);
  const toHitChance = applyMods(toHitSkill + toHitBonus, this.toHitMods);
  const toHitWithinBounds = _.setBounds(5, 90);
  util.log('To hit chance is ', toHitChance);
  return toHitWithinBounds(toHitChance);
}

this.getDefense = () => {
  //TODO: Replace with defense func from player.
  return this._entity.getAttribute('level') * 2;
}

this.getTarget = () => Type.isPlayer(this._entity) ?
  this._entity.getPreference('target') :
  this._entity.getAttribute('target');

function getHelper(entity) {
  return new CombatHelper(entity);
}

exports.CombatUtil   = { getHelper };
exports.CombatHelper = CombatHelper;
<|endoftext|>


<commit_before>/*************************************************
 * Copyright (c) 2016 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/
import ReconnectingWebSocket from 'reconnectingwebsocket';
export default
['$rootScope', '$location', '$log','$state', '$q', 'i18n',
    function ($rootScope, $location, $log, $state, $q, i18n) {
        var needsResubscribing = false,
        socketPromise = $q.defer();
        return {
            init: function() {
                var self = this,
                    host = window.location.host,
                    protocol,
                    url;

                if($location.protocol() === 'http'){
                    protocol = 'ws';
                }
                if($location.protocol() === 'https'){
                    protocol = 'wss';
                }
                url = `${protocol}://${host}/websocket/`;

                if (!$rootScope.sessionTimer || ($rootScope.sessionTimer && !$rootScope.sessionTimer.isExpired())) {

                    $log.debug('Socket connecting to: ' + url);

                    self.socket = new ReconnectingWebSocket(url, null, {
                        timeoutInterval: 3000,
                        maxReconnectAttempts: 10                    });

                    self.socket.onopen = function () {
                        $log.debug("Websocket connection opened.");
                        socketPromise.resolve();
                        console.log('promise resolved, and readyState: '+ self.readyState);
                        self.checkStatus();
                        if(needsResubscribing){
                            self.subscribe(self.getLast());
                            needsResubscribing = false;
                        }

                    };

                    self.socket.onerror = function (error) {
                        self.checkStatus();
                        $log.debug('Websocket Error Logged: ' + error); //log errors
                    };

                    self.socket.onconnecting = function () {
                        self.checkStatus();
                        $log.debug('Websocket reconnecting');
                        needsResubscribing = true;
                    };

                    self.socket.onclose = function () {
                        self.checkStatus();
                        $log.debug(`Websocket disconnected`);
                    };

                    self.socket.onmessage = this.onMessage;

                    return self.socket;
                }
                else {
                    // encountered expired token, redirect to login page
                    $rootScope.sessionTimer.expireSession('idle');
                    $location.url('/login');
                }
            },
            onMessage: function(e){
                // Function called when messages are received on by the UI from
                // the API over the websocket. This will route each message to
                // the appropriate controller for the current $state.
                $log.debug('Received From Server: ' + e.data);

                var data = JSON.parse(e.data), str = "";
                if(data.group_name==="jobs" && !('status' in data)){
                    // we know that this must have been a
                    // summary complete message b/c status is missing.
                    // A an object w/ group_name === "jobs" AND a 'status' key
                    // means it was for the event: status_changed.
                    $log.debug('Job summary_complete ' + data.unified_job_id);
                    $rootScope.$broadcast('ws-jobs-summary', data);
                    return;
                }
                else if(data.group_name==="job_events"){
                    // The naming scheme is "ws" then a
                    // dash (-) and the group_name, then the job ID
                    // ex: 'ws-jobs-<jobId>'
                    str = `ws-${data.group_name}-${data.job}`;
                }
                else if(data.group_name==="ad_hoc_command_events"){
                    // The naming scheme is "ws" then a
                    // dash (-) and the group_name, then the job ID
                    // ex: 'ws-jobs-<jobId>'
                    str = `ws-${data.group_name}-${data.ad_hoc_command}`;
                }
                else if(data.group_name==="control"){
                    // As of v. 3.1.0, there is only 1 "control"
                    // message, which is for expiring the session if the
                    // session limit is breached.
                    $log.debug(data.reason);
                    $rootScope.sessionTimer.expireSession('session_limit');
                    $state.go('signOut');
                }
                else {
                    // The naming scheme is "ws" then a
                    // dash (-) and the group_name.
                    // ex: 'ws-jobs'
                    str = `ws-${data.group_name}`;
                }
                $rootScope.$broadcast(str, data);
            },
            disconnect: function(){
                if(this.socket){
                    this.socket.close();
                    delete this.socket;
                    console.log("Socket deleted: "+this.socket);
                }
            },
            subscribe: function(state){
                // Subscribe is used to tell the API that the UI wants to
                // listen for specific messages. A subscription object could
                // look like {"groups":{"jobs": ["status_changed", "summary"]}.
                // This is used by all socket-enabled $states
                this.emit(JSON.stringify(state.data.socket));
                this.setLast(state);
            },
            unsubscribe: function(state){
                // Unsubscribing tells the API that the user is no longer on
                // on a socket-enabled page, and sends an empty groups object
                // to the API: {"groups": {}}.
                // This is used for all pages that are socket-disabled
                if(this.requiresNewSubscribe(state)){
                    this.emit(JSON.stringify(state.data.socket) || JSON.stringify({"groups": {}}));
                }
                this.setLast(state);
            },
            setLast: function(state){
                this.last = state;
            },
            getLast: function(){
                return this.last;
            },
            requiresNewSubscribe(state){
                // This function is used for unsubscribing. If the last $state
                // required an "unsubscribe", then we don't need to unsubscribe
                // again, b/c the UI is already unsubscribed from all groups
                if (this.getLast() !== undefined){
                    if( _.isEmpty(state.data.socket.groups) && _.isEmpty(this.getLast().data.socket.groups)){
                        return false;
                    }
                    else {
                        return true;
                    }
                }
                else {
                    return true;
                }
            },
            checkStatus: function() {
                // Function for changing the socket indicator icon in the nav bar
                var self = this;
                if(self){
                    if(self.socket){
                        if (self.socket.readyState === 0 ) {
                            $rootScope.socketStatus = 'connecting';
                            $rootScope.socketTip = i18n._(`Live events: attempting to connect to the ${$rootScope.BRAND_NAME} server.`);
                        }
                        else if (self.socket.readyState === 1){
                            $rootScope.socketStatus = 'ok';
                            $rootScope.socketTip = i18n._("Live events: connected. Pages containing job status information will automatically update in real-time.");
                        }
                        else if (self.socket.readyState === 2 || self.socket.readyState === 3 ){
                            $rootScope.socketStatus = 'error';
                            $rootScope.socketTip = i18n._(`Live events: error connecting to the ${$rootScope.BRAND_NAME} server.`);
                        }
                        return;
                    }
                }

            },
            emit: function(data, callback) {
                // Function used for sending objects to the API over the
                // websocket.
                var self = this;
                $log.debug('Sent to Websocket Server: ' + data);
                socketPromise.promise.then(function(){
                    console.log("socket readyState at emit: " + self.socket.readyState);
                    if(self.socket.readyState === 0){
                        self.subscribe(self.getLast());
                    }
                    if(self.socket.readyState === 1){
                        self.socket.send(data, function () {
                            var args = arguments;
                            self.scope.$apply(function () {
                                if (callback) {
                                    callback.apply(self.socket, args);
                                }
                            });
                        });
                    }
                });
            },
            addStateResolve: function(state, id){
                // This function is used for add a state resolve to all states,
                // socket-enabled AND socket-disabled, and whether the $state
                // requires a subscribe or an unsubscribe
                var self = this;
                socketPromise.promise.then(function(){
                    if(!state.data || !state.data.socket){
                        _.merge(state.data, {socket: {groups: {}}});
                        self.unsubscribe(state);
                    }
                    else{
                        if(state.data && state.data.socket && state.data.socket.groups.hasOwnProperty( "job_events")){
                            state.data.socket.groups.job_events = [id];
                        }
                        if(state.data && state.data.socket && state.data.socket.groups.hasOwnProperty( "ad_hoc_command_events")){
                            state.data.socket.groups.ad_hoc_command_events = [id];
                        }
                        if(state.data && state.data.socket && state.data.socket.groups.hasOwnProperty( "workflow_events")){
                            state.data.socket.groups.workflow_events = [id];
                        }
                        self.subscribe(state);
                    }
                    return true;
                });
            }
        };
    }];
<commit_msg>removing code that puts the UI in an infinite loop<commit_after>/*************************************************
 * Copyright (c) 2016 Ansible, Inc.
 *
 * All Rights Reserved
 *************************************************/
import ReconnectingWebSocket from 'reconnectingwebsocket';
export default
['$rootScope', '$location', '$log','$state', '$q', 'i18n',
    function ($rootScope, $location, $log, $state, $q, i18n) {
        var needsResubscribing = false,
        socketPromise = $q.defer();
        return {
            init: function() {
                var self = this,
                    host = window.location.host,
                    protocol,
                    url;

                if($location.protocol() === 'http'){
                    protocol = 'ws';
                }
                if($location.protocol() === 'https'){
                    protocol = 'wss';
                }
                url = `${protocol}://${host}/websocket/`;

                if (!$rootScope.sessionTimer || ($rootScope.sessionTimer && !$rootScope.sessionTimer.isExpired())) {

                    $log.debug('Socket connecting to: ' + url);

                    self.socket = new ReconnectingWebSocket(url, null, {
                        timeoutInterval: 3000,
                        maxReconnectAttempts: 10                    });

                    self.socket.onopen = function () {
                        $log.debug("Websocket connection opened.");
                        socketPromise.resolve();
                        console.log('promise resolved, and readyState: '+ self.readyState);
                        self.checkStatus();
                        if(needsResubscribing){
                            self.subscribe(self.getLast());
                            needsResubscribing = false;
                        }

                    };

                    self.socket.onerror = function (error) {
                        self.checkStatus();
                        $log.debug('Websocket Error Logged: ' + error); //log errors
                    };

                    self.socket.onconnecting = function () {
                        self.checkStatus();
                        $log.debug('Websocket reconnecting');
                        needsResubscribing = true;
                    };

                    self.socket.onclose = function () {
                        self.checkStatus();
                        $log.debug(`Websocket disconnected`);
                    };

                    self.socket.onmessage = this.onMessage;

                    return self.socket;
                }
                else {
                    // encountered expired token, redirect to login page
                    $rootScope.sessionTimer.expireSession('idle');
                    $location.url('/login');
                }
            },
            onMessage: function(e){
                // Function called when messages are received on by the UI from
                // the API over the websocket. This will route each message to
                // the appropriate controller for the current $state.
                $log.debug('Received From Server: ' + e.data);

                var data = JSON.parse(e.data), str = "";
                if(data.group_name==="jobs" && !('status' in data)){
                    // we know that this must have been a
                    // summary complete message b/c status is missing.
                    // A an object w/ group_name === "jobs" AND a 'status' key
                    // means it was for the event: status_changed.
                    $log.debug('Job summary_complete ' + data.unified_job_id);
                    $rootScope.$broadcast('ws-jobs-summary', data);
                    return;
                }
                else if(data.group_name==="job_events"){
                    // The naming scheme is "ws" then a
                    // dash (-) and the group_name, then the job ID
                    // ex: 'ws-jobs-<jobId>'
                    str = `ws-${data.group_name}-${data.job}`;
                }
                else if(data.group_name==="ad_hoc_command_events"){
                    // The naming scheme is "ws" then a
                    // dash (-) and the group_name, then the job ID
                    // ex: 'ws-jobs-<jobId>'
                    str = `ws-${data.group_name}-${data.ad_hoc_command}`;
                }
                else if(data.group_name==="control"){
                    // As of v. 3.1.0, there is only 1 "control"
                    // message, which is for expiring the session if the
                    // session limit is breached.
                    $log.debug(data.reason);
                    $rootScope.sessionTimer.expireSession('session_limit');
                    $state.go('signOut');
                }
                else {
                    // The naming scheme is "ws" then a
                    // dash (-) and the group_name.
                    // ex: 'ws-jobs'
                    str = `ws-${data.group_name}`;
                }
                $rootScope.$broadcast(str, data);
            },
            disconnect: function(){
                if(this.socket){
                    this.socket.close();
                    delete this.socket;
                    console.log("Socket deleted: "+this.socket);
                }
            },
            subscribe: function(state){
                // Subscribe is used to tell the API that the UI wants to
                // listen for specific messages. A subscription object could
                // look like {"groups":{"jobs": ["status_changed", "summary"]}.
                // This is used by all socket-enabled $states
                this.emit(JSON.stringify(state.data.socket));
                this.setLast(state);
            },
            unsubscribe: function(state){
                // Unsubscribing tells the API that the user is no longer on
                // on a socket-enabled page, and sends an empty groups object
                // to the API: {"groups": {}}.
                // This is used for all pages that are socket-disabled
                if(this.requiresNewSubscribe(state)){
                    this.emit(JSON.stringify(state.data.socket) || JSON.stringify({"groups": {}}));
                }
                this.setLast(state);
            },
            setLast: function(state){
                this.last = state;
            },
            getLast: function(){
                return this.last;
            },
            requiresNewSubscribe(state){
                // This function is used for unsubscribing. If the last $state
                // required an "unsubscribe", then we don't need to unsubscribe
                // again, b/c the UI is already unsubscribed from all groups
                if (this.getLast() !== undefined){
                    if( _.isEmpty(state.data.socket.groups) && _.isEmpty(this.getLast().data.socket.groups)){
                        return false;
                    }
                    else {
                        return true;
                    }
                }
                else {
                    return true;
                }
            },
            checkStatus: function() {
                // Function for changing the socket indicator icon in the nav bar
                var self = this;
                if(self){
                    if(self.socket){
                        if (self.socket.readyState === 0 ) {
                            $rootScope.socketStatus = 'connecting';
                            $rootScope.socketTip = i18n._(`Live events: attempting to connect to the ${$rootScope.BRAND_NAME} server.`);
                        }
                        else if (self.socket.readyState === 1){
                            $rootScope.socketStatus = 'ok';
                            $rootScope.socketTip = i18n._("Live events: connected. Pages containing job status information will automatically update in real-time.");
                        }
                        else if (self.socket.readyState === 2 || self.socket.readyState === 3 ){
                            $rootScope.socketStatus = 'error';
                            $rootScope.socketTip = i18n._(`Live events: error connecting to the ${$rootScope.BRAND_NAME} server.`);
                        }
                        return;
                    }
                }

            },
            emit: function(data, callback) {
                // Function used for sending objects to the API over the
                // websocket.
                var self = this;
                $log.debug('Sent to Websocket Server: ' + data);
                socketPromise.promise.then(function(){
                    console.log("socket readyState at emit: " + self.socket.readyState);
                    // if(self.socket.readyState === 0){
                    //     self.subscribe(self.getLast());
                    // }
                    if(self.socket.readyState === 1){
                        self.socket.send(data, function () {
                            var args = arguments;
                            self.scope.$apply(function () {
                                if (callback) {
                                    callback.apply(self.socket, args);
                                }
                            });
                        });
                    }
                });
            },
            addStateResolve: function(state, id){
                // This function is used for add a state resolve to all states,
                // socket-enabled AND socket-disabled, and whether the $state
                // requires a subscribe or an unsubscribe
                var self = this;
                socketPromise.promise.then(function(){
                    if(!state.data || !state.data.socket){
                        _.merge(state.data, {socket: {groups: {}}});
                        self.unsubscribe(state);
                    }
                    else{
                        if(state.data && state.data.socket && state.data.socket.groups.hasOwnProperty( "job_events")){
                            state.data.socket.groups.job_events = [id];
                        }
                        if(state.data && state.data.socket && state.data.socket.groups.hasOwnProperty( "ad_hoc_command_events")){
                            state.data.socket.groups.ad_hoc_command_events = [id];
                        }
                        if(state.data && state.data.socket && state.data.socket.groups.hasOwnProperty( "workflow_events")){
                            state.data.socket.groups.workflow_events = [id];
                        }
                        self.subscribe(state);
                    }
                    return true;
                });
            }
        };
    }];
<|endoftext|>


<commit_before>var d3 = window.d3;

d3.ma = {};

d3.ma.version = '0.1.0';
<commit_msg>update the noConflict function on d3ma, and update the d3.assert for customing the error log<commit_after>var d3 = window.d3;

var previousD3ma = window.d3.ma;

var d3ma = d3.ma = {};

d3ma.noConflict = function() {
	window.d3ma= previousD3ma;
	return d3ma;
};

d3ma.assert = function(test, message) {
	if(test) { return; }
	throw new Error('[d3.ma] ' + message);
};

d3ma.assert(d3, 'd3.js is required');

d3ma.assert( typeof d3.version === 'string' && d3.version.match(/^3/), 'd3.js version 3 is required' );

d3.ma.version = '0.1.0';

<|endoftext|>