<commit_before>// Add editor instance to 'N' & emit event for plugins
//
'use strict';

const CodeMirror = require('codemirror');
const _          = require('lodash');
const bag        = require('bagjs');
const RpcCache   = require('./_lib/rpc_cache')(N);

// Require markdown highlighter (mode) for CodeMirror
require('codemirror/mode/markdown/markdown');

const TEXT_MARGIN = 5;
const TOOLBAR = '$$ JSON.stringify(N.config.mdedit) $$';
const EMOJIS = '$$ JSON.stringify(N.config.parser.emojis) $$';
const DRAFTS_EXPIRE = 7 * 24 * 60 * 60; // 7 days

// Compile toolbar config
//
let compileToolbarConfig = _.memoize(function (name) {
  let buttonName;

  return _.reduce(TOOLBAR[name], function (result, buttonParams, key) {
    if (!buttonParams) {
      return result;
    }

    buttonName = key.indexOf('separator') === 0 ? 'separator' : key;

    if (buttonParams === true) {
      result.push(TOOLBAR.buttons[buttonName]);
    } else {
      result.push(_.defaults({}, buttonParams, TOOLBAR.buttons[buttonName]));
    }

    return result;
  }, []).sort((a, b) => a.priority - b.priority);
});

// Editor init
//
function MDEdit() {
  this.emojis = EMOJIS;
  this.commands = {};
  this.__attachments__ = [];
  this.__options__ = null;
  this.__layout__ = null;
  this.__minHeight__ = 0;
  this.__cm__ = null;
  this.__bag__ = bag({ prefix: 'nodeca' });
  this.__cache__ = new RpcCache();

  this.__cache__.on('update', () => N.wire.emit('mdedit:update.text'));
}

// Create new layout and show
//
// Options:
//
// - parseOptions (Object) - optional, object with plugins config like
//   `{ images: true, links: true, attachments: false }`, default `{}`
// - text (String) - optional, text, default empty string. Can be overwritten by draft
// - attachments (Array) - optional, attachments, default empty array. Can be overwritten by draft
// - toolbar (String) - optional, name of toolbar config, default `default`
// - draftKey (String) - optional, unique key to store draft, don't use drafts by default
// - draftCustomFields (Object) - optional, custom fields to store in draft:
//   ```
//   {
//     // Could be a selector
//     '.topic-create__title': 'input',
//
//     // Or get/set function
//     to: value => {
//       if (!value) /* return value; */
//       /* set value */
//     }
//   }
//   ```
//
// returns jQuery object
//
// Events:
//
// - `show.nd.mdedit` - before editor shown (when animation start)
// - `shown.nd.mdedit` - on editor shown
// - `hide.nd.mdedit` - before editor hide (when animation start)
// - `hidden.nd.mdedit` - on editor hide
// - `submit.nd.mdedit` - on done button press (if you want to prevent editor closing - call `event.preventDefault()`)
// - `change.nd.mdedit` - on update preview, you can save drafts on this event
//
MDEdit.prototype.show = function (options) {
  let $oldLayout = this.__layout__;

  this.__layout__ = $(N.runtime.render('mdedit'));
  this.__options__ = _.clone(options);
  this.__options__.toolbar = compileToolbarConfig(this.__options__.toolbar || 'default');
  this.__options__.parseOptions = this.__options__.parseOptions || {};
  this.__options__.draftCustomFields = this.__options__.draftCustomFields || {};

  $('body').append(this.__layout__);

  // Clamp editor height
  $(window).off('resize.nd.mdedit').on('resize.nd.mdedit', _.debounce(() => {
    let winHeight = $(window).height();

    if (this.__layout__.height() > winHeight && winHeight >= this.__minHeight__) {
      this.__layout__.height(winHeight);
      this.__cm__.setSize('100%', this.__layout__.find('.mdedit__edit-area').height());
    }
  }, 50, { maxWait: 50 }));

  // Init CodeMirror instance
  this.__cm__ = new CodeMirror(this.__layout__.find('.mdedit__edit-area').get(0), {
    cursorScrollMargin: TEXT_MARGIN,
    lineWrapping: true,
    lineNumbers: false,
    tabindex: 2,
    mode: 'markdown'
  });

  // Set initial CodeMirror options
  this.__cm__.setOption('extraKeys', {
    Esc:          () => N.wire.emit('mdedit.cancel'),
    'Ctrl-Enter': () => N.wire.emit('mdedit.submit')
  });

  this.__cm__.on('change', () => N.wire.emit('mdedit:update.text'));

  N.wire.emit('mdedit:init');

  this.text(options.text || '');
  this.attachments(options.attachments || []);

  // Get editor height from localstore
  this.__bag__.get('height', (__, height) => {

    if (height) {
      // If no prevoius editor - set `bottom` for animation
      if (!$oldLayout) {
        this.__layout__.css({ bottom: -height });
      }

      // Restore prevoius editor height
      this.__layout__.height(height);
    }

    this.__layout__.trigger('show');

    // If no prevoius editor - animate editor from bottom viewport botder
    this.__layout__.animate({ bottom: 0 }, $oldLayout ? 0 : 'fast', () => {
      // Update codemirror height
      this.__cm__.setSize('100%', this.__layout__.find('.mdedit__edit-area').height());

      let $focusItem = this.__layout__.find('[tabindex=1]');

      if ($focusItem.length !== 0) {
        // Focus to element with tabindex = 1 if exists
        $focusItem.focus();
      } else {
        // Or focus to editor window
        this.__cm__.focus();
      }

      // Hide previous editor
      if ($oldLayout) {
        $oldLayout.trigger('hide');
        $oldLayout.trigger('hidden');
        $oldLayout.remove();
      }

      this.__layout__.trigger('shown');
    });
  });

  // Load draft if needed
  //
  if (this.__options__.draftKey) {
    this.__bag__.get('mdedit_' + this.__options__.draftKey, (__, res) => {
      let draft = res || {};

      // Load custom fields
      Object.keys(this.__options__.draftCustomFields).forEach(fieldName => {
        if (!draft[fieldName]) return; // continue

        let fieldType = this.__options__.draftCustomFields[fieldName];

        if (fieldType === 'input') {
          $(fieldName).val(draft[fieldName]);
        } else {
          fieldType(draft[fieldName]);
        }
      });

      // Load text
      this.text(draft.text || options.text || '');

      // Check and load attachments
      if (draft.attachments && draft.attachments.length) {
        let checkParams = { media_ids: _.map(draft.attachments, 'media_id') };

        N.io.rpc('common.attachments_check', checkParams).then(res => {
          let attachments = draft.attachments.filter(attach => res.media_ids.indexOf(attach.media_id) !== -1);

          this.attachments(attachments || []);
        });
      } else {
        this.attachments(options.attachments || []);
      }
    });

  } else {
    // If we don't use drafts
    this.text(options.text || '');
    this.attachments(options.attachments || []);
  }

  // Save draft on change
  //
  if (this.__options__.draftKey) {
    this.__layout__.on('change.nd.mdedit', () => {
      let draft = {
        text: this.text(),
        attachments: this.attachments()
      };

      // Store custom fields
      Object.keys(this.__options__.draftCustomFields).forEach(fieldName => {
        let fieldType = this.__options__.draftCustomFields[fieldName];

        if (fieldType === 'input') {
          draft[fieldName] = $(fieldName).val();
        } else {
          draft[fieldName] = fieldType();
        }
      });

      this.__bag__.set('mdedit_' + this.__options__.draftKey, draft, DRAFTS_EXPIRE)
        .catch(() => {}); // Suppress storage errors
    });
  }

  return this.__layout__;
};

// Hide editor
//
// - options (Object)
//   - removeDraft (Boolean) - optional, remove draft after hide, default `false`
//
MDEdit.prototype.hide = function (options) {
  let $layout = this.__layout__;

  if (!$layout) return;

  $(window).off('resize.nd.mdedit');

  // Remove draft if needed
  if ((options || {}).removeDraft && this.__options__.draftKey) {
    this.__bag__.remove('mdedit_' + this.__options__.draftKey)
      .catch(() => {}); // Suppress storage errors
  }

  setTimeout(() => {
    $layout.trigger('hide');
    $layout.animate({ bottom: -$layout.height() }, 'fast', () => {
      this.__layout__ = null;
      $layout.trigger('hidden');
      $layout.remove();
    });
  }, 0);
};

// Get/set text
//
MDEdit.prototype.text = function (text) {
  if (!text) return this.__cm__.getValue();

  this.__cm__.setValue(text);
  this.__cm__.setCursor(this.__cm__.lineCount(), 0);

  N.wire.emit('mdedit:update.text');
};

// Get/set attachments
//
MDEdit.prototype.attachments = function (attachments) {
  if (!attachments) return this.__attachments__;

  this.__attachments__ = attachments;

  if (this.__attachments__.length === 0) {
    this.__layout__.addClass('mdedit__m-no-attachments');
  } else {
    this.__layout__.removeClass('mdedit__m-no-attachments');
  }

  N.wire.emit('mdedit:update.attachments');
};

// Get/set parse options
//
MDEdit.prototype.parseOptions = function (parseOptions) {
  if (!parseOptions) return this.__options__.parseOptions;

  this.__options__.parseOptions = parseOptions;

  N.wire.emit('mdedit:update.options');
};

// Add editor resize handler
//
N.wire.on('mdedit:init', function initResize() {
  let $body = $('body');
  let $window = $(window);
  let winHeight = $window.height();

  // load min-height limit & reset it to enable animation
  N.MDEdit.__minHeight__ = parseInt(N.MDEdit.__layout__.css('minHeight'), 10);
  N.MDEdit.__layout__.css('minHeight', 0);

  N.MDEdit.__layout__.height(N.MDEdit.__layout__.height());

  if (N.MDEdit.__layout__.height() > winHeight && winHeight >= N.MDEdit.__minHeight__) {
    N.MDEdit.__layout__.height(winHeight);
    N.MDEdit.__cm__.setSize('100%', N.MDEdit.__layout__.find('.mdedit__edit-area').height());
  }

  N.MDEdit.__layout__.find('.mdedit__resizer').on('mousedown touchstart', function (event) {
    let clickStart = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
    let currentHeight = parseInt(N.MDEdit.__layout__.height(), 10);

    N.MDEdit.__layout__.addClass('mdedit__m-resizing');

    $body
      .on('mouseup.nd.mdedit touchend.nd.mdedit', function () {
        $body.off('.nd.mdedit');
        N.MDEdit.__layout__.removeClass('mdedit__m-resizing');
      })
      .on('mousemove.nd.mdedit touchmove.nd.mdedit', _.debounce(function (event) {
        let point = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
            newHeight = currentHeight - (point.pageY - clickStart.pageY),
            winHeight = $window.height();

        newHeight = newHeight > winHeight ? winHeight : newHeight;
        newHeight = newHeight < N.MDEdit.__minHeight__ ? N.MDEdit.__minHeight__ : newHeight;

        N.MDEdit.__bag__.set('height', newHeight);
        N.MDEdit.__layout__.height(newHeight);
        N.MDEdit.__cm__.setSize('100%', N.MDEdit.__layout__.find('.mdedit__edit-area').height());
      }, 20, { maxWait: 20 }));

    return false;
  });
});

// Done handler
//
N.wire.on('mdedit.submit', function done_click() {
  if (N.MDEdit.__layout__.find('.mdedit__submit').hasClass('disabled')) {
    return;
  }

  let event = new $.Event('submit');

  N.MDEdit.__layout__.trigger(event);

  if (!event.isDefaultPrevented()) {
    N.MDEdit.hide();
  }
});

// Hide when escape key is pressed
//
N.wire.on('event.keypress.escape', () => N.MDEdit.hide());

// Hide on cancel
//
N.wire.on('mdedit.cancel', () => N.MDEdit.hide());

// Collapse/expand editor
//
N.wire.on('mdedit.collapse', function collapse() {
  let $layout = N.MDEdit.__layout__;

  // Expand
  if ($layout.hasClass('mdedit__m-collapsed')) {
    $layout.removeClass('mdedit__m-collapsed');

  // Collapse
  } else {
    $layout.addClass('mdedit__m-collapsed');
  }
});

// Add editor instance to 'N' & emit event for plugins
//
N.wire.once('init:assets', function (__, callback) {
  N.MDEdit = new MDEdit();

  N.wire.emit('init:mdedit', {}, callback);
});
<commit_msg>bagjs: use promise & suppress possible errors<commit_after>// Add editor instance to 'N' & emit event for plugins
//
'use strict';

const CodeMirror = require('codemirror');
const _          = require('lodash');
const bag        = require('bagjs');
const RpcCache   = require('./_lib/rpc_cache')(N);

// Require markdown highlighter (mode) for CodeMirror
require('codemirror/mode/markdown/markdown');

const TEXT_MARGIN = 5;
const TOOLBAR = '$$ JSON.stringify(N.config.mdedit) $$';
const EMOJIS = '$$ JSON.stringify(N.config.parser.emojis) $$';
const DRAFTS_EXPIRE = 7 * 24 * 60 * 60; // 7 days

// Compile toolbar config
//
let compileToolbarConfig = _.memoize(function (name) {
  let buttonName;

  return _.reduce(TOOLBAR[name], function (result, buttonParams, key) {
    if (!buttonParams) {
      return result;
    }

    buttonName = key.indexOf('separator') === 0 ? 'separator' : key;

    if (buttonParams === true) {
      result.push(TOOLBAR.buttons[buttonName]);
    } else {
      result.push(_.defaults({}, buttonParams, TOOLBAR.buttons[buttonName]));
    }

    return result;
  }, []).sort((a, b) => a.priority - b.priority);
});

// Editor init
//
function MDEdit() {
  this.emojis = EMOJIS;
  this.commands = {};
  this.__attachments__ = [];
  this.__options__ = null;
  this.__layout__ = null;
  this.__minHeight__ = 0;
  this.__cm__ = null;
  this.__bag__ = bag({ prefix: 'nodeca' });
  this.__cache__ = new RpcCache();

  this.__cache__.on('update', () => N.wire.emit('mdedit:update.text'));
}

// Create new layout and show
//
// Options:
//
// - parseOptions (Object) - optional, object with plugins config like
//   `{ images: true, links: true, attachments: false }`, default `{}`
// - text (String) - optional, text, default empty string. Can be overwritten by draft
// - attachments (Array) - optional, attachments, default empty array. Can be overwritten by draft
// - toolbar (String) - optional, name of toolbar config, default `default`
// - draftKey (String) - optional, unique key to store draft, don't use drafts by default
// - draftCustomFields (Object) - optional, custom fields to store in draft:
//   ```
//   {
//     // Could be a selector
//     '.topic-create__title': 'input',
//
//     // Or get/set function
//     to: value => {
//       if (!value) /* return value; */
//       /* set value */
//     }
//   }
//   ```
//
// returns jQuery object
//
// Events:
//
// - `show.nd.mdedit` - before editor shown (when animation start)
// - `shown.nd.mdedit` - on editor shown
// - `hide.nd.mdedit` - before editor hide (when animation start)
// - `hidden.nd.mdedit` - on editor hide
// - `submit.nd.mdedit` - on done button press (if you want to prevent editor closing - call `event.preventDefault()`)
// - `change.nd.mdedit` - on update preview, you can save drafts on this event
//
MDEdit.prototype.show = function (options) {
  let $oldLayout = this.__layout__;

  this.__layout__ = $(N.runtime.render('mdedit'));
  this.__options__ = _.clone(options);
  this.__options__.toolbar = compileToolbarConfig(this.__options__.toolbar || 'default');
  this.__options__.parseOptions = this.__options__.parseOptions || {};
  this.__options__.draftCustomFields = this.__options__.draftCustomFields || {};

  $('body').append(this.__layout__);

  // Clamp editor height
  $(window).off('resize.nd.mdedit').on('resize.nd.mdedit', _.debounce(() => {
    let winHeight = $(window).height();

    if (this.__layout__.height() > winHeight && winHeight >= this.__minHeight__) {
      this.__layout__.height(winHeight);
      this.__cm__.setSize('100%', this.__layout__.find('.mdedit__edit-area').height());
    }
  }, 50, { maxWait: 50 }));

  // Init CodeMirror instance
  this.__cm__ = new CodeMirror(this.__layout__.find('.mdedit__edit-area').get(0), {
    cursorScrollMargin: TEXT_MARGIN,
    lineWrapping: true,
    lineNumbers: false,
    tabindex: 2,
    mode: 'markdown'
  });

  // Set initial CodeMirror options
  this.__cm__.setOption('extraKeys', {
    Esc:          () => N.wire.emit('mdedit.cancel'),
    'Ctrl-Enter': () => N.wire.emit('mdedit.submit')
  });

  this.__cm__.on('change', () => N.wire.emit('mdedit:update.text'));

  N.wire.emit('mdedit:init');

  this.text(options.text || '');
  this.attachments(options.attachments || []);

  // Get editor height from localstore
  this.__bag__.get('height').catch(() => 0).then(height => {

    if (height) {
      // If no prevoius editor - set `bottom` for animation
      if (!$oldLayout) {
        this.__layout__.css({ bottom: -height });
      }

      // Restore prevoius editor height
      this.__layout__.height(height);
    }

    this.__layout__.trigger('show');

    // If no prevoius editor - animate editor from bottom viewport botder
    this.__layout__.animate({ bottom: 0 }, $oldLayout ? 0 : 'fast', () => {
      // Update codemirror height
      this.__cm__.setSize('100%', this.__layout__.find('.mdedit__edit-area').height());

      let $focusItem = this.__layout__.find('[tabindex=1]');

      if ($focusItem.length !== 0) {
        // Focus to element with tabindex = 1 if exists
        $focusItem.focus();
      } else {
        // Or focus to editor window
        this.__cm__.focus();
      }

      // Hide previous editor
      if ($oldLayout) {
        $oldLayout.trigger('hide');
        $oldLayout.trigger('hidden');
        $oldLayout.remove();
      }

      this.__layout__.trigger('shown');
    });
  });

  // Load draft if needed
  //
  if (this.__options__.draftKey) {
    this.__bag__.get('mdedit_' + this.__options__.draftKey, (__, res) => {
      let draft = res || {};

      // Load custom fields
      Object.keys(this.__options__.draftCustomFields).forEach(fieldName => {
        if (!draft[fieldName]) return; // continue

        let fieldType = this.__options__.draftCustomFields[fieldName];

        if (fieldType === 'input') {
          $(fieldName).val(draft[fieldName]);
        } else {
          fieldType(draft[fieldName]);
        }
      });

      // Load text
      this.text(draft.text || options.text || '');

      // Check and load attachments
      if (draft.attachments && draft.attachments.length) {
        let checkParams = { media_ids: _.map(draft.attachments, 'media_id') };

        N.io.rpc('common.attachments_check', checkParams).then(res => {
          let attachments = draft.attachments.filter(attach => res.media_ids.indexOf(attach.media_id) !== -1);

          this.attachments(attachments || []);
        });
      } else {
        this.attachments(options.attachments || []);
      }
    });

  } else {
    // If we don't use drafts
    this.text(options.text || '');
    this.attachments(options.attachments || []);
  }

  // Save draft on change
  //
  if (this.__options__.draftKey) {
    this.__layout__.on('change.nd.mdedit', () => {
      let draft = {
        text: this.text(),
        attachments: this.attachments()
      };

      // Store custom fields
      Object.keys(this.__options__.draftCustomFields).forEach(fieldName => {
        let fieldType = this.__options__.draftCustomFields[fieldName];

        if (fieldType === 'input') {
          draft[fieldName] = $(fieldName).val();
        } else {
          draft[fieldName] = fieldType();
        }
      });

      this.__bag__.set('mdedit_' + this.__options__.draftKey, draft, DRAFTS_EXPIRE)
        .catch(() => {}); // Suppress storage errors
    });
  }

  return this.__layout__;
};

// Hide editor
//
// - options (Object)
//   - removeDraft (Boolean) - optional, remove draft after hide, default `false`
//
MDEdit.prototype.hide = function (options) {
  let $layout = this.__layout__;

  if (!$layout) return;

  $(window).off('resize.nd.mdedit');

  // Remove draft if needed
  if ((options || {}).removeDraft && this.__options__.draftKey) {
    this.__bag__.remove('mdedit_' + this.__options__.draftKey)
      .catch(() => {}); // Suppress storage errors
  }

  setTimeout(() => {
    $layout.trigger('hide');
    $layout.animate({ bottom: -$layout.height() }, 'fast', () => {
      this.__layout__ = null;
      $layout.trigger('hidden');
      $layout.remove();
    });
  }, 0);
};

// Get/set text
//
MDEdit.prototype.text = function (text) {
  if (!text) return this.__cm__.getValue();

  this.__cm__.setValue(text);
  this.__cm__.setCursor(this.__cm__.lineCount(), 0);

  N.wire.emit('mdedit:update.text');
};

// Get/set attachments
//
MDEdit.prototype.attachments = function (attachments) {
  if (!attachments) return this.__attachments__;

  this.__attachments__ = attachments;

  if (this.__attachments__.length === 0) {
    this.__layout__.addClass('mdedit__m-no-attachments');
  } else {
    this.__layout__.removeClass('mdedit__m-no-attachments');
  }

  N.wire.emit('mdedit:update.attachments');
};

// Get/set parse options
//
MDEdit.prototype.parseOptions = function (parseOptions) {
  if (!parseOptions) return this.__options__.parseOptions;

  this.__options__.parseOptions = parseOptions;

  N.wire.emit('mdedit:update.options');
};

// Add editor resize handler
//
N.wire.on('mdedit:init', function initResize() {
  let $body = $('body');
  let $window = $(window);
  let winHeight = $window.height();

  // load min-height limit & reset it to enable animation
  N.MDEdit.__minHeight__ = parseInt(N.MDEdit.__layout__.css('minHeight'), 10);
  N.MDEdit.__layout__.css('minHeight', 0);

  N.MDEdit.__layout__.height(N.MDEdit.__layout__.height());

  if (N.MDEdit.__layout__.height() > winHeight && winHeight >= N.MDEdit.__minHeight__) {
    N.MDEdit.__layout__.height(winHeight);
    N.MDEdit.__cm__.setSize('100%', N.MDEdit.__layout__.find('.mdedit__edit-area').height());
  }

  N.MDEdit.__layout__.find('.mdedit__resizer').on('mousedown touchstart', function (event) {
    let clickStart = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
    let currentHeight = parseInt(N.MDEdit.__layout__.height(), 10);

    N.MDEdit.__layout__.addClass('mdedit__m-resizing');

    $body
      .on('mouseup.nd.mdedit touchend.nd.mdedit', function () {
        $body.off('.nd.mdedit');
        N.MDEdit.__layout__.removeClass('mdedit__m-resizing');
      })
      .on('mousemove.nd.mdedit touchmove.nd.mdedit', _.debounce(function (event) {
        let point = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
            newHeight = currentHeight - (point.pageY - clickStart.pageY),
            winHeight = $window.height();

        newHeight = newHeight > winHeight ? winHeight : newHeight;
        newHeight = newHeight < N.MDEdit.__minHeight__ ? N.MDEdit.__minHeight__ : newHeight;

        N.MDEdit.__bag__.set('height', newHeight);
        N.MDEdit.__layout__.height(newHeight);
        N.MDEdit.__cm__.setSize('100%', N.MDEdit.__layout__.find('.mdedit__edit-area').height());
      }, 20, { maxWait: 20 }));

    return false;
  });
});

// Done handler
//
N.wire.on('mdedit.submit', function done_click() {
  if (N.MDEdit.__layout__.find('.mdedit__submit').hasClass('disabled')) {
    return;
  }

  let event = new $.Event('submit');

  N.MDEdit.__layout__.trigger(event);

  if (!event.isDefaultPrevented()) {
    N.MDEdit.hide();
  }
});

// Hide when escape key is pressed
//
N.wire.on('event.keypress.escape', () => N.MDEdit.hide());

// Hide on cancel
//
N.wire.on('mdedit.cancel', () => N.MDEdit.hide());

// Collapse/expand editor
//
N.wire.on('mdedit.collapse', function collapse() {
  let $layout = N.MDEdit.__layout__;

  // Expand
  if ($layout.hasClass('mdedit__m-collapsed')) {
    $layout.removeClass('mdedit__m-collapsed');

  // Collapse
  } else {
    $layout.addClass('mdedit__m-collapsed');
  }
});

// Add editor instance to 'N' & emit event for plugins
//
N.wire.once('init:assets', function (__, callback) {
  N.MDEdit = new MDEdit();

  N.wire.emit('init:mdedit', {}, callback);
});
<|endoftext|>


<commit_before>createReactiveVars = function () {
    // Set up reactive variables to temporarily hold the values of registration form fields
    // These variables are used for dynamic calculations
    ageGroupVar = new ReactiveVar;
    registrationTypeVar = new ReactiveVar;
    accommodationsVar = new ReactiveVar;
    daysVar = new ReactiveVar;
    registrationFeeVar = new ReactiveVar;
    firstTimeAttenderVar = new ReactiveVar;
    linensVar = new ReactiveVar;
}();

resetReactiveVars = function () {
    // reset current values to undefined
    ageGroupVar.set(undefined);
    registrationTypeVar.set(undefined);
    accommodationsVar.set(undefined);
    daysVar.set(undefined);
    registrationFeeVar.set(undefined);
    linensVar.set(undefined);
}

setDaysVar = function () {
    /*
    Save selected days as a reactive variable
    for fee calculation, etc
    */

    // Create placeholder days array
    var daysArray = new Array();

    // get a list of all selected days
    $('input[name="days"]:checked').each(function() {
        daysArray.push(this.value);
    });

    // add days to reactive variable
    // used for price calculations
    daysVar.set(daysArray);
}

setReactiveVars = function () {
    resetReactiveVars();

    // Set the age group reactive variable
    // calculated based on the value of the age field
    var age = $("#age").val();
    var ageGroup = calculateAgeGroup(age);
    ageGroupVar.set(ageGroup);

    // Set the registration type reactive variable
    registrationTypeVar.set($('#registration_type').val());

    // Set the accommodations reactive variable
    accommodationsVar.set($('#accommodations').val());

    // Set the days reactive variable
    setDaysVar();

    // Set first time attender reactive variable
    var firstTimeAttenderChecked = $('#first-time-attender').is(':checked');
    firstTimeAttenderVar.set(firstTimeAttenderChecked);

    // Set linens reactive var
    var linensChecked = $('#linens').is(':checked');
    linensVar.set(linensChecked);
}

setRegistrationFeeVar = function () {
    // Create this function if necessary
    // e.g. if calculating financial aid, donations, etc
}
<commit_msg>Set age group var function. Cleanup.<commit_after>createReactiveVars = function () {
    // Set up reactive variables to temporarily hold the values of registration form fields
    // These variables are used for dynamic calculations
    ageGroupVar = new ReactiveVar;
    registrationTypeVar = new ReactiveVar;
    accommodationsVar = new ReactiveVar;
    daysVar = new ReactiveVar;
    registrationFeeVar = new ReactiveVar;
    firstTimeAttenderVar = new ReactiveVar;
    linensVar = new ReactiveVar;
}();

resetReactiveVars = function () {
    // reset current values to undefined
    ageGroupVar.set(undefined);
    registrationTypeVar.set(undefined);
    accommodationsVar.set(undefined);
    daysVar.set(undefined);
    registrationFeeVar.set(undefined);
    linensVar.set(undefined);
};

setDaysVar = function () {
    /*
    Save selected days as a reactive variable
    for fee calculation, etc
    */

    // Create placeholder days array
    var daysArray = new Array();

    // get a list of all selected days
    $('input[name="days"]:checked').each(function() {
        daysArray.push(this.value);
    });

    // add days to reactive variable
    // used for price calculations
    daysVar.set(daysArray);
};

setAgeGroupVar = function () {
    /*
     Set the age group reactive variable
     calculated based on the value of the age field
     making sure value of age is not not empty string
    */
    var age = $("#age").val();

    // Make sure age has been set
    if (age !== '') {
        var ageGroup = calculateAgeGroup(age);
        ageGroupVar.set(ageGroup);
    };
};

setReactiveVars = function () {
    // Reset all reactive variables to undefined
    resetReactiveVars();

    // Set the age group reactive variable
    setAgeGroupVar();

    // Set the registration type reactive variable
    registrationTypeVar.set($('#registration_type').val());

    // Set the accommodations reactive variable
    accommodationsVar.set($('#accommodations').val());

    // Set the days reactive variable
    setDaysVar();

    // Set first time attender reactive variable
    var firstTimeAttenderChecked = $('#first-time-attender').is(':checked');
    firstTimeAttenderVar.set(firstTimeAttenderChecked);

    // Set linens reactive var
    var linensChecked = $('#linens').is(':checked');
    linensVar.set(linensChecked);
}

setRegistrationFeeVar = function () {
    // Create this function if necessary
    // e.g. if calculating financial aid, donations, etc
}
<|endoftext|>


<commit_before>var Box = require("./math").box
var math = require("./math")
var Vector3 = math.vec3
var Plane = math.plane
var Triangle = math.triangle

// prevent too many allocations each frame
var defaultSphereShape = new Vector3(1, 1, 1)

// vel is unnormalized
var getSweptCollision = (function() {
  var newPos = new Vector3()
    , newVel = new Vector3()
    , touchPoint = new Vector3()
    , touchSpherePoint = new Vector3()
    , temp = new Vector3()
    , slidePlane = new Plane()
    , endPos = new Vector3()
    , maxIterations = 10
    , epsilon = Number.EPSILON * 2

  return function(spherePos, vel, tris, sphereShape, stick) {
    if (vel.lengthSq() < Number.EPSILON) return { position: spherePos, collision: false }
    sphereShape = sphereShape instanceof Vector3 ? sphereShape : defaultSphereShape

    var collision = false
      , hit
    newPos.copy(spherePos).divide(sphereShape)
    newVel.copy(vel).divide(sphereShape)

    for (var i = 0; i < maxIterations; i++) {
      endPos.addVectors(newPos, newVel)

      var info = getCollision(newPos, newVel, tris, sphereShape)

      if (!isFinite(info.t)) {
        hit = { position: endPos, collision: collision }
        break
      }

      collision = true
      touchPoint.copy(info.collisionPoint)
      // adding this check seems to fix some of the glitches
      if (info.t > epsilon)
        touchSpherePoint.addVectors(newPos, temp.copy(newVel).multiplyScalar(info.t))
      else
        touchSpherePoint.copy(newPos)

      var slideNormal = new Vector3().subVectors(touchSpherePoint, touchPoint).normalize()
      slidePlane.setFromNormalAndCoplanarPoint(slideNormal, touchPoint)
      if (stick) {
        hit = {
          position: newPos.copy(touchSpherePoint).add(slideNormal.multiplyScalar(epsilon)),
          collision: true
        }
        break
      }
      // Projected end point
      var endTouchPoint = new Vector3().addVectors(endPos, new Vector3().copy(slidePlane.normal).multiplyScalar(-slidePlane.distanceToPoint(endPos)))

      // Can modify
      newPos.copy(touchSpherePoint).add(slideNormal.multiplyScalar(epsilon))
      newVel.subVectors(endTouchPoint, touchPoint)
    }

    if (!hit) {
      hit = {
        position: touchSpherePoint.addVectors(newPos, newVel),
        collision: collision
      }
    }

    hit.position.multiply(sphereShape)
    return hit
  }
}())

// Returns time of impact from a swept sphere against a polygon soup
// Note that collisionPoint is point on triangle that sphere collides with and t is point it takes for sphere
// to touch so p + v*getCollision().t != getCollision().collisionPoint
var getCollision = (function() {
  var cb = new Vector3()
    , ab = new Vector3()
    , temp = new Vector3()
    , velNorm = new Vector3()
    , invVelNorm = new Vector3()
    , plane = new Plane()
    , triangle = new Triangle(new Vector3(), new Vector3(), new Vector3())

  return function(spherePos, vel, tris, sphereShape) {
    var collision = false
      , timeOfImpact = Number.POSITIVE_INFINITY
    velNorm.set(vel.x, vel.y, vel.z).normalize()
    invVelNorm.copy(velNorm).negate()

    for (var i = 0; i < tris.length; i++) {
      var original = tris[i]
        , tri = triangle

      triangle.a.copy(original.a).divide(sphereShape)
      triangle.b.copy(original.b).divide(sphereShape)
      triangle.c.copy(original.c).divide(sphereShape)

      var triCollision = false
      ab.subVectors(tri.a, tri.b).normalize()
      cb.subVectors(tri.c, tri.b).normalize()

      var normal = temp.crossVectors(cb, ab).normalize()
      plane.set(normal, -normal.dot(tri.a))

      var velDotNormal = velNorm.dot(normal)
      if (velDotNormal > Number.EPSILON) continue

      var parallel = velDotNormal <= Number.EPSILON && velDotNormal >= -Number.EPSILON
      if (parallel && plane.distanceToPoint(spherePos) >= 1 + Number.EPSILON) continue

      if (!parallel) {
        var collisions = getTCollisions(plane, spherePos, vel)
        var t0 = Math.min(collisions.t0, collisions.t1)
        var t1 = Math.max(collisions.t0, collisions.t1)

        if (t0 > 1 || t1 < 0) continue
        var tempPoint = new Vector3().addVectors(spherePos, new Vector3().copy(vel).multiplyScalar(t0).sub(plane.normal))
        if (math.isInside(tempPoint, tri) && t0 < timeOfImpact) {
          collision = triCollision = true
          timeOfImpact = t0
          collisionPoint = tempPoint
        }
      }

      if (!triCollision) {
        // Try edges and vertices if not on face
        var collisionInfos = [getTCollisionOnVertices(tri, spherePos, vel), getTCollisionOnEdges(tri, spherePos, vel)]

        for (var j = 0; j < 2; j++) {
          var info = collisionInfos[j]
          if (!isFinite(info.t) || info.t > timeOfImpact) continue

          collision = triCollision = true
          timeOfImpact = info.t
          collisionPoint = info.collisionPoint
        }
      }
    }

    return {
      collisionPoint: collisionPoint,
      t: collision ? timeOfImpact : Number.POSITIVE_INFINITY,
      collision: collision
    }
  }
}())

function getTCollisions(plane, spherePos, vel) {
  var dotVel = plane.normal.dot(vel)
  return {
    t0: (1 - plane.distanceToPoint(spherePos)) / dotVel,
    t1: (-1 - plane.distanceToPoint(spherePos)) / dotVel
  }
}

function getTCollisionOnVertices(tri, spherePos, vel) {
  var collision = false
    , collisionPoint

  var a = vel.lengthSq()
  var t = 1
  var temp = new Vector3()
  var pointToSphere = new Vector3()
  var points = [tri.a, tri.b, tri.c]

  for (var i = 0; i < 3; i++) {
    var point = points[i]
    pointToSphere.subVectors(spherePos, point)

    var b = 2 * vel.dot(pointToSphere)
    var c = pointToSphere.lengthSq() - 1

    var timeOfImpact = math.getLowestPositiveRoot(a, b, c, t)
    if (!isFinite(timeOfImpact)) continue

    t = timeOfImpact
    collision = true
    collisionPoint = point
  }

  return {
    collisionPoint: collisionPoint,
    t: collision ? t : Number.POSITIVE_INFINITY
  }
}

function getTCollisionOnEdges(tri, spherePos, vel) {
  var collision = false
    , collisionPoint = new Vector3()

  var t = 1
  var points = [tri.a, tri.b, tri.c]

  for (var i = 0; i < 3; i++) {
    var point = points[i]
    var edge = new Vector3().subVectors(points[(i + 1) % 3], points[i % 3])

    var edgeLenSq = edge.lengthSq()

    var sphereToPoint = new Vector3().subVectors(point, spherePos)

    var edgeDotVel = edge.dot(vel)
    var edgeDotSphereToTri = edge.dot(sphereToPoint)

    var a = edgeLenSq * -vel.lengthSq() + edgeDotVel * edgeDotVel
    var b = edgeLenSq * 2 * vel.dot(sphereToPoint) - 2 * edgeDotVel * edgeDotSphereToTri
    var c = edgeLenSq * (1 - sphereToPoint.lengthSq()) + edgeDotSphereToTri * edgeDotSphereToTri

    var timeOfImpact = math.getLowestPositiveRoot(a, b, c, t)
    if (!isFinite(timeOfImpact)) continue

    var f = (edgeDotVel * timeOfImpact - edgeDotSphereToTri) / edgeLenSq
    if (f < 0 || f > 1) continue

    t = timeOfImpact
    collision = true
    collisionPoint.copy(point).add(edge.multiplyScalar(f))
  }

  resultingCollisionPoint = collisionPoint

  return {
    collisionPoint: collisionPoint,
    t: collision ? t : Number.POSITIVE_INFINITY
  }
}

var getSweptBoxCollision = (function() {
  var triangles = []
    , a = new Vector3()
    , b = new Vector3()
    , c = new Vector3()
    , d = new Vector3()
    , e = new Vector3()
    , f = new Vector3()
    , g = new Vector3()
    , h = new Vector3()
    , corner = new Vector3()

  for (var i = 0; i < 12; i++) triangles.push(new Triangle(new Vector3(), new Vector3(), new Vector3()))

  return function(from, vel, shape, boxPos, boxSize, quat) {
    var width = boxSize.x
      , height = boxSize.y
      , depth = boxSize.z

    a.addVectors(boxPos, corner.set(-width, height, depth).applyQuaternion(quat))
    b.addVectors(boxPos, corner.set(-width, -height, depth).applyQuaternion(quat))
    c.addVectors(boxPos, corner.set(width, -height, depth).applyQuaternion(quat))
    d.addVectors(boxPos, corner.set(width, height, depth).applyQuaternion(quat))
    e.addVectors(boxPos, corner.set(-width, height, -depth).applyQuaternion(quat))
    f.addVectors(boxPos, corner.set(-width, -height, -depth).applyQuaternion(quat))
    g.addVectors(boxPos, corner.set(width, -height, -depth).applyQuaternion(quat))
    h.addVectors(boxPos, corner.set(width, height, -depth).applyQuaternion(quat))

    var index = 0
    triangles[index++].set(a, b, c)
    triangles[index++].set(a, c, d)
    // back
    triangles[index++].set(h, g, f)
    triangles[index++].set(h, f, e)
    // left
    triangles[index++].set(e, f, b)
    triangles[index++].set(e, b, a)
    // right
    triangles[index++].set(d, c, g)
    triangles[index++].set(d, g, h)
    // top
    triangles[index++].set(e, a, d)
    triangles[index++].set(e, d, h)
    // bottom
    triangles[index++].set(b, f, g)
    triangles[index++].set(b, g, c)

    return getSweptCollision(from, vel, triangles, shape, true)
  }
}())

module.exports = {
  getSweptCollision: getSweptCollision,
  getSweptBoxCollision: getSweptBoxCollision,
  getCollision: getCollision,

  collides: (function() {
    var defaultA = new Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
      , defaultB = new Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
      , boxA = new Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
      , boxB = Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))

    return function(a, b) {
      boxA.copy(a.box ? a.box : defaultA)
      boxB.copy(b.box ? b.box : defaultB)
      boxA.min.add(a.position)
      boxA.max.add(a.position)
      boxB.min.add(b.position)
      boxB.max.add(b.position)

      return boxA.isIntersectionBox(boxB)
    }
  }())

  collidesSwept: function collidesSwept(a, b, from, to) {
    var boxA = {
      x: from.x - 1,
      y: from.y - 1,
      z: from.z - 1,
      w: 2,
      h: 2,
      d: 2
    }
    var boxB = {
      x: b.position.x - 1,
      y: b.position.y - 1,
      z: b.position.z - 1,
      w: 2,
      h: 2,
      d: 2
    }

    var velocity = new Vector3().subVectors(from, to)
    // Inverse times
    var invEnterX, invEnterY, invEnterZ
    var invExitX, invExitY, invExitZ

    if (velocity.x > 0) {
      invEnterX = boxB.x - (boxA.x + boxA.w)
      invExitX = (boxB.x + boxB.w) - boxA.x
    }
    else {
      invEnterX = (boxB.x + boxB.w) - boxA.x
      invExitX = boxB.x - (boxA.x + boxA.w)
    }

    if (velocity.y > 0) {
      invEnterY = boxB.y - (boxA.y + boxA.h)
      invExitY = (boxB.y + boxB.h) - boxA.y
    }
    else {
      invEnterY = (boxB.y + boxB.h) - boxA.y
      invExitY = boxB.y - (boxA.y + boxA.h)
    }

    if (velocity.z > 0) {
      invEnterZ = boxB.z - (boxA.z + boxA.d)
      invExitZ = (boxB.z + boxB.d) - boxA.z
    }
    else {
      invEnterZ = (boxB.z + boxB.d) - boxA.z
      invExitZ = boxB.z - (boxA.z + boxA.d)
    }

    var entryX, entryY, entryZ
    var exitX, exitY, exitZ

    if (Math.abs(velocity.x) < Number.EPSILON) {
        entryX = Number.NEGATIVE_INFINITY
        exitX = Number.POSITIVE_INFINITY
    }
    else {
        entryX = invEnterX / velocity.x
        exitX = invExitX / velocity.x
    }

    if (Math.abs(velocity.y) < Number.EPSILON) {
        entryY = Number.NEGATIVE_INFINITY
        exitY = Number.POSITIVE_INFINITY
    }
    else {
        entryY = invEnterY / velocity.y
        exitY = invExitY / velocity.y
    }

    if (Math.abs(velocity.z) < Number.EPSILON) {
        entryZ = Number.NEGATIVE_INFINITY
        exitZ = Number.POSITIVE_INFINITY
    }
    else {
        entryZ = invEnterZ / velocity.z
        exitZ = invExitZ / velocity.z
    }

    var entry = Math.max(entryX, entryY)
    entry = Math.max(entry, entryZ)

    var exit = Math.max(exitX, exitY)
    exit = Math.max(exit, exitZ)

    if (entry > exit) return Number.POSITIVE_INFINITY
    if (entryX < 0 && entryY < 0 && entryZ < 0) return Number.POSITIVE_INFINITY
    if (entryX < 0 && (boxA.x + boxA.w < boxB.x || boxA.x > boxB.x + boxB.w)) return Number.POSITIVE_INFINITY
    if (entryY < 0 && (boxA.y + boxA.h < boxB.y || boxA.y > boxB.y + boxB.h)) return Number.POSITIVE_INFINITY
    if (entryZ < 0 && (boxA.z + boxA.d < boxB.z || boxA.z > boxB.z + boxB.d)) return Number.POSITIVE_INFINITY

    return entry
  },
}
<commit_msg>fix error<commit_after>var Box = require("./math").box
var math = require("./math")
var Vector3 = math.vec3
var Plane = math.plane
var Triangle = math.triangle

// prevent too many allocations each frame
var defaultSphereShape = new Vector3(1, 1, 1)

// vel is unnormalized
var getSweptCollision = (function() {
  var newPos = new Vector3()
    , newVel = new Vector3()
    , touchPoint = new Vector3()
    , touchSpherePoint = new Vector3()
    , temp = new Vector3()
    , slidePlane = new Plane()
    , endPos = new Vector3()
    , maxIterations = 10
    , epsilon = Number.EPSILON * 2

  return function(spherePos, vel, tris, sphereShape, stick) {
    if (vel.lengthSq() < Number.EPSILON) return { position: spherePos, collision: false }
    sphereShape = sphereShape instanceof Vector3 ? sphereShape : defaultSphereShape

    var collision = false
      , hit
    newPos.copy(spherePos).divide(sphereShape)
    newVel.copy(vel).divide(sphereShape)

    for (var i = 0; i < maxIterations; i++) {
      endPos.addVectors(newPos, newVel)

      var info = getCollision(newPos, newVel, tris, sphereShape)

      if (!isFinite(info.t)) {
        hit = { position: endPos, collision: collision }
        break
      }

      collision = true
      touchPoint.copy(info.collisionPoint)
      // adding this check seems to fix some of the glitches
      if (info.t > epsilon)
        touchSpherePoint.addVectors(newPos, temp.copy(newVel).multiplyScalar(info.t))
      else
        touchSpherePoint.copy(newPos)

      var slideNormal = new Vector3().subVectors(touchSpherePoint, touchPoint).normalize()
      slidePlane.setFromNormalAndCoplanarPoint(slideNormal, touchPoint)
      if (stick) {
        hit = {
          position: newPos.copy(touchSpherePoint).add(slideNormal.multiplyScalar(epsilon)),
          collision: true
        }
        break
      }
      // Projected end point
      var endTouchPoint = new Vector3().addVectors(endPos, new Vector3().copy(slidePlane.normal).multiplyScalar(-slidePlane.distanceToPoint(endPos)))

      // Can modify
      newPos.copy(touchSpherePoint).add(slideNormal.multiplyScalar(epsilon))
      newVel.subVectors(endTouchPoint, touchPoint)
    }

    if (!hit) {
      hit = {
        position: touchSpherePoint.addVectors(newPos, newVel),
        collision: collision
      }
    }

    hit.position.multiply(sphereShape)
    return hit
  }
}())

// Returns time of impact from a swept sphere against a polygon soup
// Note that collisionPoint is point on triangle that sphere collides with and t is point it takes for sphere
// to touch so p + v*getCollision().t != getCollision().collisionPoint
var getCollision = (function() {
  var cb = new Vector3()
    , ab = new Vector3()
    , temp = new Vector3()
    , velNorm = new Vector3()
    , invVelNorm = new Vector3()
    , plane = new Plane()
    , triangle = new Triangle(new Vector3(), new Vector3(), new Vector3())

  return function(spherePos, vel, tris, sphereShape) {
    var collision = false
      , timeOfImpact = Number.POSITIVE_INFINITY
    velNorm.set(vel.x, vel.y, vel.z).normalize()
    invVelNorm.copy(velNorm).negate()

    for (var i = 0; i < tris.length; i++) {
      var original = tris[i]
        , tri = triangle

      triangle.a.copy(original.a).divide(sphereShape)
      triangle.b.copy(original.b).divide(sphereShape)
      triangle.c.copy(original.c).divide(sphereShape)

      var triCollision = false
      ab.subVectors(tri.a, tri.b).normalize()
      cb.subVectors(tri.c, tri.b).normalize()

      var normal = temp.crossVectors(cb, ab).normalize()
      plane.set(normal, -normal.dot(tri.a))

      var velDotNormal = velNorm.dot(normal)
      if (velDotNormal > Number.EPSILON) continue

      var parallel = velDotNormal <= Number.EPSILON && velDotNormal >= -Number.EPSILON
      if (parallel && plane.distanceToPoint(spherePos) >= 1 + Number.EPSILON) continue

      if (!parallel) {
        var collisions = getTCollisions(plane, spherePos, vel)
        var t0 = Math.min(collisions.t0, collisions.t1)
        var t1 = Math.max(collisions.t0, collisions.t1)

        if (t0 > 1 || t1 < 0) continue
        var tempPoint = new Vector3().addVectors(spherePos, new Vector3().copy(vel).multiplyScalar(t0).sub(plane.normal))
        if (math.isInside(tempPoint, tri) && t0 < timeOfImpact) {
          collision = triCollision = true
          timeOfImpact = t0
          collisionPoint = tempPoint
        }
      }

      if (!triCollision) {
        // Try edges and vertices if not on face
        var collisionInfos = [getTCollisionOnVertices(tri, spherePos, vel), getTCollisionOnEdges(tri, spherePos, vel)]

        for (var j = 0; j < 2; j++) {
          var info = collisionInfos[j]
          if (!isFinite(info.t) || info.t > timeOfImpact) continue

          collision = triCollision = true
          timeOfImpact = info.t
          collisionPoint = info.collisionPoint
        }
      }
    }

    return {
      collisionPoint: collisionPoint,
      t: collision ? timeOfImpact : Number.POSITIVE_INFINITY,
      collision: collision
    }
  }
}())

function getTCollisions(plane, spherePos, vel) {
  var dotVel = plane.normal.dot(vel)
  return {
    t0: (1 - plane.distanceToPoint(spherePos)) / dotVel,
    t1: (-1 - plane.distanceToPoint(spherePos)) / dotVel
  }
}

function getTCollisionOnVertices(tri, spherePos, vel) {
  var collision = false
    , collisionPoint

  var a = vel.lengthSq()
  var t = 1
  var temp = new Vector3()
  var pointToSphere = new Vector3()
  var points = [tri.a, tri.b, tri.c]

  for (var i = 0; i < 3; i++) {
    var point = points[i]
    pointToSphere.subVectors(spherePos, point)

    var b = 2 * vel.dot(pointToSphere)
    var c = pointToSphere.lengthSq() - 1

    var timeOfImpact = math.getLowestPositiveRoot(a, b, c, t)
    if (!isFinite(timeOfImpact)) continue

    t = timeOfImpact
    collision = true
    collisionPoint = point
  }

  return {
    collisionPoint: collisionPoint,
    t: collision ? t : Number.POSITIVE_INFINITY
  }
}

function getTCollisionOnEdges(tri, spherePos, vel) {
  var collision = false
    , collisionPoint = new Vector3()

  var t = 1
  var points = [tri.a, tri.b, tri.c]

  for (var i = 0; i < 3; i++) {
    var point = points[i]
    var edge = new Vector3().subVectors(points[(i + 1) % 3], points[i % 3])

    var edgeLenSq = edge.lengthSq()

    var sphereToPoint = new Vector3().subVectors(point, spherePos)

    var edgeDotVel = edge.dot(vel)
    var edgeDotSphereToTri = edge.dot(sphereToPoint)

    var a = edgeLenSq * -vel.lengthSq() + edgeDotVel * edgeDotVel
    var b = edgeLenSq * 2 * vel.dot(sphereToPoint) - 2 * edgeDotVel * edgeDotSphereToTri
    var c = edgeLenSq * (1 - sphereToPoint.lengthSq()) + edgeDotSphereToTri * edgeDotSphereToTri

    var timeOfImpact = math.getLowestPositiveRoot(a, b, c, t)
    if (!isFinite(timeOfImpact)) continue

    var f = (edgeDotVel * timeOfImpact - edgeDotSphereToTri) / edgeLenSq
    if (f < 0 || f > 1) continue

    t = timeOfImpact
    collision = true
    collisionPoint.copy(point).add(edge.multiplyScalar(f))
  }

  resultingCollisionPoint = collisionPoint

  return {
    collisionPoint: collisionPoint,
    t: collision ? t : Number.POSITIVE_INFINITY
  }
}

var getSweptBoxCollision = (function() {
  var triangles = []
    , a = new Vector3()
    , b = new Vector3()
    , c = new Vector3()
    , d = new Vector3()
    , e = new Vector3()
    , f = new Vector3()
    , g = new Vector3()
    , h = new Vector3()
    , corner = new Vector3()

  for (var i = 0; i < 12; i++) triangles.push(new Triangle(new Vector3(), new Vector3(), new Vector3()))

  return function(from, vel, shape, boxPos, boxSize, quat) {
    var width = boxSize.x
      , height = boxSize.y
      , depth = boxSize.z

    a.addVectors(boxPos, corner.set(-width, height, depth).applyQuaternion(quat))
    b.addVectors(boxPos, corner.set(-width, -height, depth).applyQuaternion(quat))
    c.addVectors(boxPos, corner.set(width, -height, depth).applyQuaternion(quat))
    d.addVectors(boxPos, corner.set(width, height, depth).applyQuaternion(quat))
    e.addVectors(boxPos, corner.set(-width, height, -depth).applyQuaternion(quat))
    f.addVectors(boxPos, corner.set(-width, -height, -depth).applyQuaternion(quat))
    g.addVectors(boxPos, corner.set(width, -height, -depth).applyQuaternion(quat))
    h.addVectors(boxPos, corner.set(width, height, -depth).applyQuaternion(quat))

    var index = 0
    triangles[index++].set(a, b, c)
    triangles[index++].set(a, c, d)
    // back
    triangles[index++].set(h, g, f)
    triangles[index++].set(h, f, e)
    // left
    triangles[index++].set(e, f, b)
    triangles[index++].set(e, b, a)
    // right
    triangles[index++].set(d, c, g)
    triangles[index++].set(d, g, h)
    // top
    triangles[index++].set(e, a, d)
    triangles[index++].set(e, d, h)
    // bottom
    triangles[index++].set(b, f, g)
    triangles[index++].set(b, g, c)

    return getSweptCollision(from, vel, triangles, shape, true)
  }
}())

module.exports = {
  getSweptCollision: getSweptCollision,
  getSweptBoxCollision: getSweptBoxCollision,
  getCollision: getCollision,

  collides: (function() {
    var defaultA = new Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
      , defaultB = new Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
      , boxA = new Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
      , boxB = new Box(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))

    return function(a, b) {
      boxA.copy(a.box ? a.box : defaultA)
      boxB.copy(b.box ? b.box : defaultB)
      boxA.min.add(a.position)
      boxA.max.add(a.position)
      boxB.min.add(b.position)
      boxB.max.add(b.position)

      return boxA.isIntersectionBox(boxB)
    }
  }()),

  collidesSwept: function collidesSwept(a, b, from, to) {
    var boxA = {
      x: from.x - 1,
      y: from.y - 1,
      z: from.z - 1,
      w: 2,
      h: 2,
      d: 2
    }
    var boxB = {
      x: b.position.x - 1,
      y: b.position.y - 1,
      z: b.position.z - 1,
      w: 2,
      h: 2,
      d: 2
    }

    var velocity = new Vector3().subVectors(from, to)
    // Inverse times
    var invEnterX, invEnterY, invEnterZ
    var invExitX, invExitY, invExitZ

    if (velocity.x > 0) {
      invEnterX = boxB.x - (boxA.x + boxA.w)
      invExitX = (boxB.x + boxB.w) - boxA.x
    }
    else {
      invEnterX = (boxB.x + boxB.w) - boxA.x
      invExitX = boxB.x - (boxA.x + boxA.w)
    }

    if (velocity.y > 0) {
      invEnterY = boxB.y - (boxA.y + boxA.h)
      invExitY = (boxB.y + boxB.h) - boxA.y
    }
    else {
      invEnterY = (boxB.y + boxB.h) - boxA.y
      invExitY = boxB.y - (boxA.y + boxA.h)
    }

    if (velocity.z > 0) {
      invEnterZ = boxB.z - (boxA.z + boxA.d)
      invExitZ = (boxB.z + boxB.d) - boxA.z
    }
    else {
      invEnterZ = (boxB.z + boxB.d) - boxA.z
      invExitZ = boxB.z - (boxA.z + boxA.d)
    }

    var entryX, entryY, entryZ
    var exitX, exitY, exitZ

    if (Math.abs(velocity.x) < Number.EPSILON) {
        entryX = Number.NEGATIVE_INFINITY
        exitX = Number.POSITIVE_INFINITY
    }
    else {
        entryX = invEnterX / velocity.x
        exitX = invExitX / velocity.x
    }

    if (Math.abs(velocity.y) < Number.EPSILON) {
        entryY = Number.NEGATIVE_INFINITY
        exitY = Number.POSITIVE_INFINITY
    }
    else {
        entryY = invEnterY / velocity.y
        exitY = invExitY / velocity.y
    }

    if (Math.abs(velocity.z) < Number.EPSILON) {
        entryZ = Number.NEGATIVE_INFINITY
        exitZ = Number.POSITIVE_INFINITY
    }
    else {
        entryZ = invEnterZ / velocity.z
        exitZ = invExitZ / velocity.z
    }

    var entry = Math.max(entryX, entryY)
    entry = Math.max(entry, entryZ)

    var exit = Math.max(exitX, exitY)
    exit = Math.max(exit, exitZ)

    if (entry > exit) return Number.POSITIVE_INFINITY
    if (entryX < 0 && entryY < 0 && entryZ < 0) return Number.POSITIVE_INFINITY
    if (entryX < 0 && (boxA.x + boxA.w < boxB.x || boxA.x > boxB.x + boxB.w)) return Number.POSITIVE_INFINITY
    if (entryY < 0 && (boxA.y + boxA.h < boxB.y || boxA.y > boxB.y + boxB.h)) return Number.POSITIVE_INFINITY
    if (entryZ < 0 && (boxA.z + boxA.d < boxB.z || boxA.z > boxB.z + boxB.d)) return Number.POSITIVE_INFINITY

    return entry
  },
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types'
import React from 'react'
import Page from 'components/Page'
import {Grid, Row, Col} from 'react-bootstrap'

import TopBar from 'components/TopBar'
import Nav from 'components/Nav'

import API from 'api'
import {Person, Organization} from 'models'

import {Route, Switch} from 'react-router'
import Home from 'pages/Home'
import Search from 'pages/Search'
import RollupShow from 'pages/rollup/Show'
import GraphiQL from 'pages/GraphiQL'
import Help from 'pages/Help'
import PageMissing from 'pages/PageMissing'

import ReportNew from 'pages/reports/New'
import ReportShow from 'pages/reports/Show'
import ReportEdit from 'pages/reports/Edit'
import ReportMinimal from 'pages/reports/Minimal'
import MyReports from 'pages/reports/MyReports'

import PersonShow from 'pages/people/Show'
import PersonNew from 'pages/people/New'
import PersonEdit from 'pages/people/Edit'

import OrganizationShow from 'pages/organizations/Show'
import OrganizationNew from 'pages/organizations/New'
import OrganizationEdit from 'pages/organizations/Edit'

import LocationShow from 'pages/locations/Show'
import LocationEdit from 'pages/locations/Edit'
import LocationNew from 'pages/locations/New'

import PositionShow from 'pages/positions/Show'
import PositionEdit from 'pages/positions/Edit'
import PositionNew from 'pages/positions/New'

import TaskShow from 'pages/tasks/Show'
import TaskNew from 'pages/tasks/New'
import TaskEdit from 'pages/tasks/Edit'

import AdminIndex from 'pages/admin/Index'
import MergePeople from 'pages/admin/MergePeople'
import AuthorizationGroups from 'pages/admin/AuthorizationGroups'
import AuthorizationGroupShow from 'pages/admin/authorizationgroup/Show'
import AuthorizationGroupEdit from 'pages/admin/authorizationgroup/Edit'
import AuthorizationGroupNew from 'pages/admin/authorizationgroup/New'

import InsightsShow from  'pages/insights/Show'

import OnboardingShow from 'pages/onboarding/Show'
import OnboardingEdit from 'pages/onboarding/Edit'

import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'
import _isEqual from 'lodash/isEqual'

class App extends Page {

	static propTypes = {
		pageProps: PropTypes.object,
	}

	static childContextTypes = {
		app: PropTypes.object,
		currentUser: PropTypes.instanceOf(Person),
	}

	getChildContext() {
		return {
			app: this,
			currentUser: this.state.currentUser,
		}
	}

	constructor(props, context) {
		super(props, context)

		this.state = {
			pageProps: props.pageProps,
			currentUser: new Person(),
			settings: {},
			organizations: [],
			topbarOffset: 0,
			floatingMenu: false
		}

		this.updateTopbarOffset = this.updateTopbarOffset.bind(this)
		Object.assign(this.state, this.processData(window.ANET_DATA))
	}

	unlistenHistory

	componentDidMount() {
		super.componentDidMount()
		// We want to hide the floating menu on navigation events
		this.unlistenHistory = this.props.history.listen((location, action) => {
			this.setState({floatingMenu: false})
		  })
		  // TODO: This should ultimately happen through redux
	}

	componentWillUnmount() {
		super.componentWillUnmount()
		this.unlistenHistory()
	}

	componentWillReceiveProps(nextProps) {
		if (!_isEqual(this.state.pageProps, nextProps.pageProps)) {
			this.setState({pageProps: nextProps.pageProps})
		}
	}

	updateTopbarOffset(topbarOffset) {
		if (this.state.topbarOffset !== topbarOffset){
			this.setState({ topbarOffset: topbarOffset })
		}
	}

	fetchData() {
		API.query(/* GraphQL */`
			person(f:me) {
				id, name, role, emailAddress, rank, status
				position {
					id, name, type, status, isApprover
					organization { id, shortName , allDescendantOrgs { id }}
				}
			}

			adminSettings(f:getAll) {
				key, value
			}

			organizationList(f:getTopLevelOrgs, type: ADVISOR_ORG) {
				list { id, shortName }
			}
		`).then(data => {
			data.person._loaded = true
			this.setState(this.processData(data), () => {
				// if this is a new user, redirect to the create profile page
				if (this.state.currentUser.isNewUser()) {
					this.props.history.replace('/onboarding')
				}
			})
		})

	}

	processData(data) {
		const currentUser = new Person(data.person)
		let organizations = (data.organizationList && data.organizationList.list) || []
		organizations = Organization.fromArray(organizations)
		organizations.sort((a, b) => a.shortName.localeCompare(b.shortName))

		let settings = this.state.settings
		data.adminSettings.forEach(setting => settings[setting.key] = setting.value)

		return {currentUser, settings, organizations}
	}

	render() {
		const routing = <Switch>
			<Route exact path="/" component={Home} />
			<Route path="/search" component={Search} />
			<Route path="/rollup" component={RollupShow} />
			<Route path="/graphiql" component={GraphiQL} />
			<Route path="/help" component={Help} />
			<Route
				path="/reports"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={ReportNew} />
					<Route path={`${url}/:id/edit`} component={ReportEdit} />
					<Route path={`${url}/:id/min`} component={ReportMinimal} />
					<Route path={`${url}/mine`} component={MyReports} />
					<Route path={`${url}/:id`} component={ReportShow} />
				</Switch>
			)}
			/>
			<Route
				path="/people"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={PersonNew} />
					<Route path={`${url}/:id/edit`} component={PersonEdit} />
					<Route path={`${url}/:id`} component={PersonShow} />
				</Switch>
			)}
			/>
			<Route
				path="/organizations"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={OrganizationNew} />
					<Route path={`${url}/:id/edit`} component={OrganizationEdit} />
					<Route path={`${url}/:id/:action?`} component={OrganizationShow} />
				</Switch>
			)}
			/>
			<Route
				path="/locations"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={LocationNew} />
					<Route path={`${url}/:id/edit`} component={LocationEdit} />
					<Route path={`${url}/:id`} component={LocationShow} />
				</Switch>
			)}
			/>
			<Route
				path="/positions"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={PositionNew} />
					<Route path={`${url}/:id/edit`} component={PositionEdit} />
					<Route path={`${url}/:id`} component={PositionShow} />
				</Switch>
			)}
			/>
			<Route
				path="/tasks"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={TaskNew} />
					<Route path={`${url}/:id/edit`} component={TaskEdit} />
					<Route path={`${url}/:id`} component={TaskShow} />
				</Switch>
			)}
			/>
			<Route
				path="/admin"
				render={({ match: { url } }) => (
				<Switch>
					<Route exact path={`${url}/`} component={AdminIndex} />
					<Route path={`${url}/mergePeople`} component={MergePeople} />
					<Route exact path={`${url}/authorizationGroups`} component={AuthorizationGroups} />
					<Route path={`${url}/authorizationGroups/new`} component={AuthorizationGroupNew} />
					<Route path={`${url}/authorizationGroups/:id/edit`} component={AuthorizationGroupEdit} />
					<Route path={`${url}/authorizationGroups/:id`} component={AuthorizationGroupShow} />
				</Switch>
			)}
			/>
			<Route
				path="/insights"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/:insight`} component={InsightsShow} />
				</Switch>
			)}
			/>
			<Route
				path="/onboarding"
				render={({ match: { url } }) => (
				<Switch>
					<Route exact path={`${url}/`} component={OnboardingShow} />
					<Route path={`${url}/edit`} component={OnboardingEdit} />
				</Switch>
			)}
			/>

			<Route path="*" component={PageMissing} />
		</Switch>

		return (

				<TopBar
					updateTopbarOffset={this.updateTopbarOffset}
					currentUser={this.state.currentUser}
					settings={this.state.settings}
					minimalHeader={this.state.pageProps.minimalHeader}
					location={this.props.location}
					toggleMenuAction={()=>{
						this.setState({floatingMenu: !this.state.floatingMenu})
					}} />

					{(this.state.pageProps.useNavigation !== false || this.state.floatingMenu === true) &&

					}

 {this.setState({floatingMenu: false})}}>

						{routing}

		)
	}
}

const mapStateToProps = (state, ownProps) => ({
	pageProps: state.pageProps
})

export default connect(mapStateToProps)(withRouter(App))
<commit_msg>NCI-Agency/anet#551: Add some padding around main content div<commit_after>import PropTypes from 'prop-types'
import React from 'react'
import Page from 'components/Page'
import {Grid, Row, Col} from 'react-bootstrap'

import TopBar from 'components/TopBar'
import Nav from 'components/Nav'

import API from 'api'
import {Person, Organization} from 'models'

import {Route, Switch} from 'react-router'
import Home from 'pages/Home'
import Search from 'pages/Search'
import RollupShow from 'pages/rollup/Show'
import GraphiQL from 'pages/GraphiQL'
import Help from 'pages/Help'
import PageMissing from 'pages/PageMissing'

import ReportNew from 'pages/reports/New'
import ReportShow from 'pages/reports/Show'
import ReportEdit from 'pages/reports/Edit'
import ReportMinimal from 'pages/reports/Minimal'
import MyReports from 'pages/reports/MyReports'

import PersonShow from 'pages/people/Show'
import PersonNew from 'pages/people/New'
import PersonEdit from 'pages/people/Edit'

import OrganizationShow from 'pages/organizations/Show'
import OrganizationNew from 'pages/organizations/New'
import OrganizationEdit from 'pages/organizations/Edit'

import LocationShow from 'pages/locations/Show'
import LocationEdit from 'pages/locations/Edit'
import LocationNew from 'pages/locations/New'

import PositionShow from 'pages/positions/Show'
import PositionEdit from 'pages/positions/Edit'
import PositionNew from 'pages/positions/New'

import TaskShow from 'pages/tasks/Show'
import TaskNew from 'pages/tasks/New'
import TaskEdit from 'pages/tasks/Edit'

import AdminIndex from 'pages/admin/Index'
import MergePeople from 'pages/admin/MergePeople'
import AuthorizationGroups from 'pages/admin/AuthorizationGroups'
import AuthorizationGroupShow from 'pages/admin/authorizationgroup/Show'
import AuthorizationGroupEdit from 'pages/admin/authorizationgroup/Edit'
import AuthorizationGroupNew from 'pages/admin/authorizationgroup/New'

import InsightsShow from  'pages/insights/Show'

import OnboardingShow from 'pages/onboarding/Show'
import OnboardingEdit from 'pages/onboarding/Edit'

import { withRouter } from 'react-router-dom'
import { connect } from 'react-redux'
import _isEqual from 'lodash/isEqual'

class App extends Page {

	static propTypes = {
		pageProps: PropTypes.object,
	}

	static childContextTypes = {
		app: PropTypes.object,
		currentUser: PropTypes.instanceOf(Person),
	}

	getChildContext() {
		return {
			app: this,
			currentUser: this.state.currentUser,
		}
	}

	constructor(props, context) {
		super(props, context)

		this.state = {
			pageProps: props.pageProps,
			currentUser: new Person(),
			settings: {},
			organizations: [],
			topbarOffset: 0,
			floatingMenu: false
		}

		this.updateTopbarOffset = this.updateTopbarOffset.bind(this)
		Object.assign(this.state, this.processData(window.ANET_DATA))
	}

	unlistenHistory

	componentDidMount() {
		super.componentDidMount()
		// We want to hide the floating menu on navigation events
		this.unlistenHistory = this.props.history.listen((location, action) => {
			this.setState({floatingMenu: false})
		  })
		  // TODO: This should ultimately happen through redux
	}

	componentWillUnmount() {
		super.componentWillUnmount()
		this.unlistenHistory()
	}

	componentWillReceiveProps(nextProps) {
		if (!_isEqual(this.state.pageProps, nextProps.pageProps)) {
			this.setState({pageProps: nextProps.pageProps})
		}
	}

	updateTopbarOffset(topbarOffset) {
		if (this.state.topbarOffset !== topbarOffset){
			this.setState({ topbarOffset: topbarOffset })
		}
	}

	fetchData() {
		API.query(/* GraphQL */`
			person(f:me) {
				id, name, role, emailAddress, rank, status
				position {
					id, name, type, status, isApprover
					organization { id, shortName , allDescendantOrgs { id }}
				}
			}

			adminSettings(f:getAll) {
				key, value
			}

			organizationList(f:getTopLevelOrgs, type: ADVISOR_ORG) {
				list { id, shortName }
			}
		`).then(data => {
			data.person._loaded = true
			this.setState(this.processData(data), () => {
				// if this is a new user, redirect to the create profile page
				if (this.state.currentUser.isNewUser()) {
					this.props.history.replace('/onboarding')
				}
			})
		})

	}

	processData(data) {
		const currentUser = new Person(data.person)
		let organizations = (data.organizationList && data.organizationList.list) || []
		organizations = Organization.fromArray(organizations)
		organizations.sort((a, b) => a.shortName.localeCompare(b.shortName))

		let settings = this.state.settings
		data.adminSettings.forEach(setting => settings[setting.key] = setting.value)

		return {currentUser, settings, organizations}
	}

	render() {
		const routing = <Switch>
			<Route exact path="/" component={Home} />
			<Route path="/search" component={Search} />
			<Route path="/rollup" component={RollupShow} />
			<Route path="/graphiql" component={GraphiQL} />
			<Route path="/help" component={Help} />
			<Route
				path="/reports"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={ReportNew} />
					<Route path={`${url}/:id/edit`} component={ReportEdit} />
					<Route path={`${url}/:id/min`} component={ReportMinimal} />
					<Route path={`${url}/mine`} component={MyReports} />
					<Route path={`${url}/:id`} component={ReportShow} />
				</Switch>
			)}
			/>
			<Route
				path="/people"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={PersonNew} />
					<Route path={`${url}/:id/edit`} component={PersonEdit} />
					<Route path={`${url}/:id`} component={PersonShow} />
				</Switch>
			)}
			/>
			<Route
				path="/organizations"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={OrganizationNew} />
					<Route path={`${url}/:id/edit`} component={OrganizationEdit} />
					<Route path={`${url}/:id/:action?`} component={OrganizationShow} />
				</Switch>
			)}
			/>
			<Route
				path="/locations"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={LocationNew} />
					<Route path={`${url}/:id/edit`} component={LocationEdit} />
					<Route path={`${url}/:id`} component={LocationShow} />
				</Switch>
			)}
			/>
			<Route
				path="/positions"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={PositionNew} />
					<Route path={`${url}/:id/edit`} component={PositionEdit} />
					<Route path={`${url}/:id`} component={PositionShow} />
				</Switch>
			)}
			/>
			<Route
				path="/tasks"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/new`} component={TaskNew} />
					<Route path={`${url}/:id/edit`} component={TaskEdit} />
					<Route path={`${url}/:id`} component={TaskShow} />
				</Switch>
			)}
			/>
			<Route
				path="/admin"
				render={({ match: { url } }) => (
				<Switch>
					<Route exact path={`${url}/`} component={AdminIndex} />
					<Route path={`${url}/mergePeople`} component={MergePeople} />
					<Route exact path={`${url}/authorizationGroups`} component={AuthorizationGroups} />
					<Route path={`${url}/authorizationGroups/new`} component={AuthorizationGroupNew} />
					<Route path={`${url}/authorizationGroups/:id/edit`} component={AuthorizationGroupEdit} />
					<Route path={`${url}/authorizationGroups/:id`} component={AuthorizationGroupShow} />
				</Switch>
			)}
			/>
			<Route
				path="/insights"
				render={({ match: { url } }) => (
				<Switch>
					<Route path={`${url}/:insight`} component={InsightsShow} />
				</Switch>
			)}
			/>
			<Route
				path="/onboarding"
				render={({ match: { url } }) => (
				<Switch>
					<Route exact path={`${url}/`} component={OnboardingShow} />
					<Route path={`${url}/edit`} component={OnboardingEdit} />
				</Switch>
			)}
			/>

			<Route path="*" component={PageMissing} />
		</Switch>

		return (

				<TopBar
					updateTopbarOffset={this.updateTopbarOffset}
					currentUser={this.state.currentUser}
					settings={this.state.settings}
					minimalHeader={this.state.pageProps.minimalHeader}
					location={this.props.location}
					toggleMenuAction={()=>{
						this.setState({floatingMenu: !this.state.floatingMenu})
					}} />

					{(this.state.pageProps.useNavigation !== false || this.state.floatingMenu === true) &&

					}

 {this.setState({floatingMenu: false})}}>

						{routing}

		)
	}
}

const mapStateToProps = (state, ownProps) => ({
	pageProps: state.pageProps
})

export default connect(mapStateToProps)(withRouter(App))
<|endoftext|>


<commit_before>/**
 * Created by reini on 25.03.15.
 */

var hooksObject = {
    before: {
        'method-update': function(doc) {
            clearErrors();
            return doc;
        },
        'method': function(doc) {
            clearErrors();
            return doc;
        }
    },

    // The same as the callbacks you would normally provide when calling
    // collection.insert, collection.update, or Meteor.call
    //after: {
    //    // Replace `formType` with the form `type` attribute to which this hook applies
    //},

    // Called when form does not have a `type` attribute
    //onSubmit: function(insertDoc, updateDoc, currentDoc) {
        // You must call this.done()!
        //this.done(); // submitted successfully, call onSuccess
        //this.done(new Error('foo')); // failed to submit, call onError with the provided error
        //this.done(null, "foo"); // submitted successfully, call onSuccess with `result` arg set to "foo"
    //},

    // Called when any submit operation succeeds
    onSuccess: function(formType, result) {
        if (result && result.template) {
            if (result.param) {
                Router.go(result.template, result.param);
            } else {
                Router.go(result.template);
            }
        }
    },

    // Called when any submit operation fails
    onError: function(formType, error) {
        if (error) {
            throwError(error.reason);
        }
    }
};

AutoForm.addHooks(null, hooksObject);<commit_msg>remove errors on success<commit_after>/**
 * Created by reini on 25.03.15.
 */

var hooksObject = {
    before: {
        'method-update': function(doc) {
            clearErrors();
            return doc;
        },
        'method': function(doc) {
            clearErrors();
            return doc;
        }
    },

    // The same as the callbacks you would normally provide when calling
    // collection.insert, collection.update, or Meteor.call
    //after: {
    //    // Replace `formType` with the form `type` attribute to which this hook applies
    //},

    // Called when form does not have a `type` attribute
    //onSubmit: function(insertDoc, updateDoc, currentDoc) {
        // You must call this.done()!
        //this.done(); // submitted successfully, call onSuccess
        //this.done(new Error('foo')); // failed to submit, call onError with the provided error
        //this.done(null, "foo"); // submitted successfully, call onSuccess with `result` arg set to "foo"
    //},

    // Called when any submit operation succeeds
    onSuccess: function(formType, result) {
        clearErrors();
        if (result && result.template) {
            if (result.param) {
                Router.go(result.template, result.param);
            } else {
                Router.go(result.template);
            }
        }
    },

    // Called when any submit operation fails
    onError: function(formType, error) {
        if (error) {
            throwError(error.reason);
        }
    }
};

AutoForm.addHooks(null, hooksObject);<|endoftext|>


<commit_before>Template.registerHelper('mspIsDeviceConnected', function () {
    return Session.get('mspConnectedDeviceName');
});

Template.registerHelper('mspRc', function (stick) {
    if (Session.get('mspData')) {
        return Session.get('mspData').rc[stick];
    }

    return 1000;
});

Template.registerHelper('mspRcPercentage', function (stick) {
    if (Session.get('mspData')) {
        return (Session.get('mspData').rc[stick] - 1000) / 10;
    }

    return 0;
});

Template.registerHelper('mspBoxActive', function (boxIndex) {
    if (Session.get('mspData')) {
        return Session.get('mspData').status.boxActivation[boxIndex];
    }

    return false;
});

Template.registerHelper('mspRawImu', function (sensor, coord) {
    if (Session.get('mspData')) {
        return Session.get('mspData').rawImu[sensor][coord];
    }

    return 0;
});

Template.registerHelper('mspIsBoxActive', function (nameOrIndex) {
    var index;

    if (Session.get('mspBoxNames') && Session.get('mspData')) {
        index = isNaN(nameOrIndex) ? Session.get('mspBoxNames').indexOf(nameOrIndex.toUpperCase()) : nameOrIndex;
        if (index > -1) {
            return Session.get('mspData').status.boxActivation[index];
        }
    }

    return false;
});<commit_msg>Removed duplicated helper method<commit_after>Template.registerHelper('mspIsDeviceConnected', function () {
    return Session.get('mspConnectedDeviceName');
});

Template.registerHelper('mspRc', function (stick) {
    if (Session.get('mspData')) {
        return Session.get('mspData').rc[stick];
    }

    return 1000;
});

Template.registerHelper('mspRcPercentage', function (stick) {
    if (Session.get('mspData')) {
        return (Session.get('mspData').rc[stick] - 1000) / 10;
    }

    return 0;
});

Template.registerHelper('mspRawImu', function (sensor, coord) {
    if (Session.get('mspData')) {
        return Session.get('mspData').rawImu[sensor][coord];
    }

    return 0;
});

Template.registerHelper('mspIsBoxActive', function (nameOrIndex) {
    var index;

    if (Session.get('mspBoxNames') && Session.get('mspData')) {
        index = isNaN(nameOrIndex) ? Session.get('mspBoxNames').indexOf(nameOrIndex.toUpperCase()) : nameOrIndex;
        if (index > -1) {
            return Session.get('mspData').status.boxActivation[index];
        }
    }

    return false;
});<|endoftext|>