<commit_before>var _ = require("lodash");
var Bootprint = require("./bootprint.js");
var debug = require("debug")("bootprint:builder");

var jsonschema = require('jsonschema');
var extra = require('jsonschema-extra');

var validator = new (jsonschema.Validator)();
extra(validator);

/**
 * This class is responsible for storing and adapting configuration options
 * for the [Bootprint](#Bootprint) object. The constructor is not
 * accessible outside the module. An instance of this class can be obtained
 * via `require("bootprint")`. Configurations can be changed using
 * [merge({...})](#BootprintBuilder#merge) and [load(require("bootprint-module"))](#BootprintBuilder#load)
 *
 * This class is immutable. All functions return new instances rather than mutating the current instance.
 *
 * @param {object} options new options for this builder.
 * @param {object} [parentOptions] a build to inherit options from
 * @class
 */
function BootprintBuilder(options, parentOptions) {

    debug("additional options:", options);
    var validationErrors = validator.validate(options, require("./config-schema")).errors;
    if (validationErrors.length > 0) {
        console.error("Error while validating config",options);
        console.error("Errors: ",validationErrors.map(String).join("\n"));
        throw new Error("Error while validating options-object",validationErrors);
    }
    require("assert")(validationErrors.length === 0, "Error: " + validationErrors);
    var _options = overrideOptions(options || {}, parentOptions);
    debug("merged options:", _options);

    // Accessible for testcases
    this._options = _options;

    /**
     * Creates a new instance of BootprintBuilder. The options of the current BootprintBuilder
     * are used as default values and are overridden by the options provided as parameter.
     * @param {object} options options overriding the options of this builder
     * @return {BootprintBuilder} new Builder instance
     */
    this.merge = function (options) {
        return new BootprintBuilder(options, _options);
    };

    /**
     * Inherit configuration options from another module.
     * `require("bootprint-modulename")` usually return a function(builder)
     * and this functions needs to be passed in here.
     * A new BootprintBuilder will be returned that overrides the current options
     * with options from the builderFunction's result.
     * @param builderFunction {function} that receives a BootprintBuilder as paramater
     *  and returns a BootprintBuilder with changed configuration.
     * @return {BootprintBuilder} the result of the builderFunction
     */
    this.load = function (builderFunction) {
        return builderFunction(this);
    };

    /**
     * Build the configured Bootprint-instance.
     * @param {string} jsonFile path the a file containing the data to pass into the template
     * @param {string} targetDir path to a directory where the HTML and CSS file should be created
     * @return {Bootprint} a Bootprint-instance
     */
    this.build = function (jsonFile, targetDir) {
        debug("Building converter with config: %o", _options);
        return new Bootprint(jsonFile, _options, targetDir);
    };
}

module.exports = BootprintBuilder;

// Helper functions

// Function for overriding options as described in the Builder-JSDoc
function overrideOptions(options, parentOptions) {
    // Inherit options from parent build or use empty object if not set
    var copy = _.clone(options, true);
    coerceToArray(copy, "partials");
    if (copy.less) {
        coerceToArray(copy.less, "main");
        coerceToArray(copy.less, "paths");
    }

    if (!parentOptions) {
        return copy;
    }
    var parentPreprocessor = parentOptions.preprocessor;
    // The preprocessor must be able to call the parent preprocessor.
    if (copy.preprocessor) {
        copy.preprocessor = copy.preprocessor.bind({
            parent: parentPreprocessor
        });
    }
    // Merge without mutating the parentOptions
    return _.merge({}, parentOptions, copy, function (a, b) {
        if (_.isArray(a)) {
            return a.concat(b);
        }
    });
}

/**
 * If `object[propertyName]` exists and is a non-array, it is replaced by
 * an array with the property as single object.
 * @param obj {object} the object
 * @param propertyName {string} the name of the object`s property to replace
 */
function coerceToArray(obj, propertyName) {
    if (!_.isUndefined(obj[propertyName]) && !_.isArray(obj[propertyName])) {
        obj[propertyName] = [ obj[propertyName] ];
    }
}

<commit_msg>Helper file is now configured as file, not as object of functions<commit_after>var _ = require("lodash");
var Bootprint = require("./bootprint.js");
var debug = require("debug")("bootprint:builder");

var jsonschema = require('jsonschema');
var extra = require('jsonschema-extra');

var validator = new (jsonschema.Validator)();
extra(validator);

/**
 * This class is responsible for storing and adapting configuration options
 * for the [Bootprint](#Bootprint) object. The constructor is not
 * accessible outside the module. An instance of this class can be obtained
 * via `require("bootprint")`. Configurations can be changed using
 * [merge({...})](#BootprintBuilder#merge) and [load(require("bootprint-module"))](#BootprintBuilder#load)
 *
 * This class is immutable. All functions return new instances rather than mutating the current instance.
 *
 * @param {object} options new options for this builder.
 * @param {object} [parentOptions] a build to inherit options from
 * @class
 */
function BootprintBuilder(options, parentOptions) {

    debug("additional options:", options);
    var validationErrors = validator.validate(options, require("./config-schema")).errors;
    if (validationErrors.length > 0) {
        console.error("Error while validating config",options);
        console.error("Errors: ",validationErrors.map(String).join("\n"));
        throw new Error("Error while validating options-object",validationErrors);
    }
    require("assert")(validationErrors.length === 0, "Error: " + validationErrors);
    var _options = overrideOptions(options || {}, parentOptions);
    debug("merged options:", _options);

    // Accessible for testcases
    this._options = _options;

    /**
     * Creates a new instance of BootprintBuilder. The options of the current BootprintBuilder
     * are used as default values and are overridden by the options provided as parameter.
     * @param {object} options options overriding the options of this builder
     * @return {BootprintBuilder} new Builder instance
     */
    this.merge = function (options) {
        return new BootprintBuilder(options, _options);
    };

    /**
     * Inherit configuration options from another module.
     * `require("bootprint-modulename")` usually return a function(builder)
     * and this functions needs to be passed in here.
     * A new BootprintBuilder will be returned that overrides the current options
     * with options from the builderFunction's result.
     * @param builderFunction {function} that receives a BootprintBuilder as paramater
     *  and returns a BootprintBuilder with changed configuration.
     * @return {BootprintBuilder} the result of the builderFunction
     */
    this.load = function (builderFunction) {
        return builderFunction(this);
    };

    /**
     * Build the configured Bootprint-instance.
     * @param {string} jsonFile path the a file containing the data to pass into the template
     * @param {string} targetDir path to a directory where the HTML and CSS file should be created
     * @return {Bootprint} a Bootprint-instance
     */
    this.build = function (jsonFile, targetDir) {
        debug("Building converter with config: %o", _options);
        return new Bootprint(jsonFile, _options, targetDir);
    };
}

module.exports = BootprintBuilder;

// Helper functions

// Function for overriding options as described in the Builder-JSDoc
function overrideOptions(options, parentOptions) {

    // Clone "options" to perform some modifications on the copy
    var copy = _.clone(options, true);
    coerceToArray(copy, "partials");
    if (copy.less) {
        coerceToArray(copy.less, "main");
        coerceToArray(copy.less, "paths");
    }
    copy.helpers = require(copy.helpers);

    if (!parentOptions) {
        return copy;
    }
    var parentPreprocessor = parentOptions.preprocessor;
    // The preprocessor must be able to call the parent preprocessor.
    if (copy.preprocessor) {
        copy.preprocessor = copy.preprocessor.bind({
            parent: parentPreprocessor
        });
    }
    // Merge without mutating the parentOptions
    return _.merge({}, parentOptions, copy, function (a, b) {
        if (_.isArray(a)) {
            return a.concat(b);
        }
    });
}

/**
 * If `object[propertyName]` exists and is a non-array, it is replaced by
 * an array with the property as single object.
 * @param obj {object} the object
 * @param propertyName {string} the name of the object`s property to replace
 */
function coerceToArray(obj, propertyName) {
    if (!_.isUndefined(obj[propertyName]) && !_.isArray(obj[propertyName])) {
        obj[propertyName] = [ obj[propertyName] ];
    }
}

<|endoftext|>


<commit_before>/**
 * @ngdoc directive
 * @name aaValMsgFor
 *
 * @description
 * Description place holder.
 **/
(function () {
  'use strict';

  angular.module('aa.formExtensions')
    //if used directly rather than passively with aaValMsg allows for direct placement of validation messages
    //for a given form field. ex. pass "myForm.myFieldName"
    .directive('aaValMsgFor', ['aaFormExtensions', 'aaUtils', function (aaFormExtensions, aaUtils) {
      //generate the validation message for a particular form field here
      return {
        require: ['^form'],
        priority: 1,
        scope: true,
        link: function ($scope, element, attrs) {

          var fullFieldPath = attrs.aaValMsgFor,
            fieldInForm = $scope.$eval(fullFieldPath),
            formObj = $scope.$eval(fullFieldPath.substring(0, fullFieldPath.indexOf('.')));

          //TODO: if this is inside an isolate scope and the form is outside the isolate scope this doesn't work
          //could nest multiple forms so can't trust directive require and have to eval to handle edge cases...
          aaUtils.ensureaaFormExtensionsFieldExists(formObj, fieldInForm.$name);
          $scope.fieldInFormExtensions = $scope.$eval(fullFieldPath.replace('.', '.$aaFormExtensions.'));

          $scope.$watchCollection(
            function () {
              return $scope.fieldInFormExtensions.$errorMessages;
            },
            function (val) {
              $scope.errorMessages = val;
            }
          );

          $scope.$watch(
            function () {
              return [
                formObj.$aaFormExtensions.$invalidAttempt,
                $scope.fieldInFormExtensions.showErrorReasons
              ];
            },
            function (watches) {
              var invalidAttempt = watches[0],
                showErrorReasons = watches[1];

              $scope.showMessages = invalidAttempt || showErrorReasons.length;
            },
            true
          );
        },
        template: aaFormExtensions.valMsgForTemplate,
        replace: true
      };
    }]);

})();
<commit_msg>fix(aaValMsgFor):Isolated Scopes<commit_after>/**
 * @ngdoc directive
 * @name aaValMsgFor
 *
 * @description
 * Description place holder.
 **/
(function () {
  'use strict';

  angular.module('aa.formExtensions')
    //if used directly rather than passively with aaValMsg allows for direct placement of validation messages
    //for a given form field. ex. pass "myForm.myFieldName"
    .directive('aaValMsgFor', ['aaFormExtensions', 'aaUtils', function (aaFormExtensions, aaUtils) {
      //generate the validation message for a particular form field here
      return {
        require: ['^form'],
        priority: 1,
        scope: true,
        link: function ($scope, element, attrs) {

          var fullFieldPath = attrs.aaValMsgFor;
          var  fieldInForm, formObj;

          var innerScope = $scope;
          while((!fieldInForm || !formObj) && innerScope){
            fieldInForm = innerScope.$eval(fullFieldPath);
            formObj = innerScope.$eval(fullFieldPath.substring(0, fullFieldPath.indexOf('.')));

            if((!fieldInForm || !formObj)){
              innerScope = innerScope.$parent;
            }
          }

          //TODO: if this is inside an isolate scope and the form is outside the isolate scope this doesn't work
          //could nest multiple forms so can't trust directive require and have to eval to handle edge cases...
          aaUtils.ensureaaFormExtensionsFieldExists(formObj, fieldInForm.$name);
          $scope.fieldInFormExtensions = innerScope.$eval(fullFieldPath.replace('.', '.$aaFormExtensions.'));

          $scope.$watchCollection(
            function () {
              return $scope.fieldInFormExtensions.$errorMessages;
            },
            function (val) {
              $scope.errorMessages = val;
            }
          );

          $scope.$watch(
            function () {
              return [
                formObj.$aaFormExtensions.$invalidAttempt,
                $scope.fieldInFormExtensions.showErrorReasons
              ];
            },
            function (watches) {
              var invalidAttempt = watches[0],
                showErrorReasons = watches[1];

              $scope.showMessages = invalidAttempt || showErrorReasons.length;
            },
            true
          );
        },
        template: aaFormExtensions.valMsgForTemplate,
        replace: true
      };
    }]);

})();
<|endoftext|>


<commit_before>import Vue from "vue";
import Vuex from "vuex";
import { createSharedMutations } from "vuex-electron";
import syncState from "./syncState";
import cloneDeep from "lodash.clonedeep";

Vue.use(Vuex);

export const AppStatus = {
  start: "start",
  setup: "setup",
  synchronize: "synchronize",
  ready: "ready",
  shutdown: "shutdown"
};

export default new Vuex.Store({
  state: {
    accounts: [],
    activeAccount: null,
    balance: null,
    coreReady: false,
    mutations: null,
    receiveAddress: null,
    status: AppStatus.start,
    unityVersion: null,
    walletExists: null,
    walletVersion: null
  },
  mutations: {
    REPLACE_STATE(state, payload) {
      this.replaceState(cloneDeep(payload.state));
    },
    SET_ACCOUNTS(state, payload) {
      state.accounts = payload.accounts;
    },
    SET_ACTIVE_ACCOUNT(state, payload) {
      state.activeAccount = payload.accountUUID;
    },
    SET_BALANCE(state, payload) {
      state.balance = payload.balance;
    },
    SET_CORE_READY(state, payload) {
      state.coreReady = payload.coreReady;
    },
    SET_MUTATIONS(state, payload) {
      state.mutations = payload.mutations;
    },
    SET_RECEIVE_ADDRESS(state, payload) {
      state.receiveAddress = payload.receiveAddress;
    },
    SET_STATUS(state, status) {
      if (state.status === AppStatus.shutdown) return;
      if (status === AppStatus.synchronize) {
        console.log(`skip synchronization for now`);
        status = AppStatus.ready;
      }
      state.status = status;
    },
    SET_UNITY_VERSION(state, payload) {
      state.unityVersion = payload.version;
    },
    SET_WALLET_EXISTS(state, walletExists) {
      state.walletExists = walletExists;
    },
    SET_WALLET_VERSION(state, payload) {
      state.walletVersion = payload.version;
    }
  },
  actions: {
    REPLACE_STATE({ commit }, payload) {
      commit(payload);
    },
    SET_ACCOUNT_NAME({ state, commit }, payload) {
      let accounts = [...state.accounts];
      let account = accounts.find(x => x.UUID === payload.accountUUID);
      account.label = payload.newAccountName;
      commit({ type: "SET_ACCOUNTS", accounts: accounts });
    },
    SET_ACCOUNTS({ commit }, payload) {
      commit(payload);
    },
    SET_ACTIVE_ACCOUNT({ commit }, payload) {
      commit(payload);
    },
    SET_BALANCE({ commit }, payload) {
      commit(payload);
    },
    SET_CORE_READY({ commit }, payload) {
      commit(payload);
    },
    SET_GULDEN_VERSION({ commit }, payload) {
      commit(payload);
    },
    SET_MUTATIONS({ commit }, payload) {
      commit(payload);
    },
    SET_RECEIVE_ADDRESS({ commit }, payload) {
      commit(payload);
    },
    SET_STATUS({ commit }, payload) {
      commit("SET_STATUS", payload.status);
    },
    SET_UNITY_VERSION({ commit }, payload) {
      commit(payload);
    },
    SET_WALLET_EXISTS({ commit }, payload) {
      let status = payload.walletExists
        ? AppStatus.synchronize
        : AppStatus.setup;
      commit("SET_STATUS", status);
      commit("SET_WALLET_EXISTS", payload.walletExists);
    },
    SET_WALLET_VERSION({ commit }, payload) {
      commit(payload);
    }
  },
  getters: {
    totalBalance: state => {
      let balance = state.balance;
      if (balance === undefined || balance === null) return null;
      return (
        (balance.availableIncludingLocked +
          balance.unconfirmedIncludingLocked +
          balance.immatureIncludingLocked) /
        100000000
      ).toFixed(2);
    },
    accounts: state => {
      return state.accounts
        .filter(x => x.state === "Normal")
        .sort((a, b) => {
          const labelA = a.label.toUpperCase();
          const labelB = b.label.toUpperCase();

          let comparison = 0;
          if (labelA > labelB) {
            comparison = 1;
          } else if (labelA < labelB) {
            comparison = -1;
          }
          return comparison;
        });
    },
    account: state => {
      return state.accounts.find(x => x.UUID === state.activeAccount);
    }
  },
  plugins: [syncState, createSharedMutations()]
});
<commit_msg>use synchronization status<commit_after>import Vue from "vue";
import Vuex from "vuex";
import { createSharedMutations } from "vuex-electron";
import syncState from "./syncState";
import cloneDeep from "lodash.clonedeep";

Vue.use(Vuex);

export const AppStatus = {
  start: "start",
  setup: "setup",
  synchronize: "synchronize",
  ready: "ready",
  shutdown: "shutdown"
};

export default new Vuex.Store({
  state: {
    accounts: [],
    activeAccount: null,
    balance: null,
    coreReady: false,
    mutations: null,
    receiveAddress: null,
    status: AppStatus.start,
    unityVersion: null,
    walletExists: null,
    walletVersion: null
  },
  mutations: {
    REPLACE_STATE(state, payload) {
      this.replaceState(cloneDeep(payload.state));
    },
    SET_ACCOUNTS(state, payload) {
      state.accounts = payload.accounts;
    },
    SET_ACTIVE_ACCOUNT(state, payload) {
      state.activeAccount = payload.accountUUID;
    },
    SET_BALANCE(state, payload) {
      state.balance = payload.balance;
    },
    SET_CORE_READY(state, payload) {
      state.coreReady = payload.coreReady;
    },
    SET_MUTATIONS(state, payload) {
      state.mutations = payload.mutations;
    },
    SET_RECEIVE_ADDRESS(state, payload) {
      state.receiveAddress = payload.receiveAddress;
    },
    SET_STATUS(state, status) {
      if (state.status === AppStatus.shutdown) return; // shutdown in progress, do not switch to other status
      state.status = status;
    },
    SET_UNITY_VERSION(state, payload) {
      state.unityVersion = payload.version;
    },
    SET_WALLET_EXISTS(state, walletExists) {
      state.walletExists = walletExists;
    },
    SET_WALLET_VERSION(state, payload) {
      state.walletVersion = payload.version;
    }
  },
  actions: {
    REPLACE_STATE({ commit }, payload) {
      commit(payload);
    },
    SET_ACCOUNT_NAME({ state, commit }, payload) {
      let accounts = [...state.accounts];
      let account = accounts.find(x => x.UUID === payload.accountUUID);
      account.label = payload.newAccountName;
      commit({ type: "SET_ACCOUNTS", accounts: accounts });
    },
    SET_ACCOUNTS({ commit }, payload) {
      commit(payload);
    },
    SET_ACTIVE_ACCOUNT({ commit }, payload) {
      commit(payload);
    },
    SET_BALANCE({ commit }, payload) {
      commit(payload);
    },
    SET_CORE_READY({ commit }, payload) {
      commit("SET_STATUS", AppStatus.ready); // set status to ready. maybe core_ready is redundant and can be removed.
      commit(payload);
    },
    SET_GULDEN_VERSION({ commit }, payload) {
      commit(payload);
    },
    SET_MUTATIONS({ commit }, payload) {
      commit(payload);
    },
    SET_RECEIVE_ADDRESS({ commit }, payload) {
      commit(payload);
    },
    SET_STATUS({ commit }, payload) {
      commit("SET_STATUS", payload.status);
    },
    SET_UNITY_VERSION({ commit }, payload) {
      commit(payload);
    },
    SET_WALLET_EXISTS({ commit }, payload) {
      let status = payload.walletExists
        ? AppStatus.synchronize
        : AppStatus.setup;
      commit("SET_STATUS", status);
      commit("SET_WALLET_EXISTS", payload.walletExists);
    },
    SET_WALLET_VERSION({ commit }, payload) {
      commit(payload);
    }
  },
  getters: {
    totalBalance: state => {
      let balance = state.balance;
      if (balance === undefined || balance === null) return null;
      return (
        (balance.availableIncludingLocked +
          balance.unconfirmedIncludingLocked +
          balance.immatureIncludingLocked) /
        100000000
      ).toFixed(2);
    },
    accounts: state => {
      return state.accounts
        .filter(x => x.state === "Normal")
        .sort((a, b) => {
          const labelA = a.label.toUpperCase();
          const labelB = b.label.toUpperCase();

          let comparison = 0;
          if (labelA > labelB) {
            comparison = 1;
          } else if (labelA < labelB) {
            comparison = -1;
          }
          return comparison;
        });
    },
    account: state => {
      return state.accounts.find(x => x.UUID === state.activeAccount);
    }
  },
  plugins: [syncState, createSharedMutations()]
});
<|endoftext|>


<commit_before>(function(global) {
  "use strict;"

  var VdomBuilder = function VdomBuilder(component, formId) {
    this.component = component;
    this.formId = formId;
    this.h = virtualDom.h;
    this.elements = [];
  };

  $.extend(VdomBuilder.prototype, {
    markup: function(tagName, arg1, arg2) {
      this.contentTag(tagName, arg1, arg2);
      return this.elements[0];
    },
    contentTag: function(tagName) {
      var options, content, callback, vb;

      if (typeof arguments[1] === 'string') {
        content = arguments[1];
        options = arguments[2] || {};
        attributes = generateAttributes(options);
        this.elements.push(this.h(tagName, attributes, content));
      }
      else {
        if (typeof arguments[1] === 'object') {
          options = arguments[1];
          callback = arguments[2];
        }
        else {
          options = {};
          callback = arguments[1];
        }
        if (typeof callback === 'function') {
          var vb = new VdomBuilder(this.component, this.formId);
          if (callback.length === 0) { throw new Error("Callback requires an argument.") }
          callback.call(this.component, vb);
          attributes = generateAttributes(options);
          this.elements.push(this.h(tagName, attributes, vb.elements));
        }
      }
    },
    tag: function(tagName, options) {
      attributes = generateAttributes(options);
      this.elements.push(this.h(tagName, attributes));
    },
    text: function(content) {
      this.elements.push(content);
    },
    space: function() {
      this.elements.push(' ');
    },
    form: function(name, options, callback) {
      var vb, attributes;

      if (callback.length === 0) { throw new Error("Callback requires an argument.") }
      vb = new VdomBuilder(this.component, name);
      callback.call(this.component, vb);
      options = options || {};
      options['name'] = name;
      if (options['onsubmit'] === undefined) {
        options['onsubmit'] = function(e) { return false };
      }
      attributes = generateAttributes(options);
      this.elements.push(this.h('form', attributes, vb.elements));
    },
    input: function(options) {
      var form, name, value;

      options = options || {};
      name = options['name'];
      value = options['value'];
      if (value === undefined && name !== undefined && this.formId !== undefined)
        options['value'] = this.component.getValue(this.formId, name);
      attributes = generateAttributes(options);
      this.elements.push(this.h('input', attributes));
    },
    textField: function(name, options) {
      var self = this;

      options = options || {};
      options['type'] = 'text';
      options['name'] = name;
      this.input(options);
    },
    checkBox: function(name, checked, options) {
      options = options || {};
      options['type'] = 'checkbox';
      if (name) options['name'] = name;
      if (checked) options['checked'] = 'checked';
      if (!options['value']) options['value'] = '1';
      this.input(options);
    },
    value: function(name) {
      this.component.getValue(this.formId, name);
    }
  });

  function generateAttributes(options) {
    if ('visible' in options && !options['visible']) {
      options['style'] = options['style'] || {};
      options['style']['display'] = 'none';
    }
    if (typeof options['className'] === 'object') {
      var names = []
      for (var name in options['className']) {
        if (options['className'][name]) {
          names.push(name)
        }
      }
      if (names.length) {
        options['className'] = names.join(' ')
      }
      else {
        delete options['className'];
      }
    }
    return options;
  }

  var normalElementNames = [
    'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo',
    'blockquote', 'body', 'button', 'canvas', 'caption', 'cite', 'code',
    'colgroup', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
    'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer',
    'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'html',
    'i', 'iframe', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark',
    'menu', 'menuitem', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup',
    'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's',
    'samp', 'script', 'section', 'select', 'small', 'span', 'strong', 'style',
    'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot',
    'th', 'thead', 'time', 'title', 'tr', 'u', 'ul', 'var', 'video' ];

  for (var i = 0; i < normalElementNames.length; i++) {
    var tagName = normalElementNames[i];
    VdomBuilder.prototype[tagName] = new Function("arg1", "arg2",
      "this.contentTag('" + tagName + "', arg1, arg2)");
  }

  var voidElementNames = [
    'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'keygen',
    'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'
  ]

  for (var i = 0; i < voidElementNames.length; i++) {
    var tagName = voidElementNames[i];
    VdomBuilder.prototype[tagName] = new Function("options",
      "this.tag('" + tagName + "', options)");
  }

  if (!global.CapeJS) {
    var CapeJS = {};
    if ("process" in global) module.exports = CapeJS;
    global.CapeJS = CapeJS;
  }
  global.CapeJS.VdomBuilder = VdomBuilder;

})((this || 0).self || global);
<commit_msg>Change signature of VdomBuilder#checkBox<commit_after>(function(global) {
  "use strict;"

  var VdomBuilder = function VdomBuilder(component, formId) {
    this.component = component;
    this.formId = formId;
    this.h = virtualDom.h;
    this.elements = [];
  };

  $.extend(VdomBuilder.prototype, {
    markup: function(tagName, arg1, arg2) {
      this.contentTag(tagName, arg1, arg2);
      return this.elements[0];
    },
    contentTag: function(tagName) {
      var options, content, callback, vb;

      if (typeof arguments[1] === 'string') {
        content = arguments[1];
        options = arguments[2] || {};
        attributes = generateAttributes(options);
        this.elements.push(this.h(tagName, attributes, content));
      }
      else {
        if (typeof arguments[1] === 'object') {
          options = arguments[1];
          callback = arguments[2];
        }
        else {
          options = {};
          callback = arguments[1];
        }
        if (typeof callback === 'function') {
          var vb = new VdomBuilder(this.component, this.formId);
          if (callback.length === 0) { throw new Error("Callback requires an argument.") }
          callback.call(this.component, vb);
          attributes = generateAttributes(options);
          this.elements.push(this.h(tagName, attributes, vb.elements));
        }
      }
    },
    tag: function(tagName, options) {
      attributes = generateAttributes(options);
      this.elements.push(this.h(tagName, attributes));
    },
    text: function(content) {
      this.elements.push(content);
    },
    space: function() {
      this.elements.push(' ');
    },
    form: function(name, options, callback) {
      var vb, attributes;

      if (callback.length === 0) { throw new Error("Callback requires an argument.") }
      vb = new VdomBuilder(this.component, name);
      callback.call(this.component, vb);
      options = options || {};
      options['name'] = name;
      if (options['onsubmit'] === undefined) {
        options['onsubmit'] = function(e) { return false };
      }
      attributes = generateAttributes(options);
      this.elements.push(this.h('form', attributes, vb.elements));
    },
    input: function(options) {
      var form, name, value;

      options = options || {};
      name = options['name'];
      value = options['value'];
      if (value === undefined && name !== undefined && this.formId !== undefined)
        options['value'] = this.component.getValue(this.formId, name);
      attributes = generateAttributes(options);
      this.elements.push(this.h('input', attributes));
    },
    textField: function(name, options) {
      var self = this;

      options = options || {};
      options['type'] = 'text';
      options['name'] = name;
      this.input(options);
    },
    checkBox: function(name, options) {
      var checked = this.component.getValue(this.formId, name);

      options = options || {};
      options['type'] = 'checkbox';
      if (name) options['name'] = name;
      if (checked) options['checked'] = 'checked';
      if (!options['value']) options['value'] = '1';
      this.input(options);
    },
    value: function(name) {
      this.component.getValue(this.formId, name);
    }
  });

  function generateAttributes(options) {
    if ('visible' in options && !options['visible']) {
      options['style'] = options['style'] || {};
      options['style']['display'] = 'none';
    }
    if (typeof options['className'] === 'object') {
      var names = []
      for (var name in options['className']) {
        if (options['className'][name]) {
          names.push(name)
        }
      }
      if (names.length) {
        options['className'] = names.join(' ')
      }
      else {
        delete options['className'];
      }
    }
    return options;
  }

  var normalElementNames = [
    'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo',
    'blockquote', 'body', 'button', 'canvas', 'caption', 'cite', 'code',
    'colgroup', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
    'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer',
    'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'html',
    'i', 'iframe', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark',
    'menu', 'menuitem', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup',
    'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's',
    'samp', 'script', 'section', 'select', 'small', 'span', 'strong', 'style',
    'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot',
    'th', 'thead', 'time', 'title', 'tr', 'u', 'ul', 'var', 'video' ];

  for (var i = 0; i < normalElementNames.length; i++) {
    var tagName = normalElementNames[i];
    VdomBuilder.prototype[tagName] = new Function("arg1", "arg2",
      "this.contentTag('" + tagName + "', arg1, arg2)");
  }

  var voidElementNames = [
    'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'keygen',
    'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'
  ]

  for (var i = 0; i < voidElementNames.length; i++) {
    var tagName = voidElementNames[i];
    VdomBuilder.prototype[tagName] = new Function("options",
      "this.tag('" + tagName + "', options)");
  }

  if (!global.CapeJS) {
    var CapeJS = {};
    if ("process" in global) module.exports = CapeJS;
    global.CapeJS = CapeJS;
  }
  global.CapeJS.VdomBuilder = VdomBuilder;

})((this || 0).self || global);
<|endoftext|>


<commit_before>'use strict';

var moment = require('moment-timezone');
var _ = require('lodash');

function init (client, $) {
  var careportal = { };

  var translate = client.translate;
  var storage = $.localStorage;

  careportal.events = [
      { val: '<none>', name: '<none>' }
    , { val: 'BG Check', name: 'BG Check' }
    , { val: 'Snack Bolus', name: 'Snack Bolus' }
    , { val: 'Meal Bolus', name: 'Meal Bolus' }
    , { val: 'Correction Bolus', name: 'Correction Bolus' }
    , { val: 'Carb Correction', name: 'Carb Correction' }
    , { val: 'Announcement', name: 'Announcement' }
    , { val: 'Note', name: 'Note' }
    , { val: 'Question', name: 'Question' }
    , { val: 'Exercise', name: 'Exercise' }
    , { val: 'Site Change', name: 'Pump Site Change' }
    , { val: 'Sensor Start', name: 'Dexcom Sensor Start' }
    , { val: 'Sensor Change', name: 'Dexcom Sensor Change' }
    , { val: 'Insulin Change', name: 'Insulin Cartridge Change' }
    , { val: 'Temp Basal Start', name: 'Temp Basal Start' }
    , { val: 'Temp Basal End', name: 'Temp Basal End' }
    , { val: 'D.A.D. Alert', name: 'D.A.D. Alert' }
  ];

  var eventTime = $('#eventTimeValue');
  var eventDate = $('#eventDateValue');

  function setDateAndTime (time) {
    time = time || moment();
    eventTime.val(time.format('HH:mm'));
    eventDate.val(time.format('YYYY-MM-DD'));
  }

  function mergeDateAndTime ( ) {
    return client.utils.mergeInputTime(eventTime.val(), eventDate.val());
  }

  function updateTime(ele, time) {
    ele.attr('oldminutes', time.minutes());
    ele.attr('oldhours', time.hours());
  }

  function maybePrevent (event) {
    if (event) {
      event.preventDefault();
    }
  }

  careportal.filterInputs = function filterInputs ( event ) {
    var inputMatrix = {
      '<none>':            { bg: true,  insulin: true,  carbs: true,  prebolus: true,  duration: false, percent: false, absolute: false }
    , 'BG Check':          { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Snack Bolus':       { bg: true,  insulin: true,  carbs: true,  prebolus: true,  duration: false, percent: false, absolute: false  }
    , 'Meal Bolus':        { bg: true,  insulin: true,  carbs: true,  prebolus: true,  duration: false, percent: false, absolute: false  }
    , 'Correction Bolus':  { bg: true,  insulin: true,  carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Carb Correction':   { bg: true,  insulin: false, carbs: true,  prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Announcement':      { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Note':              { bg: true,  insulin: false, carbs: false, prebolus: false, duration: true,  percent: false, absolute: false  }
    , 'Question':          { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Exercise':          { bg: false, insulin: false, carbs: false, prebolus: false, duration: true,  percent: false, absolute: false  }
    , 'Site Change':       { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Sensor Start':      { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Sensor Change':     { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Insulin Change':    { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Temp Basal Start':  { bg: true,  insulin: false, carbs: false, prebolus: false, duration: true,  percent: true,  absolute: true   }
    , 'Temp Basal End':    { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'D.A.D. Alert':      { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    };

    var eventType = $('#eventType').val();

    function displayType (enabled) {
      if (enabled) {
        return '';
      } else {
        return 'none';
      }
    }

    function resetIfHidden(visible, id) {
      if (!visible) {
        $(id).val('');
      }
    }

    $('#bg').css('display',displayType(inputMatrix[eventType]['bg']));
    $('#insulinGivenLabel').css('display',displayType(inputMatrix[eventType]['insulin']));
    $('#carbsGivenLabel').css('display',displayType(inputMatrix[eventType]['carbs']));
    $('#durationLabel').css('display',displayType(inputMatrix[eventType]['duration']));
    $('#percentLabel').css('display',displayType(inputMatrix[eventType]['percent'] && $('#absolute').val() === ''));
    $('#absoluteLabel').css('display',displayType(inputMatrix[eventType]['absolute'] && $('#percent').val() === ''));
    $('#preBolusLabel').css('display',displayType(inputMatrix[eventType]['prebolus']));

    resetIfHidden(inputMatrix[eventType]['insulin'], '#insulinGiven');
    resetIfHidden(inputMatrix[eventType]['carbs'], '#carbsGiven');
    resetIfHidden(inputMatrix[eventType]['duration'], '#duration');
    resetIfHidden(inputMatrix[eventType]['absolute'], '#absolute');
    resetIfHidden(inputMatrix[eventType]['percent'], '#percent');
    resetIfHidden(inputMatrix[eventType]['prebolus'], '#preBolus');

    maybePrevent(event);
  };

  careportal.prepareEvents = function prepareEvents ( ) {
    $('#eventType').empty();
    _.each(careportal.events, function eachEvent(event) {
      $('#eventType').append('<option value="' + event.val+ '">' + translate(event.name) + '</option>');
    });
    $('#eventType').change(careportal.filterInputs);
    $('#percentLabel').change(careportal.filterInputs);
    $('#absoluteLabel').change(careportal.filterInputs);
    careportal.filterInputs();
  };

  careportal.resolveEventName = function resolveEventName(value) {
    _.each(careportal.events, function eachEvent(e) {
      if (e.val === value) {
        value = e.name;
      }
    });
    return value;
  };

  careportal.prepare = function prepare ( ) {
    careportal.prepareEvents();
    $('#eventType').val('<none>');
    $('#glucoseValue').val('').attr('placeholder', translate('Value in') + ' ' + client.settings.units);
    $('#meter').prop('checked', true);
    $('#carbsGiven').val('');
    $('#insulinGiven').val('');
    $('#duration').val('');
    $('#percent').val('');
    $('#absolute').val('');
    $('#preBolus').val(0);
    $('#notes').val('');
    $('#enteredBy').val(storage.get('enteredBy') || '');
    $('#nowtime').prop('checked', true);
    setDateAndTime();
  };

  function gatherData ( ) {
    var data = {
      enteredBy: $('#enteredBy').val()
    , eventType: $('#eventType').val()
    , glucose: $('#glucoseValue').val()
    , glucoseType: $('#treatment-form').find('input[name=glucoseType]:checked').val()
    , carbs: $('#carbsGiven').val()
    , insulin: $('#insulinGiven').val()
    , duration: $('#duration').val()
    , percent: $('#percent').val()
    , absolute: $('#absolute').val()
    , preBolus: parseInt($('#preBolus').val())
    , notes: $('#notes').val()
    , units: client.settings.units
    };

    if ($('#othertime').is(':checked')) {
      data.eventTime = mergeDateAndTime().toDate();
    }

    if (data.eventType.indexOf('Temp Basal') > -1) {
      data.eventType = 'Temp Basal';
    }

    return data;
  }

  careportal.save = function save (event) {
    var data = gatherData();
    confirmPost(data);
    maybePrevent(event);
  };

  function buildConfirmText(data) {
    var text = [
      translate('Please verify that the data entered is correct') + ': '
      , translate('Event Type') + ': ' + translate(careportal.resolveEventName(data.eventType))
    ];

    function pushIf (check, valueText) {
      if (check) {
        text.push(valueText);
      }
    }

    pushIf(data.glucose, translate('Blood Glucose') + ': ' + data.glucose);
    pushIf(data.glucose, translate('Measurement Method') + ': ' + translate(data.glucoseType));

    pushIf(data.carbs, translate('Carbs Given') + ': ' + data.carbs);
    pushIf(data.insulin, translate('Insulin Given') + ': ' + data.insulin);
    pushIf(data.duration, translate('Duration') + ': ' + data.duration);
    pushIf(data.percent, translate('Percent') + ': ' + data.percent);
    pushIf(data.absolute, translate('Basal value') + ': ' + data.absolute);
    pushIf(data.preBolus, translate('Carb Time') + ': ' + data.preBolus + ' ' + translate('mins'));
    pushIf(data.notes, translate('Notes') + ': ' + data.notes);
    pushIf(data.enteredBy, translate('Entered By') + ': ' + data.enteredBy);

    text.push(translate('Event Time') + ': ' + (data.eventTime ? data.eventTime.toLocaleString() : new Date().toLocaleString()));
    return text.join('\n');
  }

  function confirmPost(data) {
    if (window.confirm(buildConfirmText(data))) {
      $.ajax({
        method: 'POST',
        url: '/api/v1/treatments/'
      , headers: {
        'api-secret': client.hashauth.hash()
      }
      , data: data
      }).done(function treatmentSaved (response) {
        console.info('treatment saved', response);
      }).fail(function treatmentSaveFail (response) {
        console.info('treatment saved', response);
        alert(translate('Entering record failed') + '. ' + translate('Status') + ': ' + response.status);
      });

      storage.set('enteredBy', data.enteredBy);

      client.browserUtils.closeDrawer('#treatmentDrawer');
    }
  }

  careportal.dateTimeFocus = function dateTimeFocus (event) {
    $('#othertime').prop('checked', true);
    updateTime($(this), mergeDateAndTime());
    maybePrevent(event);
  };

  careportal.dateTimeChange = function dateTimeChange (event) {
    $('#othertime').prop('checked', true);
    var ele = $(this);
    var merged = mergeDateAndTime();

    if (ele.attr('oldminutes') === '59' && merged.minutes() === 0) {
      merged.add(1, 'hours');
    }
    if (ele.attr('oldminutes') === '0' && merged.minutes() === 59) {
      merged.add(-1, 'hours');
    }

    setDateAndTime(merged);
    updateTime(ele, merged);
    maybePrevent(event);
  };

  careportal.eventTimeTypeChange = function eventTimeTypeChange (event) {
    if ($('#othertime').is(':checked')) {
      eventTime.focus();
    } else {
      setDateAndTime();
    }
    maybePrevent(event);
  };

  careportal.toggleDrawer = function toggleDrawer (event) {
    client.browserUtils.toggleDrawer('#treatmentDrawer', careportal.prepare);
    maybePrevent(event);
  };

  $('#treatmentDrawerToggle').click(careportal.toggleDrawer);
  $('#treatmentDrawer').find('button').click(careportal.save);
  $('#eventTime').find('input:radio').change(careportal.eventTimeTypeChange);

  $('.eventinput').focus(careportal.dateTimeFocus).change(careportal.dateTimeChange);

  return careportal;
}

module.exports = init;

<commit_msg>tweek inputMatrix<commit_after>'use strict';

var moment = require('moment-timezone');
var _ = require('lodash');

function init (client, $) {
  var careportal = { };

  var translate = client.translate;
  var storage = $.localStorage;

  careportal.events = [
      { val: '<none>', name: '<none>' }
    , { val: 'BG Check', name: 'BG Check' }
    , { val: 'Snack Bolus', name: 'Snack Bolus' }
    , { val: 'Meal Bolus', name: 'Meal Bolus' }
    , { val: 'Correction Bolus', name: 'Correction Bolus' }
    , { val: 'Carb Correction', name: 'Carb Correction' }
    , { val: 'Announcement', name: 'Announcement' }
    , { val: 'Note', name: 'Note' }
    , { val: 'Question', name: 'Question' }
    , { val: 'Exercise', name: 'Exercise' }
    , { val: 'Site Change', name: 'Pump Site Change' }
    , { val: 'Sensor Start', name: 'Dexcom Sensor Start' }
    , { val: 'Sensor Change', name: 'Dexcom Sensor Change' }
    , { val: 'Insulin Change', name: 'Insulin Cartridge Change' }
    , { val: 'Temp Basal Start', name: 'Temp Basal Start' }
    , { val: 'Temp Basal End', name: 'Temp Basal End' }
    , { val: 'D.A.D. Alert', name: 'D.A.D. Alert' }
  ];

  var eventTime = $('#eventTimeValue');
  var eventDate = $('#eventDateValue');

  function setDateAndTime (time) {
    time = time || moment();
    eventTime.val(time.format('HH:mm'));
    eventDate.val(time.format('YYYY-MM-DD'));
  }

  function mergeDateAndTime ( ) {
    return client.utils.mergeInputTime(eventTime.val(), eventDate.val());
  }

  function updateTime(ele, time) {
    ele.attr('oldminutes', time.minutes());
    ele.attr('oldhours', time.hours());
  }

  function maybePrevent (event) {
    if (event) {
      event.preventDefault();
    }
  }

  careportal.filterInputs = function filterInputs ( event ) {
    var inputMatrix = {
      '<none>':            { bg: true,  insulin: true,  carbs: true,  prebolus: true,  duration: false, percent: false, absolute: false }
    , 'BG Check':          { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Snack Bolus':       { bg: true,  insulin: true,  carbs: true,  prebolus: true,  duration: false, percent: false, absolute: false  }
    , 'Meal Bolus':        { bg: true,  insulin: true,  carbs: true,  prebolus: true,  duration: false, percent: false, absolute: false  }
    , 'Correction Bolus':  { bg: true,  insulin: true,  carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Carb Correction':   { bg: true,  insulin: false, carbs: true,  prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Announcement':      { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Note':              { bg: true,  insulin: false, carbs: false, prebolus: false, duration: true,  percent: false, absolute: false  }
    , 'Question':          { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Exercise':          { bg: false, insulin: false, carbs: false, prebolus: false, duration: true,  percent: false, absolute: false  }
    , 'Site Change':       { bg: false, insulin: true,  carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Sensor Start':      { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Sensor Change':     { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Insulin Change':    { bg: false, insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'Temp Basal Start':  { bg: true,  insulin: false, carbs: false, prebolus: false, duration: true,  percent: true,  absolute: true   }
    , 'Temp Basal End':    { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    , 'D.A.D. Alert':      { bg: true,  insulin: false, carbs: false, prebolus: false, duration: false, percent: false, absolute: false  }
    };

    var eventType = $('#eventType').val();

    function displayType (enabled) {
      if (enabled) {
        return '';
      } else {
        return 'none';
      }
    }

    function resetIfHidden(visible, id) {
      if (!visible) {
        $(id).val('');
      }
    }

    $('#bg').css('display',displayType(inputMatrix[eventType]['bg']));
    $('#insulinGivenLabel').css('display',displayType(inputMatrix[eventType]['insulin']));
    $('#carbsGivenLabel').css('display',displayType(inputMatrix[eventType]['carbs']));
    $('#durationLabel').css('display',displayType(inputMatrix[eventType]['duration']));
    $('#percentLabel').css('display',displayType(inputMatrix[eventType]['percent'] && $('#absolute').val() === ''));
    $('#absoluteLabel').css('display',displayType(inputMatrix[eventType]['absolute'] && $('#percent').val() === ''));
    $('#preBolusLabel').css('display',displayType(inputMatrix[eventType]['prebolus']));

    resetIfHidden(inputMatrix[eventType]['insulin'], '#insulinGiven');
    resetIfHidden(inputMatrix[eventType]['carbs'], '#carbsGiven');
    resetIfHidden(inputMatrix[eventType]['duration'], '#duration');
    resetIfHidden(inputMatrix[eventType]['absolute'], '#absolute');
    resetIfHidden(inputMatrix[eventType]['percent'], '#percent');
    resetIfHidden(inputMatrix[eventType]['prebolus'], '#preBolus');

    maybePrevent(event);
  };

  careportal.prepareEvents = function prepareEvents ( ) {
    $('#eventType').empty();
    _.each(careportal.events, function eachEvent(event) {
      $('#eventType').append('<option value="' + event.val+ '">' + translate(event.name) + '</option>');
    });
    $('#eventType').change(careportal.filterInputs);
    $('#percentLabel').change(careportal.filterInputs);
    $('#absoluteLabel').change(careportal.filterInputs);
    careportal.filterInputs();
  };

  careportal.resolveEventName = function resolveEventName(value) {
    _.each(careportal.events, function eachEvent(e) {
      if (e.val === value) {
        value = e.name;
      }
    });
    return value;
  };

  careportal.prepare = function prepare ( ) {
    careportal.prepareEvents();
    $('#eventType').val('<none>');
    $('#glucoseValue').val('').attr('placeholder', translate('Value in') + ' ' + client.settings.units);
    $('#meter').prop('checked', true);
    $('#carbsGiven').val('');
    $('#insulinGiven').val('');
    $('#duration').val('');
    $('#percent').val('');
    $('#absolute').val('');
    $('#preBolus').val(0);
    $('#notes').val('');
    $('#enteredBy').val(storage.get('enteredBy') || '');
    $('#nowtime').prop('checked', true);
    setDateAndTime();
  };

  function gatherData ( ) {
    var data = {
      enteredBy: $('#enteredBy').val()
    , eventType: $('#eventType').val()
    , glucose: $('#glucoseValue').val()
    , glucoseType: $('#treatment-form').find('input[name=glucoseType]:checked').val()
    , carbs: $('#carbsGiven').val()
    , insulin: $('#insulinGiven').val()
    , duration: $('#duration').val()
    , percent: $('#percent').val()
    , absolute: $('#absolute').val()
    , preBolus: parseInt($('#preBolus').val())
    , notes: $('#notes').val()
    , units: client.settings.units
    };

    if ($('#othertime').is(':checked')) {
      data.eventTime = mergeDateAndTime().toDate();
    }

    if (data.eventType.indexOf('Temp Basal') > -1) {
      data.eventType = 'Temp Basal';
    }

    return data;
  }

  careportal.save = function save (event) {
    var data = gatherData();
    confirmPost(data);
    maybePrevent(event);
  };

  function buildConfirmText(data) {
    var text = [
      translate('Please verify that the data entered is correct') + ': '
      , translate('Event Type') + ': ' + translate(careportal.resolveEventName(data.eventType))
    ];

    function pushIf (check, valueText) {
      if (check) {
        text.push(valueText);
      }
    }

    pushIf(data.glucose, translate('Blood Glucose') + ': ' + data.glucose);
    pushIf(data.glucose, translate('Measurement Method') + ': ' + translate(data.glucoseType));

    pushIf(data.carbs, translate('Carbs Given') + ': ' + data.carbs);
    pushIf(data.insulin, translate('Insulin Given') + ': ' + data.insulin);
    pushIf(data.duration, translate('Duration') + ': ' + data.duration);
    pushIf(data.percent, translate('Percent') + ': ' + data.percent);
    pushIf(data.absolute, translate('Basal value') + ': ' + data.absolute);
    pushIf(data.preBolus, translate('Carb Time') + ': ' + data.preBolus + ' ' + translate('mins'));
    pushIf(data.notes, translate('Notes') + ': ' + data.notes);
    pushIf(data.enteredBy, translate('Entered By') + ': ' + data.enteredBy);

    text.push(translate('Event Time') + ': ' + (data.eventTime ? data.eventTime.toLocaleString() : new Date().toLocaleString()));
    return text.join('\n');
  }

  function confirmPost(data) {
    if (window.confirm(buildConfirmText(data))) {
      $.ajax({
        method: 'POST',
        url: '/api/v1/treatments/'
      , headers: {
        'api-secret': client.hashauth.hash()
      }
      , data: data
      }).done(function treatmentSaved (response) {
        console.info('treatment saved', response);
      }).fail(function treatmentSaveFail (response) {
        console.info('treatment saved', response);
        alert(translate('Entering record failed') + '. ' + translate('Status') + ': ' + response.status);
      });

      storage.set('enteredBy', data.enteredBy);

      client.browserUtils.closeDrawer('#treatmentDrawer');
    }
  }

  careportal.dateTimeFocus = function dateTimeFocus (event) {
    $('#othertime').prop('checked', true);
    updateTime($(this), mergeDateAndTime());
    maybePrevent(event);
  };

  careportal.dateTimeChange = function dateTimeChange (event) {
    $('#othertime').prop('checked', true);
    var ele = $(this);
    var merged = mergeDateAndTime();

    if (ele.attr('oldminutes') === '59' && merged.minutes() === 0) {
      merged.add(1, 'hours');
    }
    if (ele.attr('oldminutes') === '0' && merged.minutes() === 59) {
      merged.add(-1, 'hours');
    }

    setDateAndTime(merged);
    updateTime(ele, merged);
    maybePrevent(event);
  };

  careportal.eventTimeTypeChange = function eventTimeTypeChange (event) {
    if ($('#othertime').is(':checked')) {
      eventTime.focus();
    } else {
      setDateAndTime();
    }
    maybePrevent(event);
  };

  careportal.toggleDrawer = function toggleDrawer (event) {
    client.browserUtils.toggleDrawer('#treatmentDrawer', careportal.prepare);
    maybePrevent(event);
  };

  $('#treatmentDrawerToggle').click(careportal.toggleDrawer);
  $('#treatmentDrawer').find('button').click(careportal.save);
  $('#eventTime').find('input:radio').change(careportal.eventTimeTypeChange);

  $('.eventinput').focus(careportal.dateTimeFocus).change(careportal.dateTimeChange);

  return careportal;
}

module.exports = init;

<|endoftext|>


<commit_before>function SmartCollection(name) {
  var self = this;
  this.name = name;
  this._remoteCollection = new Meteor.Collection(name);
  this._localCollection = new Meteor.Collection(null);

  this._pipeHandler = this._pipe(this._remoteCollection, this._localCollection);

  //wrap methods from the _remoteCollection
  ['find', 'findOne', 'allow', 'deny'].forEach(function(field) {
    self[field] = function() {
      return self._localCollection[field].apply(self._localCollection, arguments);
    };
  });
}

SmartCollection.prototype.insert = function(doc, callback) {
  //_si_ == smart insert :P
  if(!doc._id) {
    doc._id = Random.id();
  }

  if(this._isSimulation()) {
    this._remoteCollection.insert(doc, callback);
  } else {
    Meteor.call('_si_', this.name, doc, callback);
  }
  return doc._id;
};

SmartCollection.prototype.update = function(selector, modifier, callback) {
  if(this._isSimulation()) {
    this._remoteCollection.update(selector, modifier, callback);
  } else {
    var id = this._getId(selector);
    Meteor.call('_su_', this.name, id, modifier, callback);
  }
};

SmartCollection.prototype.remove = function(selector, callback) {
  if(this._isSimulation()) {
    this._remoteCollection.remove(selector, callback);
  } else {
    var id = this._getId(selector);
    Meteor.call('_sr_', this.name, id, callback);
  }
};

SmartCollection.prototype._getId = function(selector) {
  var id;
  if(typeof(selector) == 'string') {
    id = selector;
  } else if(typeof(selector) == 'object' && typeof(selector._id) == 'string') {
    id = selector._id;
  }

  if(!id) {
    throw new Meteor.Error('403', 'Not permitted. Untrusted code may only update documents by ID');
  } else {
    return id;
  }
};

SmartCollection.prototype._isSimulation = function() {
  var enclosing = Meteor._CurrentInvocation.get();
  return enclosing && enclosing.isSimulation;
};

SmartCollection.prototype._pipe = function() {
  var self = this;
  var handler = this._remoteCollection.find().observeChanges({
    added: onAdded,
    changed: onChanged,
    removed: onRemoved
  });

  function onAdded(id, doc) {
    var haveDoc = self._localCollection.findOne(id);
    if(haveDoc) {
      self._localCollection.update(id, {$set: doc});
    } else {
      doc._id = id;
      self._localCollection.insert(doc);
    }
  }

  function onChanged(id, fields) {
    var haveDoc = self._localCollection.findOne(id);
    if(haveDoc) {
      self._localCollection.update(id, {$set: fields});
    } else {
      fields._id = id;
      self._localCollection.insert(fields);
    }
  }

  function onRemoved(id) {
    self._localCollection.remove(id);
  }

  return handler;
};

Meteor.SmartCollection = SmartCollection;<commit_msg>added imediate propergation, but not tested yet<commit_after>function SmartCollection(name) {
  var self = this;
  this.name = name;
  this._remoteCollection = new Meteor.Collection(name);
  this._localCollection = new Meteor.Collection(null);

  this._pipeHandler = this._pipe(this._remoteCollection, this._localCollection);

  //wrap methods from the _remoteCollection
  ['find', 'findOne', 'allow', 'deny'].forEach(function(field) {
    self[field] = function() {
      return self._localCollection[field].apply(self._localCollection, arguments);
    };
  });
}

SmartCollection.prototype.insert = function(doc, callback) {
  var self = this;
  //_si_ == smart insert :P
  if(!doc._id) {
    doc._id = Random.id();
  }

  if(this._isSimulation()) {
    this._remoteCollection.insert(doc, callback);
  } else {
    this._localCollection.insert(doc);
    Meteor.call('_si_', this.name, doc, afterInserted);
  }

  function afterInserted(err) {
    if(err) {
      //check the document in the remoteCollection
      var remoteDoc = self._remoteCollection.findOne(doc._id);
      if(!remoteDoc) {
        //only remove from localCollection if no such doc exits in the remoteCollection
        self._localCollection.remove(doc._id);
      }
    }

    if(callback) callback(err);
  }
  return doc._id;
};

SmartCollection.prototype.update = function(selector, modifier, callback) {
  var self = this;
  if(this._isSimulation()) {
    this._remoteCollection.update(selector, modifier, callback);
  } else {
    var id = this._getId(selector);
    this._localCollection.update(selector, modifier);
    Meteor.call('_su_', this.name, id, modifier, afterUpdated);
  }

  function afterUpdated(err) {
    if(err) {
      var remoteDoc = self._remoteCollection.findOne(selector);
      if(remoteDoc) {
        self._localCollection.update(selector, {$set: remoteDoc});
      }
    }

    if(callback) callback(err);
  }
};

SmartCollection.prototype.remove = function(selector, callback) {
  var self = this;
  if(this._isSimulation()) {
    this._remoteCollection.remove(selector, callback);
  } else {
    var id = this._getId(selector);
    this._localCollection.remove(selector);
    Meteor.call('_sr_', this.name, id, afterRemoved);
  }

  function afterRemoved(err) {
    if(err) {
      var remoteDoc = self._remoteCollection.findOne(selector);
      if(remoteDoc) {
        self._localCollection.insert(remoteDoc);
      }
    }

    if(callback) callback(err);
  }
};

SmartCollection.prototype._getId = function(selector) {
  var id;
  if(typeof(selector) == 'string') {
    id = selector;
  } else if(typeof(selector) == 'object' && typeof(selector._id) == 'string') {
    id = selector._id;
  }

  if(!id) {
    throw new Meteor.Error('403', 'Not permitted. Untrusted code may only update documents by ID');
  } else {
    return id;
  }
};

SmartCollection.prototype._isSimulation = function() {
  var enclosing = Meteor._CurrentInvocation.get();
  return enclosing && enclosing.isSimulation;
};

SmartCollection.prototype._pipe = function() {
  var self = this;
  var handler = this._remoteCollection.find().observeChanges({
    added: onAdded,
    changed: onChanged,
    removed: onRemoved
  });

  function onAdded(id, doc) {
    var haveDoc = self._localCollection.findOne(id);
    if(haveDoc) {
      self._localCollection.update(id, {$set: doc});
    } else {
      doc._id = id;
      self._localCollection.insert(doc);
    }
  }

  function onChanged(id, fields) {
    var haveDoc = self._localCollection.findOne(id);
    if(haveDoc) {
      self._localCollection.update(id, {$set: fields});
    } else {
      fields._id = id;
      self._localCollection.insert(fields);
    }
  }

  function onRemoved(id) {
    self._localCollection.remove(id);
  }

  return handler;
};

Meteor.SmartCollection = SmartCollection;<|endoftext|>


<commit_before>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2022 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * Renders this Game Object with the Canvas Renderer to the given Camera.
 * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
 * This method should not be called directly. It is a utility function of the Render module.
 *
 * @method Phaser.GameObjects.Layer#renderCanvas
 * @since 3.50.0
 * @private
 *
 * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
 * @param {Phaser.GameObjects.Layer} layer - The Game Object being rendered in this call.
 * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
 * @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
 */
var LayerCanvasRenderer = function (renderer, layer, camera)
{
    var children = layer.list;

    if (children.length === 0)
    {
        return;
    }

    layer.depthSort();

    var layerHasBlendMode = (layer.blendMode !== -1);

    if (!layerHasBlendMode)
    {
        //  If Layer is SKIP_TEST then set blend mode to be Normal
        renderer.setBlendMode(0);
    }

    var alpha = layer._alpha;

    if (layer.mask)
    {
        layer.mask.preRenderCanvas(renderer, null, camera);
    }

    for (var i = 0; i < children.length; i++)
    {
        var child = children[i];

        if (!child.willRender(camera))
        {
            continue;
        }

        var childAlpha = child.alpha;

        if (!layerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
        {
            //  If Layer doesn't have its own blend mode, then a child can have one
            renderer.setBlendMode(child.blendMode);
        }

        //  Set parent values
        child.setAlpha(childAlpha * alpha);

        //  Render
        child.renderCanvas(renderer, child, camera);

        //  Restore original values
        child.setAlpha(childAlpha);
    }

    if (layer.mask)
    {
        layer.mask.postRenderCanvas(renderer);
    }
};

module.exports = LayerCanvasRenderer;
<commit_msg>Fixed jsdocs<commit_after>/**
 * @author       Richard Davey <rich@photonstorm.com>
 * @copyright    2022 Photon Storm Ltd.
 * @license      {@link https://opensource.org/licenses/MIT|MIT License}
 */

/**
 * Renders this Game Object with the Canvas Renderer to the given Camera.
 * The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
 * This method should not be called directly. It is a utility function of the Render module.
 *
 * @method Phaser.GameObjects.Layer#renderCanvas
 * @since 3.50.0
 * @private
 *
 * @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
 * @param {Phaser.GameObjects.Layer} layer - The Game Object being rendered in this call.
 * @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
 */
var LayerCanvasRenderer = function (renderer, layer, camera)
{
    var children = layer.list;

    if (children.length === 0)
    {
        return;
    }

    layer.depthSort();

    var layerHasBlendMode = (layer.blendMode !== -1);

    if (!layerHasBlendMode)
    {
        //  If Layer is SKIP_TEST then set blend mode to be Normal
        renderer.setBlendMode(0);
    }

    var alpha = layer._alpha;

    if (layer.mask)
    {
        layer.mask.preRenderCanvas(renderer, null, camera);
    }

    for (var i = 0; i < children.length; i++)
    {
        var child = children[i];

        if (!child.willRender(camera))
        {
            continue;
        }

        var childAlpha = child.alpha;

        if (!layerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
        {
            //  If Layer doesn't have its own blend mode, then a child can have one
            renderer.setBlendMode(child.blendMode);
        }

        //  Set parent values
        child.setAlpha(childAlpha * alpha);

        //  Render
        child.renderCanvas(renderer, child, camera);

        //  Restore original values
        child.setAlpha(childAlpha);
    }

    if (layer.mask)
    {
        layer.mask.postRenderCanvas(renderer);
    }
};

module.exports = LayerCanvasRenderer;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Adobe Systems Incorporated and other contributors.
 * All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, brackets, $ */

define(function (require, exports, module) {
	"use strict";

	var EditorManager = brackets.getModule("editor/EditorManager");
	var Inspector     = brackets.getModule("LiveDevelopment/Inspector/Inspector");
	var Main          = require("main");

	var $panel, $toolbar;
	var _panel, _shown = false;

	function setPanel(panel) {
		if (panel === _panel) {
			return;
		}
		if (_panel) {
			_panel.remove();
		}
		_panel = panel;
		_panel.add($panel);
	}

	/** Toggle the display of the panel */
	function toggle(show) {
		if (arguments.length > 0) {
			_shown = show;
		} else {
			_shown = !_shown;
		}
		$panel.toggle(show);
		EditorManager.resizeEditor();
	}

	function _enable() {
		// toggle(true);
	}

	function _disable() {
		toggle(false);
	}

	/** Initialize the panel */
	function init() {
		$panel = $("
").appendTo(".main-view .content");
		$toolbar = $("
").appendTo($panel);
		$("
").appendTo($toolbar).text("Log");
		$("").appendTo($toolbar).html("×");

		$(Main).on("enable", _enable);
		$(Main).on("disable", _disable);
	}

	/** Unload the panel */
	function unload() {
		$(Main).off("enable", _enable);
		$(Main).off("disable", _disable);

		$panel.remove();
		$panel = undefined;
	}

	exports.init = init;
	exports.unload = unload;
	exports.toggle = toggle;
	exports.setPanel = setPanel;
});
<commit_msg>make the Theseus panel resizable (hi @joelrbrandt!)<commit_after>/*
 * Copyright (c) 2012 Adobe Systems Incorporated and other contributors.
 * All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, brackets, $ */

define(function (require, exports, module) {
	"use strict";

	var EditorManager = brackets.getModule("editor/EditorManager");
	var Inspector     = brackets.getModule("LiveDevelopment/Inspector/Inspector");
	var Main          = require("main");
	var Resizer       = brackets.getModule("utils/Resizer");

	var $panel, $toolbar;
	var _panel, _shown = false;

	function setPanel(panel) {
		if (panel === _panel) {
			return;
		}
		if (_panel) {
			_panel.remove();
		}
		_panel = panel;
		_panel.add($panel);
	}

	/** Toggle the display of the panel */
	function toggle(show) {
		if (show === undefined) {
			Resizer.toggle($panel.get(0));
		} else if (show) {
			Resizer.show($panel.get(0));
		} else {
			Resizer.hide($panel.get(0));
		}
		$panel.toggle(show);
	}

	function _enable() {
		// toggle(true);
	}

	function _disable() {
		toggle(false);
	}

	/** Initialize the panel */
	function init() {
		$panel = $("
").insertAfter(".bottom-panel:last");
		$toolbar = $("
").appendTo($panel);
		$("
").appendTo($toolbar).text("Log");
		$("").appendTo($toolbar).html("×");

		Resizer.makeResizable($panel.get(0),
		                      "vert" /* Resizer.DIRECTION_VERTICAL */,
		                      "top" /* Resizer.POSITION_TOP */,
		                      100, // minSize
		                      false // collapsible
		                      );

		$(Main).on("enable", _enable);
		$(Main).on("disable", _disable);
	}

	/** Unload the panel */
	function unload() {
		$(Main).off("enable", _enable);
		$(Main).off("disable", _disable);

		$panel.remove();
		$panel = undefined;
	}

	exports.init = init;
	exports.unload = unload;
	exports.toggle = toggle;
	exports.setPanel = setPanel;
});
<|endoftext|>


<commit_before>var _ = require('../util').lodash,
    PropertyBase = require('./property-base').PropertyBase,

    Cookie,

    PAIR_SPLIT_REGEX = /; */,

    /**
     * Enum for all the Cookie attributes.
     * @private
     * @readonly
     * @enum {string} CookieAttributes
     */
    cookieAttributes = {
        httponly: 'httpOnly',
        secure: 'secure',
        domain: 'domain',
        path: 'path',
        'max-age': 'maxAge',
        session: 'session',
        expires: 'expires'
    };

/**
 * The following is the object structure accepted as constructor parameter while calling `new Cookie(...)`. It is
 * also the structure exported when {@link Property#toJSON} or {@link Property#toObjectResolved} is called on a
 * Cookie instance.
 * @typedef Cookie~definition
 *
 * @property {String=} [name] The name of the cookie. Some call it the "key".
 * @property {String=} [expires] Expires sets an expiry date for when a cookie gets deleted. It should either be a
 * date object or timestamp string of date.
 * @property {Number=} [maxAge] Max-age sets the time in seconds for when a cookie will be deleted.
 * @property {String=} [domain] Indicates the domain(s) for which the cookie should be sent.
 * @property {String=} [path] Limits the scope of the cookie to a specified path, e.g: "/accounts"
 * @property {Boolean=} [secure] A secure cookie will only be sent to the server when a request is made using SSL and
 * the HTTPS protocol.
 * The idea that the contents of the cookie are of high value and could be potentially damaging to transmit
 * as clear text.
 * @property {Boolean=} [httpOnly] The idea behind HTTP-only cookies is to instruct a browser that a cookie should never
 * be accessible via JavaScript through the document.cookie property. This feature was designed as a security measure
 * to help prevent cross-site scripting (XSS) attacks perpetrated by stealing cookies via JavaScript.
 * @property {Boolean=} [hostOnly] Indicates that this cookie is only valid for the given domain (and not its parent or
 * child domains.)
 * @property {Boolean=} [session] Indicates whether this is a Session Cookie. (A transient cookie, which is deleted at
 * the end of an HTTP session.)
 * @property {String=} [value] The value stored in the Cookie
 * @property {Array=} [extensions] Any extra attributes that are extensions to the original Cookie specification can be
 * specified here.
 * @property {String} [extensions[].key] Name of the extension.
 * @property {String} [extensions[].value] Value of the extension
 *
 * @example
JSON definition of an example collection

 * {
 *     name: 'my-cookie-name',
 *     expires: '1464769543832', // UNIX timestamp, in *milliseconds*
 *     maxAge: '300'  // In seconds. In this case, the Cookie is valid for 5 minutes
 *     domain: 'something.example.com',
 *     path: '/',
 *     secure: false,
 *     httpOnly: true,
 *     session: false,
 *     value: 'my-cookie-value',
 *     extensions: [{
 *         key: 'Priority',
 *         value: 'HIGH'
 *     }]
 * }
 */
_.inherit((

    /**
     * A Postman Cookie definition that comprehensively represents an HTTP Cookie.
     * @constructor
     * @extends {PropertyBase}
     *
     * @param {Cookie~definition} [options] Pass the initial definition of the Cookie.
     * @example
Create a new Cookie

     * var Cookie = require('postman-collection').Cookie,
     *     myCookie = new Cookie({
     *          name: 'my-cookie-name',
     *          expires: '1464769543832', // UNIX timestamp, in *milliseconds*
     *          maxAge: '300'  // In seconds. In this case, the Cookie is valid for 5 minutes
     *          domain: 'something.example.com',
     *          path: '/',
     *          secure: false,
     *          httpOnly: true,
     *          session: false,
     *          value: 'my-cookie-value',
     *          extensions: [{
     *              key: 'Priority',
     *              value: 'HIGH'
     *          }]
     *     });
     *
     * @example
Parse a Cookie Header

     * var Cookie = require('postman-collection').Cookie,
     *     rawHeader = 'myCookie=myValue;Path=/;Expires=Sun, 04-Feb-2018 14:18:27 GMT;Secure;HttpOnly;Priority=HIGH'
     *     myCookie = new Cookie(rawHeader);
     *
     * console.log(myCookie.toJSON());
     */
    Cookie = function PostmanCookie (options) {
        // this constructor is intended to inherit and as such the super constructor is required to be executed
        Cookie.super_.call(this, options);
        if (!options) { return; } // in case definition object is missing, there is no point moving forward

        _.isString(options) && (options = Cookie.parse(options));

        this.update(options);
    }), PropertyBase);

_.assign(Cookie.prototype, /** @lends Cookie.prototype */ {
    update: function (options) {
        _.assign(this, /** @lends Cookie.prototype */ {
            /**
             * The name of the cookie.
             * @type {String}
             */
            name: options.name,

            /**
             * Expires sets an expiry date for when a cookie gets deleted. It should either be a date object or
             * timestamp string of date.
             * @type {Date|String}
             *
             * @note
             * The value for this option is a date in the format Wdy, DD-Mon-YYYY HH:MM:SS GMT such as
             * "Sat, 02 May 2009 23:38:25 GMT". Without the expires option, a cookie has a lifespan of a single session.
             * A session is defined as finished when the browser is shut down, so session cookies exist only while the
             * browser remains open. If the expires option is set to a date that appears in the past, then the cookie is
             * immediately deleted in browser.
             *
             * @todo Accept date object and convert stringified date (timestamp only) to date object
             */
            expires: _.isString(options.expires) ? new Date(options.expires) : options.expires,

            /**
             * Max-age sets the time in seconds for when a cookie will be deleted.
             * @type {Number}
             */
            maxAge: _.has(options, 'maxAge') ? Number(options.maxAge) : undefined,

            /**
             * Indicates the domain(s) for which the cookie should be sent.
             * @type {String}
             *
             * @note
             * By default, domain is set to the host name of the page setting the cookie, so the cookie value is sent
             * whenever a request is made to the same host name. The value set for the domain option must be part of the
             * host name that is sending the Set-Cookie header. The SDK does not perform this check, but the underlying
             * client that actually sends the request could do it automatically.
             */
            domain: options.domain,

            /**
             * @type {String}
             *
             * @note
             * On server, the default value for the path option is the path of the URL that sent the Set-Cookie header.
             */
            path: options.path,

            /**
             * A secure cookie will only be sent to the server when a request is made using SSL and the HTTPS protocol.
             * The idea that the contents of the cookie are of high value and could be potentially damaging to transmit
             * as clear text.
             * @type: {Boolean}
             */
            secure: _.has(options, 'secure') ? Boolean(options.secure) : undefined,

            /**
             * The idea behind HTTP-only cookies is to instruct a browser that a cookie should never be accessible via
             * JavaScript through the document.cookie property. This feature was designed as a security measure to help
             * prevent cross-site scripting (XSS) attacks perpetrated by stealing cookies via JavaScript.
             * @type: {Boolean}
             */
            httpOnly: _.has(options, 'httpOnly') ? Boolean(options.httpOnly) : undefined,

            /**
             * @type: {Boolean}
             */
            hostOnly: _.has(options, 'hostOnly') ? Boolean(options.hostOnly) : undefined,

            /**
             * Indicates whether this is a Session Cookie.
             * @type: {Boolean}
             */
            session: _.has(options, 'session') ? Boolean(options.session) : undefined,

            /**
             * @note The commonly held belief is that cookie values must be URL-encoded, but this is a fallacy even
             * though it is the de facto implementation. The original specification indicates that only three types of
             * characters must be encoded: semicolon, comma, and white space. The specification indicates that URL
             * encoding may be used but stops short of requiring it. The RFC makes no mention of encoding whatsoever.
             * Still, almost all implementations perform some sort of URL encoding on cookie values.
             * @type {String}
             */
            value: options.value ? _.ensureEncoded(options.value) : undefined,

            /**
             * Any extra parameters that are not strictly a part of the Cookie spec go here.
             * @type {Array}
             */
            extensions: options.extensions || undefined
        });
    }
});

_.assign(Cookie, /** @lends Cookie */ {

    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'Cookie',

    /**
     * Cookie header parser
     *
     * @param str
     * @returns {*} A plain cookie options object, use it to create a new Cookie
     */
    parse: function (str) {
        if (!_.isString(str)) {
            return str;
        }

        var obj = {},
            pairs = str.split(PAIR_SPLIT_REGEX),
            nameval;

        nameval = Cookie.splitParam(pairs.shift()); // The first kvp is the name and value
        obj.name = nameval.key;
        obj.value = nameval.value;

        pairs.forEach(function (pair) {
            var keyval = Cookie.splitParam(pair),
                value = keyval.value,
                keyLower = keyval.key.toLowerCase();

            if (cookieAttributes[keyLower]) {
                obj[cookieAttributes[keyLower]] = value;
            }
            else {
                obj.extensions = obj.extensions || [];
                obj.extensions.push(keyval);
            }
        });
        // Handle the hostOnly flag
        if (!obj.domain) {
            obj.hostOnly = true;
        }
        return obj;
    },

    /**
     * Splits a Cookie parameter into a key and a value
     *
     * @private
     * @param param
     * @returns {{key: *, value: (boolean|*)}}
     */
    splitParam: function (param) {
        var split = param.split('='),
            key, value;
        key = split[0].trim();
        value = (split[1]) ? split[1].trim() : true;

        if (_.isString(value) && value[0] === '"') {
            value = value.slice(1, -1);
        }

        return { key: key, value: value };
    }
});

module.exports = {
    Cookie: Cookie
};
<commit_msg>rename 'name' to 'key' to make our cookie compatible with tough cookie<commit_after>var _ = require('../util').lodash,
    PropertyBase = require('./property-base').PropertyBase,

    Cookie,

    PAIR_SPLIT_REGEX = /; */,

    /**
     * Enum for all the Cookie attributes.
     * @private
     * @readonly
     * @enum {string} CookieAttributes
     */
    cookieAttributes = {
        httponly: 'httpOnly',
        secure: 'secure',
        domain: 'domain',
        path: 'path',
        'max-age': 'maxAge',
        session: 'session',
        expires: 'expires'
    };

/**
 * The following is the object structure accepted as constructor parameter while calling `new Cookie(...)`. It is
 * also the structure exported when {@link Property#toJSON} or {@link Property#toObjectResolved} is called on a
 * Cookie instance.
 * @typedef Cookie~definition
 *
 * @property {String=} [key] The name of the cookie. Some call it the "name".
 * @property {String=} [value] The value stored in the Cookie
 * @property {String=} [expires] Expires sets an expiry date for when a coo0kie gets deleted. It should either be a
 * date object or timestamp string of date.
 * @property {Number=} [maxAge] Max-age sets the time in seconds for when a cookie will be deleted.
 * @property {String=} [domain] Indicates the domain(s) for which the cookie should be sent.
 * @property {String=} [path] Limits the scope of the cookie to a specified path, e.g: "/accounts"
 * @property {Boolean=} [secure] A secure cookie will only be sent to the server when a request is made using SSL and
 * the HTTPS protocol.
 * The idea that the contents of the cookie are of high value and could be potentially damaging to transmit
 * as clear text.
 * @property {Boolean=} [httpOnly] The idea behind HTTP-only cookies is to instruct a browser that a cookie should never
 * be accessible via JavaScript through the document.cookie property. This feature was designed as a security measure
 * to help prevent cross-site scripting (XSS) attacks perpetrated by stealing cookies via JavaScript.
 * @property {Boolean=} [hostOnly] Indicates that this cookie is only valid for the given domain (and not its parent or
 * child domains.)
 * @property {Boolean=} [session] Indicates whether this is a Session Cookie. (A transient cookie, which is deleted at
 * the end of an HTTP session.)
 * @property {Array=} [extensions] Any extra attributes that are extensions to the original Cookie specification can be
 * specified here.
 * @property {String} [extensions[].key] Name of the extension.
 * @property {String} [extensions[].value] Value of the extension
 *
 * @example
JSON definition of an example collection

 * {
 *     key: 'my-cookie-name',
 *     expires: '1464769543832', // UNIX timestamp, in *milliseconds*
 *     maxAge: '300'  // In seconds. In this case, the Cookie is valid for 5 minutes
 *     domain: 'something.example.com',
 *     path: '/',
 *     secure: false,
 *     httpOnly: true,
 *     session: false,
 *     value: 'my-cookie-value',
 *     extensions: [{
 *         key: 'Priority',
 *         value: 'HIGH'
 *     }]
 * }
 */
_.inherit((

    /**
     * A Postman Cookie definition that comprehensively represents an HTTP Cookie.
     * @constructor
     * @extends {PropertyBase}
     *
     * @param {Cookie~definition} [options] Pass the initial definition of the Cookie.
     * @example
Create a new Cookie

     * var Cookie = require('postman-collection').Cookie,
     *     myCookie = new Cookie({
     *          name: 'my-cookie-name',
     *          expires: '1464769543832', // UNIX timestamp, in *milliseconds*
     *          maxAge: '300'  // In seconds. In this case, the Cookie is valid for 5 minutes
     *          domain: 'something.example.com',
     *          path: '/',
     *          secure: false,
     *          httpOnly: true,
     *          session: false,
     *          value: 'my-cookie-value',
     *          extensions: [{
     *              key: 'Priority',
     *              value: 'HIGH'
     *          }]
     *     });
     *
     * @example
Parse a Cookie Header

     * var Cookie = require('postman-collection').Cookie,
     *     rawHeader = 'myCookie=myValue;Path=/;Expires=Sun, 04-Feb-2018 14:18:27 GMT;Secure;HttpOnly;Priority=HIGH'
     *     myCookie = new Cookie(rawHeader);
     *
     * console.log(myCookie.toJSON());
     */
    Cookie = function PostmanCookie (options) {
        // this constructor is intended to inherit and as such the super constructor is required to be executed
        Cookie.super_.call(this, options);
        if (!options) { return; } // in case definition object is missing, there is no point moving forward

        _.isString(options) && (options = Cookie.parse(options));

        this.update(options);
    }), PropertyBase);

_.assign(Cookie.prototype, /** @lends Cookie.prototype */ {
    update: function (options) {
        _.assign(this, /** @lends Cookie.prototype */ {
            /**
             * The name of the cookie.
             * @type {String}
             */
            key: options.key,

            /**
             * Expires sets an expiry date for when a cookie gets deleted. It should either be a date object or
             * timestamp string of date.
             * @type {Date|String}
             *
             * @note
             * The value for this option is a date in the format Wdy, DD-Mon-YYYY HH:MM:SS GMT such as
             * "Sat, 02 May 2009 23:38:25 GMT". Without the expires option, a cookie has a lifespan of a single session.
             * A session is defined as finished when the browser is shut down, so session cookies exist only while the
             * browser remains open. If the expires option is set to a date that appears in the past, then the cookie is
             * immediately deleted in browser.
             *
             * @todo Accept date object and convert stringified date (timestamp only) to date object
             */
            expires: _.isString(options.expires) ? new Date(options.expires) : options.expires,

            /**
             * Max-age sets the time in seconds for when a cookie will be deleted.
             * @type {Number}
             */
            maxAge: _.has(options, 'maxAge') ? Number(options.maxAge) : undefined,

            /**
             * Indicates the domain(s) for which the cookie should be sent.
             * @type {String}
             *
             * @note
             * By default, domain is set to the host name of the page setting the cookie, so the cookie value is sent
             * whenever a request is made to the same host name. The value set for the domain option must be part of the
             * host name that is sending the Set-Cookie header. The SDK does not perform this check, but the underlying
             * client that actually sends the request could do it automatically.
             */
            domain: options.domain,

            /**
             * @type {String}
             *
             * @note
             * On server, the default value for the path option is the path of the URL that sent the Set-Cookie header.
             */
            path: options.path,

            /**
             * A secure cookie will only be sent to the server when a request is made using SSL and the HTTPS protocol.
             * The idea that the contents of the cookie are of high value and could be potentially damaging to transmit
             * as clear text.
             * @type: {Boolean}
             */
            secure: _.has(options, 'secure') ? Boolean(options.secure) : undefined,

            /**
             * The idea behind HTTP-only cookies is to instruct a browser that a cookie should never be accessible via
             * JavaScript through the document.cookie property. This feature was designed as a security measure to help
             * prevent cross-site scripting (XSS) attacks perpetrated by stealing cookies via JavaScript.
             * @type: {Boolean}
             */
            httpOnly: _.has(options, 'httpOnly') ? Boolean(options.httpOnly) : undefined,

            /**
             * @type: {Boolean}
             */
            hostOnly: _.has(options, 'hostOnly') ? Boolean(options.hostOnly) : undefined,

            /**
             * Indicates whether this is a Session Cookie.
             * @type: {Boolean}
             */
            session: _.has(options, 'session') ? Boolean(options.session) : undefined,

            /**
             * @note The commonly held belief is that cookie values must be URL-encoded, but this is a fallacy even
             * though it is the de facto implementation. The original specification indicates that only three types of
             * characters must be encoded: semicolon, comma, and white space. The specification indicates that URL
             * encoding may be used but stops short of requiring it. The RFC makes no mention of encoding whatsoever.
             * Still, almost all implementations perform some sort of URL encoding on cookie values.
             * @type {String}
             */
            value: options.value ? _.ensureEncoded(options.value) : undefined,

            /**
             * Any extra parameters that are not strictly a part of the Cookie spec go here.
             * @type {Array}
             */
            extensions: options.extensions || undefined
        });
    }
});

_.assign(Cookie, /** @lends Cookie */ {

    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'Cookie',

    /**
     * Cookie header parser
     *
     * @param str
     * @returns {*} A plain cookie options object, use it to create a new Cookie
     */
    parse: function (str) {
        if (!_.isString(str)) {
            return str;
        }

        var obj = {},
            pairs = str.split(PAIR_SPLIT_REGEX),
            nameval;

        nameval = Cookie.splitParam(pairs.shift()); // The first kvp is the name and value
        obj.key = nameval.key;
        obj.value = nameval.value;

        pairs.forEach(function (pair) {
            var keyval = Cookie.splitParam(pair),
                value = keyval.value,
                keyLower = keyval.key.toLowerCase();

            if (cookieAttributes[keyLower]) {
                obj[cookieAttributes[keyLower]] = value;
            }
            else {
                obj.extensions = obj.extensions || [];
                obj.extensions.push(keyval);
            }
        });
        // Handle the hostOnly flag
        if (!obj.domain) {
            obj.hostOnly = true;
        }
        return obj;
    },

    /**
     * Splits a Cookie parameter into a key and a value
     *
     * @private
     * @param param
     * @returns {{key: *, value: (boolean|*)}}
     */
    splitParam: function (param) {
        var split = param.split('='),
            key, value;
        key = split[0].trim();
        value = (split[1]) ? split[1].trim() : true;

        if (_.isString(value) && value[0] === '"') {
            value = value.slice(1, -1);
        }

        return { key: key, value: value };
    }
});

module.exports = {
    Cookie: Cookie
};
<|endoftext|>


<commit_before>Posts = new Mongo.Collection('posts');
import {
  check
} from 'meteor/check';

Posts.allow({
  update: function(userId, post) {
    return ownsDocument(userId, post);
  },
  remove: function(userId, post) {
    return ownsDocument(userId, post);
  }
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String,
    });
    // Recherche d'un doublon
    // Attention l'ordre est important
    // Il faut que le return soit avant l'insert
    var postWithSameLink = Posts.findOne({
      url: postAttributes.url,
    });
    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      }
    }
    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.username,
      submitted: new Date()
    });
    var postId = Posts.insert(post);
    return {
      _id: postId
    };
  }
})<commit_msg>Commit 8-3 Accepter le changement de seulement certain champs<commit_after>Posts = new Mongo.Collection('posts');
import {
  check
} from 'meteor/check';

Posts.allow({
  update: function(userId, post) {
    return ownsDocument(userId, post);
  },
  remove: function(userId, post) {
    return ownsDocument(userId, post);
  }
});
Posts.deny({
  update: function(userId, post, fieldNames) {
    // may only edit the following two fields:
    return (_.without(fieldNames, 'url', 'title').length > 0);
  }
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String,
    });
    // Recherche d'un doublon
    // Attention l'ordre est important
    // Il faut que le return soit avant l'insert
    var postWithSameLink = Posts.findOne({
      url: postAttributes.url,
    });
    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      }
    }
    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.username,
      submitted: new Date()
    });
    var postId = Posts.insert(post);
    return {
      _id: postId
    };
  }
})<|endoftext|>