<commit_before>'use strict';
let pxToIn = px => { return px / 96.75 };
let hexColor = color => {
  if (color[0] === '#') {
    return color;
  } else {
    let rgb = color.match(/\d+/g).map(num => { return parseInt(num).toString(16) });
    return `#${rgb.join('')}`;
  }
}

let commits = $('li.commit');
commits.attr('data-octotrax-hash', function () {
  return this.dataset.channel.split(':').slice(-1)[0];
});

let head = commits.first();
let headHash = head.attr('data-octotrax-hash');
let color = hexColor(head.find('.commit-author').first().css('color'));
let rowHeight = head.height();
let nodeHeight = 9;
let ranksep = rowHeight - nodeHeight;
let dot =
`
digraph "commit graph" {
  rankdir = TB;
  ranksep = "${pxToIn(ranksep)} equally"
  splines = line;
  edge [arrowhead = none, color = "${color}"];
  node [shape = circle, label = "", height = "${pxToIn(nodeHeight)}", color = "${color}"];
`;

let username = $('.entry-title .author').text();
let repo = $('.entry-title [itemprop="name"]').text();
let octokat = new Octokat();
octokat.repos(username, repo).commits.fetch(
  {sha: headHash, per_page: commits.length}
).then(rawInfo => {
  let commitInfo = {};
  rawInfo.forEach(commit => {
    commitInfo[commit.sha] = commit;
  });
  commits.toArray().forEach(commit => {
    let hash = commit.dataset.octotraxHash;
    let shortHash = hash.slice(0, 7);
    commitInfo[hash].parents.forEach(parent => {
      dot += `  "${hash}" -> "${parent.sha}";\n`;
    });
  });
  dot += '}';

  let svg = $(Viz(dot));
  let svgDiv = $('

').attr({id: 'octotrax-commit-graph'}).append(svg);
  svgDiv.css('margin-top', ((rowHeight - nodeHeight) - 2) / 2);
  let commitsListing = $('.commits-listing');
  svgDiv.insertBefore(commitsListing);
  commitsListing.width((_, oldWidth) => {
    return (oldWidth - svgDiv.width()) - 1;
  });
});
<commit_msg>Force ranking. [#5]<commit_after>'use strict';
let pxToIn = px => { return px / 96.75 };
let hexColor = color => {
  if (color[0] === '#') {
    return color;
  } else {
    let rgb = color.match(/\d+/g).map(num => { return parseInt(num).toString(16) });
    return `#${rgb.join('')}`;
  }
}

let commits = $('li.commit');
commits.attr('data-octotrax-hash', function () {
  return this.dataset.channel.split(':').slice(-1)[0];
});

let head = commits.first();
let headHash = head.attr('data-octotrax-hash');
let color = hexColor(head.find('.commit-author').first().css('color'));
let rowHeight = head.height();
let nodeHeight = 9;
let ranksep = rowHeight - nodeHeight;
let dot =
`
digraph "commit graph" {
  rankdir = TB;
  ranksep = "${pxToIn(ranksep)} equally"
  splines = line;
  edge [arrowhead = none, color = "${color}"];
  node [shape = circle, label = "", height = "${pxToIn(nodeHeight)}", color = "${color}"];

  subgraph levels {
    edge [style = invis];
    node [style = invis, height = 0];
    ${Array.from(new Array(commits.length), (_, i) => `"L${i}"`).join(' -> ')};
  }
`;

let username = $('.entry-title .author').text();
let repo = $('.entry-title [itemprop="name"]').text();
let octokat = new Octokat();
octokat.repos(username, repo).commits.fetch(
  {sha: headHash, per_page: commits.length}
).then(rawInfo => {
  let commitInfo = {};
  rawInfo.forEach(commit => {
    commitInfo[commit.sha] = commit;
  });

  commits.toArray().forEach((commit, index) => {
    let hash = commit.dataset.octotraxHash;
    let shortHash = hash.slice(0, 7);
    commitInfo[hash].parents.forEach(parent => {
      dot += `  "${hash}" -> "${parent.sha}";\n`;
    });
    dot += `  { rank = same; "${hash}"; "L${index}"; }\n`
  });
  dot += '}';

  let svg = $(Viz(dot));
  let svgDiv = $('

').attr({id: 'octotrax-commit-graph'}).append(svg);
  svgDiv.css('margin-top', ((rowHeight - nodeHeight) - 2) / 2);
  let commitsListing = $('.commits-listing');
  svgDiv.insertBefore(commitsListing);
  commitsListing.width((_, oldWidth) => {
    return (oldWidth - svgDiv.width()) - 1;
  });
});
<|endoftext|>


<commit_before>import 'bunsen-core/typedefs'

import redux from 'npm:redux'
const {createStore, applyMiddleware} = redux
import thunk from 'npm:redux-thunk'
const thunkMiddleware = thunk.default
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore)
import reducer from 'bunsen-core/reducer'
import {validate, changeModel} from 'bunsen-core/actions'

import _ from 'lodash'
import Ember from 'ember'
const {Component, RSVP, typeOf} = Ember
import computed, {readOnly} from 'ember-computed-decorators'
import getOwner from 'ember-getowner-polyfill'
import PropTypeMixin, {PropTypes} from 'ember-prop-types'
import {dereference} from 'bunsen-core/dereference'
import {getDefaultView} from 'bunsen-core/generator'
import validateView, {validateModel} from 'bunsen-core/validator'
import viewV1ToV2 from 'bunsen-core/conversion/view-v1-to-v2'
import layout from 'ember-frost-bunsen/templates/components/frost-bunsen-detail'

import {deemberify, validateRenderer} from '../utils'

function getAlias (cell) {
  if (cell.label) {
    return cell.label
  }

  const words = Ember.String.dasherize(cell.model || 'Tab').replace('-', ' ')
  return Ember.String.capitalize(words)
}

/**
 * Determine if an object is an Ember.Object or not
 * @param {Object|Ember.Object} object - object to check
 * @returns {Boolean} whether or not object is an Ember.Object
 */
function isEmberObject (object) {
  return !_.isEmpty(object) && !_.isPlainObject(object)
}

export default Component.extend(PropTypeMixin, {
  // == Component Properties ===================================================

  layout,

  // == State Properties =======================================================

  propTypes: {
    bunsenModel: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.object
    ]).isRequired,
    bunsenView: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.object
    ]),
    hook: PropTypes.string,
    onChange: PropTypes.func,
    onError: PropTypes.func,
    onValidation: PropTypes.func,
    registeredComponents: PropTypes.array,
    renderers: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.object
    ]),
    value: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.null,
      PropTypes.object
    ])
  },

  getDefaultProps () {
    return {
      classNames: ['frost-bunsen-detail'],
      disabled: false,
      hook: 'bunsenDetail',
      renderers: {},
      registeredComponents: [],
      showAllErrors: false,
      validators: [],
      value: null
    }
  },

  // == Computed Properties ====================================================

  @readOnly
  @computed('errors')
  renderErrors (errors) {
    return errors || {}
  },

  @readOnly
  @computed('reduxModel')
  renderModel (model) {
    return dereference(model || {}).schema
  },

  @readOnly
  @computed('renderModel', 'bunsenView')
  /**
   * Get the view to render (generate one if consumer doesn't supply a view)
   * @param {BunsenModel} model - the model schema to use to generate a view (if view is undefined)
   * @param {BunsenView} bunsenView - the view to use (if given)
   * @returns {BunsenView} the view to render
   */
  renderView (model, bunsenView) {
    if (_.isEmpty(bunsenView)) {
      return getDefaultView(model)
    }

    if (bunsenView.version === '1.0') {
      return viewV1ToV2(bunsenView)
    }

    if (typeOf(bunsenView.get) === 'function' && bunsenView.get('view') === '1.0') {
      return viewV1ToV2(deemberify(bunsenView))
    }

    return _.cloneDeep(bunsenView)
  },

  @readOnly
  @computed('renderView')
  cellTabs () {
    const cells = this.get('renderView.cells')

    // If there is only one cell then we don't need to render tabs
    if (cells.length === 1) {
      return Ember.A([])
    }

    const tabs = cells.map((cell, index) => {
      const alias = getAlias(cell)

      // Since label is used for tab text don't render a label within tab as well
      delete cell.label

      return {
        alias,
        cell,
        id: `${index}-${Date.now()}`,
        classNames: Ember.String.dasherize(alias)
      }
    })

    return Ember.A(tabs)
  },

  @readOnly
  @computed('cellTabs', 'selectedTabIndex')
  tabSelection (cellTabs, selectedTabIndex) {
    return selectedTabIndex || cellTabs.get('0.id')
  },

  @readOnly
  @computed('propValidationResult')
  isInvalid (propValidationResult) {
    return !_.isEmpty(propValidationResult.errors)
  },

  // == Functions ==============================================================

  /* eslint-disable complexity */
  /**
   * Keep UI in sync with updates to redux store
   */
  storeUpdated () {
    const state = this.get('reduxStore').getState()
    const {errors, validationResult, value} = state

    const newProps = {}

    if (!_.isEqual(this.get('errors'), errors)) {
      newProps.errors = errors
    }

    if (!_.isEqual(this.get('reduxModel'), state.model)) {
      newProps.reduxModel = state.model
    }

    if (!_.isEqual(this.get('renderValue'), value)) {
      newProps.renderValue = value

      this.get('registeredComponents').forEach((component) => {
        component.formValueChanged(value)
      })
    }

    if (Object.keys(newProps).length === 0) {
      return
    }

    this.setProperties(newProps)

    if ('renderValue' in newProps && this.onChange) {
      this.onChange(value)
    }

    if (('errors' in newProps || 'renderValue' in newProps) && this.onValidation) {
      this.onValidation(validationResult)
    }
  },
  /* eslint-enable complexity */

  /**
   * Setup redux store
   */
  init () {
    this._super(...arguments)

    const value = this.get('value')
    const plainObjectValue = isEmberObject(value) ? deemberify(value) : value
    const reduxStore = createStoreWithMiddleware(reducer, {
      baseModel: this.get('bunsenModel'),
      value: plainObjectValue
    })

    this.set('reduxStore', reduxStore)
    this.set('reduxModel', reduxStore.getState().model)
    reduxStore.subscribe(this.storeUpdated.bind(this))
  },

  /**
   * Validate properties
   */
  validateProps () {
    const bunsenModel = this.get('bunsenModel')
    const bunsenModelPojo = isEmberObject(bunsenModel) ? deemberify(bunsenModel) : bunsenModel
    const renderers = this.get('renderers')

    let result = validateModel(bunsenModelPojo)
    this.get('reduxStore').dispatch(changeModel(bunsenModel))
    const view = this.get('renderView')

    if (result.errors.length === 0) {
      const validateRendererFn = validateRenderer.bind(null, getOwner(this))
      result = validateView(view, bunsenModel, _.keys(renderers), validateRendererFn)
    }

    this.set('propValidationResult', result)
  },

  /* eslint-disable complexity */
  /**
   * Keep value in sync with store and validate properties
   */
  didReceiveAttrs ({newAttrs, oldAttrs}) {
    this._super(...arguments)

    let dispatchValue

    const reduxStore = this.get('reduxStore')
    const value = this.get('value')
    const plainObjectValue = isEmberObject(value) ? deemberify(value) : value
    const reduxStoreValue = reduxStore.getState().value
    const hasUserProvidedValue = [null, undefined].indexOf(plainObjectValue) === -1
    const isReduxStoreValueEmpty = [null, undefined].indexOf(reduxStoreValue) !== -1
    const doesUserValueMatchStoreValue = _.isEqual(plainObjectValue, reduxStoreValue)

    // If the store value is empty we need to make sure we we set it to an empty object so
    // properties can be assigned to it via onChange events
    if (isReduxStoreValueEmpty) {
      dispatchValue = {}
    }

    // If the user/consumer has provided a value and it differs from the current store value
    // then we need to update the store to be the user/consumer supplied value
    if (hasUserProvidedValue && !doesUserValueMatchStoreValue) {
      dispatchValue = plainObjectValue
    }

    // If we have a new value to assign the store then let's get to it
    if (dispatchValue) {
      reduxStore.dispatch(
        validate(null, dispatchValue, this.get('renderModel'), this.get('validators'), RSVP.all)
      )
    } else {
      const newModel = _.get(newAttrs, 'bunsenModel.value')
      const newModelPojo = isEmberObject(newModel) ? deemberify(newModel) : newModel
      const oldModel = _.get(oldAttrs, 'bunsenModel.value')
      const oldModelPojo = isEmberObject(oldModel) ? deemberify(oldModel) : oldModel
      const modelChanged = !_.isEqual(oldModelPojo, newModelPojo)

      if (modelChanged) {
        reduxStore.dispatch(
          validate(null, value, newModelPojo, this.get('validators'), RSVP.all)
        )
      }
    }

    this.validateProps()
  },
  /* eslint-enable complexity */

  // == Actions ================================================================

  actions: {
    /**
     * Nothing to handle, since value doesn't change for detail component
     */
    handleChange () {},

    /**
     * When a renderer has an error (not a validation issue, but more a logic error)
     * we report it back to the consumer. The main use-case here is API errors
     * for select renderers and custom renderers
     * @param {String} bunsenId - the busnen ID of the component that had an error
     * @param {BunsenValidationError[]} errors - the errors that occurred they're not actually validation errors,
     *                                           but it's a handy format to use for errors
     */
    handleError (bunsenId, errors) {
      if (this.onError) {
        this.onError(bunsenId, errors)
      }
    },

    /**
     * Change selected tab/root cell
     * @param {Number} tabIndex - index of root cell corresponding to tab
     */
    handleTabChange (tabIndex) {
      this.set('selectedTabIndex', tabIndex)
    },

    /**
     * Register a component for formValue changes
     * @param {Ember.Component} component - the component being registered
     */
    registerComponentForFormValueChanges (component) {
      component.formValueChanged(this.get('renderValue'))
      this.get('registeredComponents').push(component)
    }
  }
})
<commit_msg>Fix regression<commit_after>import 'bunsen-core/typedefs'

import redux from 'npm:redux'
const {createStore, applyMiddleware} = redux
import thunk from 'npm:redux-thunk'
const thunkMiddleware = thunk.default
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore)
import reducer from 'bunsen-core/reducer'
import {validate, changeModel} from 'bunsen-core/actions'

import _ from 'lodash'
import Ember from 'ember'
const {Component, RSVP, typeOf} = Ember
import computed, {readOnly} from 'ember-computed-decorators'
import getOwner from 'ember-getowner-polyfill'
import PropTypeMixin, {PropTypes} from 'ember-prop-types'
import {dereference} from 'bunsen-core/dereference'
import {getDefaultView} from 'bunsen-core/generator'
import validateView, {validateModel} from 'bunsen-core/validator'
import viewV1ToV2 from 'bunsen-core/conversion/view-v1-to-v2'
import layout from 'ember-frost-bunsen/templates/components/frost-bunsen-detail'

import {deemberify, validateRenderer} from '../utils'

function getAlias (cell) {
  if (cell.label) {
    return cell.label
  }

  const words = Ember.String.dasherize(cell.model || 'Tab').replace('-', ' ')
  return Ember.String.capitalize(words)
}

/**
 * Determine if an object is an Ember.Object or not
 * @param {Object|Ember.Object} object - object to check
 * @returns {Boolean} whether or not object is an Ember.Object
 */
function isEmberObject (object) {
  return !_.isEmpty(object) && !_.isPlainObject(object)
}

export default Component.extend(PropTypeMixin, {
  // == Component Properties ===================================================

  layout,

  // == State Properties =======================================================

  propTypes: {
    bunsenModel: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.object
    ]).isRequired,
    bunsenView: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.object
    ]),
    hook: PropTypes.string,
    onChange: PropTypes.func,
    onError: PropTypes.func,
    onValidation: PropTypes.func,
    registeredComponents: PropTypes.array,
    renderers: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.object
    ]),
    value: PropTypes.oneOfType([
      PropTypes.EmberObject,
      PropTypes.null,
      PropTypes.object
    ])
  },

  getDefaultProps () {
    return {
      classNames: ['frost-bunsen-detail'],
      disabled: false,
      hook: 'bunsenDetail',
      renderers: {},
      registeredComponents: [],
      showAllErrors: false,
      validators: [],
      value: null
    }
  },

  // == Computed Properties ====================================================

  @readOnly
  @computed('errors')
  renderErrors (errors) {
    return errors || {}
  },

  @readOnly
  @computed('reduxModel')
  renderModel (model) {
    return dereference(model || {}).schema
  },

  @readOnly
  @computed('renderModel', 'bunsenView')
  /**
   * Get the view to render (generate one if consumer doesn't supply a view)
   * @param {BunsenModel} model - the model schema to use to generate a view (if view is undefined)
   * @param {BunsenView} bunsenView - the view to use (if given)
   * @returns {BunsenView} the view to render
   */
  renderView (model, bunsenView) {
    if (_.isEmpty(bunsenView)) {
      return getDefaultView(model)
    }

    if (bunsenView.version === '1.0') {
      bunsenView = viewV1ToV2(bunsenView)

      if (bunsenView.cells.length === 1) {
        delete bunsenView.cells[0].label
      }

      return bunsenView
    }

    if (typeOf(bunsenView.get) === 'function' && bunsenView.get('view') === '1.0') {
      bunsenView = viewV1ToV2(deemberify(bunsenView))

      if (bunsenView.cells.length === 1) {
        delete bunsenView.cells[0].label
      }

      return bunsenView
    }

    return _.cloneDeep(bunsenView)
  },

  @readOnly
  @computed('renderView')
  cellTabs () {
    const cells = this.get('renderView.cells')

    // If there is only one cell then we don't need to render tabs
    if (cells.length === 1) {
      return Ember.A([])
    }

    const tabs = cells.map((cell, index) => {
      const alias = getAlias(cell)

      // Since label is used for tab text don't render a label within tab as well
      delete cell.label

      return {
        alias,
        cell,
        id: `${index}-${Date.now()}`,
        classNames: Ember.String.dasherize(alias)
      }
    })

    return Ember.A(tabs)
  },

  @readOnly
  @computed('cellTabs', 'selectedTabIndex')
  tabSelection (cellTabs, selectedTabIndex) {
    return selectedTabIndex || cellTabs.get('0.id')
  },

  @readOnly
  @computed('propValidationResult')
  isInvalid (propValidationResult) {
    return !_.isEmpty(propValidationResult.errors)
  },

  // == Functions ==============================================================

  /* eslint-disable complexity */
  /**
   * Keep UI in sync with updates to redux store
   */
  storeUpdated () {
    const state = this.get('reduxStore').getState()
    const {errors, validationResult, value} = state

    const newProps = {}

    if (!_.isEqual(this.get('errors'), errors)) {
      newProps.errors = errors
    }

    if (!_.isEqual(this.get('reduxModel'), state.model)) {
      newProps.reduxModel = state.model
    }

    if (!_.isEqual(this.get('renderValue'), value)) {
      newProps.renderValue = value

      this.get('registeredComponents').forEach((component) => {
        component.formValueChanged(value)
      })
    }

    if (Object.keys(newProps).length === 0) {
      return
    }

    this.setProperties(newProps)

    if ('renderValue' in newProps && this.onChange) {
      this.onChange(value)
    }

    if (('errors' in newProps || 'renderValue' in newProps) && this.onValidation) {
      this.onValidation(validationResult)
    }
  },
  /* eslint-enable complexity */

  /**
   * Setup redux store
   */
  init () {
    this._super(...arguments)

    const value = this.get('value')
    const plainObjectValue = isEmberObject(value) ? deemberify(value) : value
    const reduxStore = createStoreWithMiddleware(reducer, {
      baseModel: this.get('bunsenModel'),
      value: plainObjectValue
    })

    this.set('reduxStore', reduxStore)
    this.set('reduxModel', reduxStore.getState().model)
    reduxStore.subscribe(this.storeUpdated.bind(this))
  },

  /**
   * Validate properties
   */
  validateProps () {
    const bunsenModel = this.get('bunsenModel')
    const bunsenModelPojo = isEmberObject(bunsenModel) ? deemberify(bunsenModel) : bunsenModel
    const renderers = this.get('renderers')

    let result = validateModel(bunsenModelPojo)
    this.get('reduxStore').dispatch(changeModel(bunsenModel))
    const view = this.get('renderView')

    if (result.errors.length === 0) {
      const validateRendererFn = validateRenderer.bind(null, getOwner(this))
      result = validateView(view, bunsenModel, _.keys(renderers), validateRendererFn)
    }

    this.set('propValidationResult', result)
  },

  /* eslint-disable complexity */
  /**
   * Keep value in sync with store and validate properties
   */
  didReceiveAttrs ({newAttrs, oldAttrs}) {
    this._super(...arguments)

    let dispatchValue

    const reduxStore = this.get('reduxStore')
    const value = this.get('value')
    const plainObjectValue = isEmberObject(value) ? deemberify(value) : value
    const reduxStoreValue = reduxStore.getState().value
    const hasUserProvidedValue = [null, undefined].indexOf(plainObjectValue) === -1
    const isReduxStoreValueEmpty = [null, undefined].indexOf(reduxStoreValue) !== -1
    const doesUserValueMatchStoreValue = _.isEqual(plainObjectValue, reduxStoreValue)

    // If the store value is empty we need to make sure we we set it to an empty object so
    // properties can be assigned to it via onChange events
    if (isReduxStoreValueEmpty) {
      dispatchValue = {}
    }

    // If the user/consumer has provided a value and it differs from the current store value
    // then we need to update the store to be the user/consumer supplied value
    if (hasUserProvidedValue && !doesUserValueMatchStoreValue) {
      dispatchValue = plainObjectValue
    }

    // If we have a new value to assign the store then let's get to it
    if (dispatchValue) {
      reduxStore.dispatch(
        validate(null, dispatchValue, this.get('renderModel'), this.get('validators'), RSVP.all)
      )
    } else {
      const newModel = _.get(newAttrs, 'bunsenModel.value')
      const newModelPojo = isEmberObject(newModel) ? deemberify(newModel) : newModel
      const oldModel = _.get(oldAttrs, 'bunsenModel.value')
      const oldModelPojo = isEmberObject(oldModel) ? deemberify(oldModel) : oldModel
      const modelChanged = !_.isEqual(oldModelPojo, newModelPojo)

      if (modelChanged) {
        reduxStore.dispatch(
          validate(null, value, newModelPojo, this.get('validators'), RSVP.all)
        )
      }
    }

    this.validateProps()
  },
  /* eslint-enable complexity */

  // == Actions ================================================================

  actions: {
    /**
     * Nothing to handle, since value doesn't change for detail component
     */
    handleChange () {},

    /**
     * When a renderer has an error (not a validation issue, but more a logic error)
     * we report it back to the consumer. The main use-case here is API errors
     * for select renderers and custom renderers
     * @param {String} bunsenId - the busnen ID of the component that had an error
     * @param {BunsenValidationError[]} errors - the errors that occurred they're not actually validation errors,
     *                                           but it's a handy format to use for errors
     */
    handleError (bunsenId, errors) {
      if (this.onError) {
        this.onError(bunsenId, errors)
      }
    },

    /**
     * Change selected tab/root cell
     * @param {Number} tabIndex - index of root cell corresponding to tab
     */
    handleTabChange (tabIndex) {
      this.set('selectedTabIndex', tabIndex)
    },

    /**
     * Register a component for formValue changes
     * @param {Ember.Component} component - the component being registered
     */
    registerComponentForFormValueChanges (component) {
      component.formValueChanged(this.get('renderValue'))
      this.get('registeredComponents').push(component)
    }
  }
})
<|endoftext|>


<commit_before>'use strict';

angular.module('ngDependencyGraph')
  .value('Const', {
    // loader.js required, first introduced in 1.0
    AngularVersionRequired: '1.0.0',

    COOKIE_NAME: '__ngDependencyGraph',
    TOUR_KEY: 'tour_done',

    Events: {
      UPDATE_GRAPH: 'updateGraph',
      CHOOSE_NODE: 'chooseNode',
      INIT_MAIN: 'initMain'
    },

    ComponentType: {
      CONTROLLER: 'controller',
      DIRECTIVE: 'directive',
      SERVICE: 'service',
      FILTER: 'filter'
    },

    Scope: {
      COMPONENTS: 'components',
      MODULES: 'modules'
    },

    View: {
      HOVER_TRANSITION_TIME: '500'
    },

    FilterModules: {
      DEFAULT_FILTER: '',
      DEFAULT_IGNORE: 'ngLocale, ui.*, template*',
      DELIMITER: ','
    }

  });<commit_msg>feat(*): change default ignore list<commit_after>'use strict';

angular.module('ngDependencyGraph')
  .value('Const', {
    // loader.js required, first introduced in 1.0
    AngularVersionRequired: '1.0.0',

    COOKIE_NAME: '__ngDependencyGraph',
    TOUR_KEY: 'tour_done',

    Events: {
      UPDATE_GRAPH: 'updateGraph',
      CHOOSE_NODE: 'chooseNode',
      INIT_MAIN: 'initMain'
    },

    ComponentType: {
      CONTROLLER: 'controller',
      DIRECTIVE: 'directive',
      SERVICE: 'service',
      FILTER: 'filter'
    },

    Scope: {
      COMPONENTS: 'components',
      MODULES: 'modules'
    },

    View: {
      HOVER_TRANSITION_TIME: '500'
    },

    FilterModules: {
      DEFAULT_FILTER: '',
      DEFAULT_IGNORE: 'ngLocale, ui.*, *.html',
      DELIMITER: ','
    }

  });<|endoftext|>


<commit_before>import {Vector3} from 'three';
import {ControlsModule} from '../ControlsModule';

import {ThreeOrbitControls} from './lib/ThreeOrbitControls';

export class OrbitControlsModule extends ControlsModule {
  constructor(params = {}, patchEvents = true) {
    super(params, patchEvents);

    this.params = Object.assign({
      follow: false,
      object: null,
      target: new Vector3(0, 0, 0)
    }, params);
  }

  manager(manager) {
    const object = this.params.object
      ? this.params.object
      : manager.get('camera').native;

    const controls = new ThreeOrbitControls(
      object,
      manager.get('element'),
      manager.handler
    );

    const {params} = this;

    const updateProcessor = params.follow ? c => {
      controls.update(c.getDelta());
      controls.target.copy(params.target);
    } : c => {
      controls.update(c.getDelta());
    };

    this.setControls(controls);
    this.setUpdate(updateProcessor);

    manager.update({
      camera: camera => {
        if (this.params.object) return;
        controls.object = camera.native;
      }
    });

    controls.target.copy(params.target);
  }
}
<commit_msg>Fix .native<commit_after>import {Vector3} from 'three';
import {ControlsModule} from '../ControlsModule';

import {ThreeOrbitControls} from './lib/ThreeOrbitControls';

export class OrbitControlsModule extends ControlsModule {
  constructor(params = {}, patchEvents = true) {
    super(params, patchEvents);

    this.params = Object.assign({
      follow: false,
      object: null,
      target: new Vector3(0, 0, 0)
    }, params);
  }

  manager(manager) {
    const object = this.params.object
      ? this.params.object.native
      : manager.get('camera').native;

    const controls = new ThreeOrbitControls(
      object,
      manager.get('element'),
      manager.handler
    );

    const {params} = this;

    const updateProcessor = params.follow ? c => {
      controls.update(c.getDelta());
      controls.target.copy(params.target);
    } : c => {
      controls.update(c.getDelta());
    };

    this.setControls(controls);
    this.setUpdate(updateProcessor);

    manager.update({
      camera: camera => {
        if (this.params.object) return;
        controls.object = camera.native;
      }
    });

    controls.target.copy(params.target);
  }
}
<|endoftext|>


<commit_before>describe("autosubmit-plugin", function() {
    var pattern;

    requireDependencies(["patterns/autosubmit"], function(cls) {
        pattern = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("parse", function() {
        it("Shorthand notation", function() {
            var $trigger = $("<input data-pat-autosubmit='500'/>");
                options = pattern.parse($trigger);
            expect(options.delay).toBe("500");
        });

        it("Multiple options not accepted", function() {
            var $trigger = $("<input data-pat-autosubmit='500 && 400'/>");
                options = pattern.parse($trigger);
            expect(options.delay).toBe("500");
        });
    });

    describe("validateOptions", function() {
        it("Integer delay", function() {
            var options = pattern.validateOptions({delay: 500});
            expect(options.delay).toBe(500);
        });

        it("String integer delay", function() {
            var options = pattern.validateOptions({delay: "500"});
            expect(options.delay).toBe(500);
        });

        it("Delay keyword", function() {
            var options = pattern.validateOptions({delay: "delay"});
            expect(options.delay).toBe(400);
        });

        it("Delay set to true", function() {
            var options = pattern.validateOptions({delay: "true"});
            expect(options.delay).toBe(400);
        });

        it("Invalid syntax", function() {
            var options = pattern.validateOptions({delay: "invalid"});
            expect(options).toBeFalsy();
        });

        it("Bad type", function() {
            var options = pattern.validateOptions({delay: [500]});
            expect(options).toBeFalsy();
        });

        it("Negative delay", function() {
            var options = pattern.validateOptions({delay: -500});
            expect(options).toBeFalsy();
        });

    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<commit_msg>Autosubmit: Update validateOptions tests<commit_after>describe("autosubmit-plugin", function() {
    var pattern;

    requireDependencies(["patterns/autosubmit"], function(cls) {
        pattern = cls;
    });

    // Reset the lab before each test
    beforeEach(function() {
        $("#lab *").remove();
    });

    describe("parse", function() {
        it("Shorthand notation", function() {
            var $trigger = $("<input data-pat-autosubmit='500'/>");
                options = pattern.parse($trigger);
            expect(options.delay).toBe("500");
        });

        it("Multiple options not accepted", function() {
            var $trigger = $("<input data-pat-autosubmit='500 && 400'/>");
                options = pattern.parse($trigger);
            expect(options.delay).toBe("500");
        });
    });

    describe("validateOptions", function() {
        var defaultKeyupDelay = 400;  // as defined in patterns/autosubmit.js

        it("Integer delay", function() {
            var options = pattern.validateOptions({delay: 500});
            expect(options.delay).toBe(500);
        });

        it("String integer delay", function() {
            var options = pattern.validateOptions({delay: "500"});
            expect(options.delay).toBe(500);
        });

        it("Delay keyword", function() {
            var options = pattern.validateOptions({delay: "delay"});
            expect(options.delay).toBe(defaultKeyupDelay);
        });

        it("Delay set to true", function() {
            var options = pattern.validateOptions({delay: "true"});
            expect(options.delay).toBe(defaultKeyupDelay);
        });

        it("Invalid syntax", function() {
            var options = pattern.validateOptions({delay: "invalid"});
            expect(options.delay).toBe(defaultKeyupDelay);
        });

        it("Bad type", function() {
            var options = pattern.validateOptions({delay: [500]});
            expect(options.delay).toBe(defaultKeyupDelay);
        });

        it("Negative delay", function() {
            var options = pattern.validateOptions({delay: -500});
            expect(options.delay).toBe(defaultKeyupDelay);
        });

    });
});

// jshint indent: 4, browser: true, jquery: true, quotmark: double
// vim: sw=4 expandtab
<|endoftext|>


<commit_before>// asynchronously load fonts
WebFontConfig = {
  google: {
    families: ["Alegreya:700", "Spectral:400,400i,700,700i"]
  }
};

// if( cookie( fullCSSKey ) ){
//   (function(d) {
//     var wf = d.createElement('script'), s = d.scripts[0];
//     wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.28/webfont.js';
//     s.parentNode.insertBefore(wf, s);
//   })(document);
// };

$(document).ready(function() {
  // SVG for Everybody init
  svg4everybody();

  // smooth scroll init
  $("a").smoothScroll({ offset: -20 });

  // add lightbox class to all image links
  $("a[href$='.jpg'], a[href$='.png'], a[href$='.gif']").attr("data-lity", "");

  // Bigfoot footnotes
  var bigfoot = $.bigfoot({
    actionOriginalFN: 'delete',
    buttonMarkup: (
      '
' +
      ' <button href="#" class="bigfoot-footnote__button" rel="footnote"' +
      ' id="{{SUP:data-footnote-backlink-ref}}"' +
      ' data-footnote-number="{{FOOTNOTENUM}}"' +
      ' data-footnote-identifier="{{FOOTNOTEID}}"' +
      ' alt="See Footnote {{FOOTNOTENUM}}"' +
      ' data-bigfoot-footnote="{{FOOTNOTECONTENT}}">' +
      ' {{FOOTNOTENUM}}' +
      ' </button>' +
      '
'
    )
  });

  // Page cover object-fit fix
  var userAgent, ieReg, ie;
  userAgent = window.navigator.userAgent;
  ieReg = /msie|Trident.*rv[ :]*11\./gi;
  ie = ieReg.test(userAgent);

  if(ie) {
    $(".page__cover").each(function () {
      var $container = $(this),
          imgUrl = $container.find("img").prop("src");
      if (imgUrl) {
        $container.css("backgroundImage", 'url(' + imgUrl + ')').addClass("custom-object-fit");
      }
    });
  }
});

// Animate sidebar menu items
var menuItems = document.querySelectorAll("#menu-main-navigation li");

// Get vendor transition property
var docElemStyle = document.documentElement.style;
var transitionProp =
  typeof docElemStyle.transition == "string"
    ? "transition"
    : "WebkitTransition";

function animateMenuItems() {
  for (var i = 0; i < menuItems.length; i++) {
    var item = menuItems[i];
    // Stagger transition with transitionDelay
    item.style[transitionProp + "Delay"] = i * 75 + "ms";
    item.classList.toggle("is--moved");
  }
}

var myHeader = document.querySelector(".site__header");
var myMenu = document.querySelector(".menu__overlay");
var myToggle = document.querySelector(".menu__toggle");

// Toggle overlay visibility
function toggleClassMenu() {
  myMenu.classList.add("is--animatable");
  if (!myMenu.classList.contains("is--visible")) {
    myHeader.classList.add("is--inverted");
    myMenu.classList.add("is--visible");
    myToggle.classList.add("open");
  } else {
    myHeader.classList.remove("is--inverted");
    myMenu.classList.remove("is--visible");
    myToggle.classList.remove("open");
  }
}

function MenuOnTransitionEnd() {
  myMenu.classList.remove("is--animatable");
}

myMenu.addEventListener("transitionend", MenuOnTransitionEnd, false);
myToggle.addEventListener("click", function() {
  toggleClassMenu();
  animateMenuItems();
}, false);

// Static comments
(function($) {
  var $comments = $(".js-comments");

  $("#comment-form").submit(function() {
    var form = this;

    $(form).addClass("disabled");
    $("#comment-form-submit").html(
      '<svg class="icon spin"><use xlink:href="/assets/icons/icons.svg#icon-loading"></use></svg> Loading...'
    );

    $.ajax({
      type: $(this).attr("method"),
      url: $(this).attr("action"),
      data: $(this).serialize(),
      contentType: "application/x-www-form-urlencoded",
      success: function(data) {
        $("#comment-form-submit")
          .html("Submitted")
          .addClass("btn--disabled");
        $("#comment-form .js-notice")
          .removeClass("danger")
          .addClass("success");
        showAlert(
          'Thanks for your comment! It is currently pending and will show on the site once approved.'
        );
      },
      error: function(err) {
        console.log(err);
        $("#comment-form-submit").html("Submit Comment");
        $("#comment-form .js-notice")
          .removeClass("success")
          .addClass("danger");
        showAlert(
          "Sorry, there was an error with your submission. Please make sure all required fields have been completed and try again."
        );
        $(form).removeClass("disabled");
      }
    });

    return false;
  });

  function showAlert(message) {
    $("#comment-form .js-notice").removeClass("hidden");
    $("#comment-form .js-notice-text").html(message);
  }
})(jQuery);

// Staticman comment replies
// modified from Wordpress https://core.svn.wordpress.org/trunk/wp-includes/js/comment-reply.js
// Released under the GNU General Public License - https://wordpress.org/about/gpl/
var addComment = {
  moveForm: function(commId, parentId, respondId, postId) {
    var div,
      element,
      style,
      cssHidden,
      t = this,
      comm = t.I(commId),
      respond = t.I(respondId),
      cancel = t.I("cancel-comment-reply-link"),
      parent = t.I("comment-replying-to"),
      post = t.I("comment-post-slug"),
      commentForm = respond.getElementsByTagName("form")[0];

    if (!comm || !respond || !cancel || !parent || !commentForm) {
      return;
    }

    t.respondId = respondId;
    postId = postId || false;

    if (!t.I("sm-temp-form-div")) {
      div = document.createElement("div");
      div.id = "sm-temp-form-div";
      div.style.display = "none";
      respond.parentNode.insertBefore(div, respond);
    }

    comm.parentNode.insertBefore(respond, comm.nextSibling);
    if (post && postId) {
      post.value = postId;
    }
    parent.value = parentId;
    cancel.style.display = "";

    cancel.onclick = function() {
      var t = addComment,
        temp = t.I("sm-temp-form-div"),
        respond = t.I(t.respondId);

      if (!temp || !respond) {
        return;
      }

      t.I("comment-replying-to").value = null;
      temp.parentNode.insertBefore(respond, temp);
      temp.parentNode.removeChild(temp);
      this.style.display = "none";
      this.onclick = null;
      return false;
    };

    /*
     * Set initial focus to the first form focusable element.
     * Try/catch used just to avoid errors in IE 7- which return visibility
     * 'inherit' when the visibility value is inherited from an ancestor.
     */
    try {
      for (var i = 0; i < commentForm.elements.length; i++) {
        element = commentForm.elements[i];
        cssHidden = false;

        // Modern browsers.
        if ("getComputedStyle" in window) {
          style = window.getComputedStyle(element);
          // IE 8.
        } else if (document.documentElement.currentStyle) {
          style = element.currentStyle;
        }

        /*
         * For display none, do the same thing jQuery does. For visibility,
         * check the element computed style since browsers are already doing
         * the job for us. In fact, the visibility computed style is the actual
         * computed value and already takes into account the element ancestors.
         */
        if (
          (element.offsetWidth <= 0 && element.offsetHeight <= 0) ||
          style.visibility === "hidden"
        ) {
          cssHidden = true;
        }

        // Skip form elements that are hidden or disabled.
        if ("hidden" === element.type || element.disabled || cssHidden) {
          continue;
        }

        element.focus();
        // Stop after the first focusable element.
        break;
      }
    } catch (er) {}

    return false;
  },

  I: function(id) {
    return document.getElementById(id);
  }
};
<commit_msg>Remove unused variable<commit_after>// asynchronously load fonts
WebFontConfig = {
  google: {
    families: ["Alegreya:700", "Spectral:400,400i,700,700i"]
  }
};

// if( cookie( fullCSSKey ) ){
//   (function(d) {
//     var wf = d.createElement('script'), s = d.scripts[0];
//     wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.28/webfont.js';
//     s.parentNode.insertBefore(wf, s);
//   })(document);
// };

$(document).ready(function() {
  // SVG for Everybody init
  svg4everybody();

  // smooth scroll init
  $("a").smoothScroll({ offset: -20 });

  // add lightbox class to all image links
  $("a[href$='.jpg'], a[href$='.png'], a[href$='.gif']").attr("data-lity", "");

  // Bigfoot footnotes
  var bigfoot = $.bigfoot({
    actionOriginalFN: 'delete',
    buttonMarkup: (
      '
' +
      ' <button href="#" class="bigfoot-footnote__button" rel="footnote"' +
      ' id="{{SUP:data-footnote-backlink-ref}}"' +
      ' data-footnote-number="{{FOOTNOTENUM}}"' +
      ' data-footnote-identifier="{{FOOTNOTEID}}"' +
      ' alt="See Footnote {{FOOTNOTENUM}}"' +
      ' data-bigfoot-footnote="{{FOOTNOTECONTENT}}">' +
      ' {{FOOTNOTENUM}}' +
      ' </button>' +
      '
'
    )
  });

  // Page cover object-fit fix
  var userAgent, ieReg, ie;
  userAgent = window.navigator.userAgent;
  ieReg = /msie|Trident.*rv[ :]*11\./gi;
  ie = ieReg.test(userAgent);

  if(ie) {
    $(".page__cover").each(function () {
      var $container = $(this),
          imgUrl = $container.find("img").prop("src");
      if (imgUrl) {
        $container.css("backgroundImage", 'url(' + imgUrl + ')').addClass("custom-object-fit");
      }
    });
  }
});

// Animate sidebar menu items
var menuItems = document.querySelectorAll("#menu-main-navigation li");

// Get vendor transition property
var docElemStyle = document.documentElement.style;
var transitionProp =
  typeof docElemStyle.transition == "string"
    ? "transition"
    : "WebkitTransition";

function animateMenuItems() {
  for (var i = 0; i < menuItems.length; i++) {
    var item = menuItems[i];
    // Stagger transition with transitionDelay
    item.style[transitionProp + "Delay"] = i * 75 + "ms";
    item.classList.toggle("is--moved");
  }
}

var myHeader = document.querySelector(".site__header");
var myMenu = document.querySelector(".menu__overlay");
var myToggle = document.querySelector(".menu__toggle");

// Toggle overlay visibility
function toggleClassMenu() {
  myMenu.classList.add("is--animatable");
  if (!myMenu.classList.contains("is--visible")) {
    myHeader.classList.add("is--inverted");
    myMenu.classList.add("is--visible");
    myToggle.classList.add("open");
  } else {
    myHeader.classList.remove("is--inverted");
    myMenu.classList.remove("is--visible");
    myToggle.classList.remove("open");
  }
}

function MenuOnTransitionEnd() {
  myMenu.classList.remove("is--animatable");
}

myMenu.addEventListener("transitionend", MenuOnTransitionEnd, false);
myToggle.addEventListener("click", function() {
  toggleClassMenu();
  animateMenuItems();
}, false);

// Static comments
(function($) {
  $("#comment-form").submit(function() {
    var form = this;

    $(form).addClass("disabled");
    $("#comment-form-submit").html(
      '<svg class="icon spin"><use xlink:href="/assets/icons/icons.svg#icon-loading"></use></svg> Loading...'
    );

    $.ajax({
      type: $(this).attr("method"),
      url: $(this).attr("action"),
      data: $(this).serialize(),
      contentType: "application/x-www-form-urlencoded",
      success: function(data) {
        $("#comment-form-submit")
          .html("Submitted")
          .addClass("btn--disabled");
        $("#comment-form .js-notice")
          .removeClass("danger")
          .addClass("success");
        showAlert(
          'Thanks for your comment! It is currently pending and will show on the site once approved.'
        );
      },
      error: function(err) {
        console.log(err);
        $("#comment-form-submit").html("Submit Comment");
        $("#comment-form .js-notice")
          .removeClass("success")
          .addClass("danger");
        showAlert(
          "Sorry, there was an error with your submission. Please make sure all required fields have been completed and try again."
        );
        $(form).removeClass("disabled");
      }
    });

    return false;
  });

  function showAlert(message) {
    $("#comment-form .js-notice").removeClass("hidden");
    $("#comment-form .js-notice-text").html(message);
  }
})(jQuery);

// Staticman comment replies
// modified from Wordpress https://core.svn.wordpress.org/trunk/wp-includes/js/comment-reply.js
// Released under the GNU General Public License - https://wordpress.org/about/gpl/
var addComment = {
  moveForm: function(commId, parentId, respondId, postId) {
    var div,
      element,
      style,
      cssHidden,
      t = this,
      comm = t.I(commId),
      respond = t.I(respondId),
      cancel = t.I("cancel-comment-reply-link"),
      parent = t.I("comment-replying-to"),
      post = t.I("comment-post-slug"),
      commentForm = respond.getElementsByTagName("form")[0];

    if (!comm || !respond || !cancel || !parent || !commentForm) {
      return;
    }

    t.respondId = respondId;
    postId = postId || false;

    if (!t.I("sm-temp-form-div")) {
      div = document.createElement("div");
      div.id = "sm-temp-form-div";
      div.style.display = "none";
      respond.parentNode.insertBefore(div, respond);
    }

    comm.parentNode.insertBefore(respond, comm.nextSibling);
    if (post && postId) {
      post.value = postId;
    }
    parent.value = parentId;
    cancel.style.display = "";

    cancel.onclick = function() {
      var t = addComment,
        temp = t.I("sm-temp-form-div"),
        respond = t.I(t.respondId);

      if (!temp || !respond) {
        return;
      }

      t.I("comment-replying-to").value = null;
      temp.parentNode.insertBefore(respond, temp);
      temp.parentNode.removeChild(temp);
      this.style.display = "none";
      this.onclick = null;
      return false;
    };

    /*
     * Set initial focus to the first form focusable element.
     * Try/catch used just to avoid errors in IE 7- which return visibility
     * 'inherit' when the visibility value is inherited from an ancestor.
     */
    try {
      for (var i = 0; i < commentForm.elements.length; i++) {
        element = commentForm.elements[i];
        cssHidden = false;

        // Modern browsers.
        if ("getComputedStyle" in window) {
          style = window.getComputedStyle(element);
          // IE 8.
        } else if (document.documentElement.currentStyle) {
          style = element.currentStyle;
        }

        /*
         * For display none, do the same thing jQuery does. For visibility,
         * check the element computed style since browsers are already doing
         * the job for us. In fact, the visibility computed style is the actual
         * computed value and already takes into account the element ancestors.
         */
        if (
          (element.offsetWidth <= 0 && element.offsetHeight <= 0) ||
          style.visibility === "hidden"
        ) {
          cssHidden = true;
        }

        // Skip form elements that are hidden or disabled.
        if ("hidden" === element.type || element.disabled || cssHidden) {
          continue;
        }

        element.focus();
        // Stop after the first focusable element.
        break;
      }
    } catch (er) {}

    return false;
  },

  I: function(id) {
    return document.getElementById(id);
  }
};
<|endoftext|>


<commit_before>/*!
 * Description:
 *
 *
 * Author:  Henrik Grönvall
 * File:
 * Version: 0.0.1
 * Created on 2016-10-16
 */
import React from 'react';

require('./book.css');

const DisplayMode = (props) => {
  const { setListing, setThumbnail, displayMode } = props;
  const switchToListing = () => {
    setListing();
  };

  const switchToThumbnail = () => {
    setThumbnail();
  };

  const styles = {
    radio: {
      marginLeft: '10px',
      cursor: 'pointer',
    },

    radiospan: {
      marginLeft: '20px',
      fontFamily: 'tahoma',
      fontSize: '16px',
    },
  };

  return (

        Thumbnail

      <input
        type="radio"
        name="display"
        style={styles.radio}
        onChange={switchToThumbnail}
        checked={displayMode === 'THUMBNAIL'}
        value="thumbnail"
      />

        List

      <input
        type="radio"
        name="display"
        style={styles.radio}
        onChange={switchToListing}
        checked={displayMode !== 'THUMBNAIL'}
        value="list"
      />

  );
};

DisplayMode.contextTypes = {
  store: React.PropTypes.object.isRequired,
};

DisplayMode.propTypes = {
  setListing: React.PropTypes.func.isRequired,
  setThumbnail: React.PropTypes.func.isRequired,
  displayMode: React.PropTypes.string.isRequired,
};

export default DisplayMode;
<commit_msg>Updated documentation<commit_after>/*!
 * Description: DisplayMode stateless function component
 *
 * The component renders radio button used to select how the search result
 * should be rendered.
 *
 * The app component hierarchy looks like this:
 *
 * App
 *  - ControlsContainer
 *   - TopicSelectorContainer
 *    - TopicSelector
 *   - DisplayModeContainer
 *    - DisplayMode (*)
 *   - HistoryContainer
 *    - History
 *  - BooksContainer
 *   - Book
 *   - Book
 *   - ...
 *  - StateViewerContainer
 *
 * The component gets props from the DisplayModeContainer component;
 * - displayMode, string containing the current value of the radio field.
 * - setListing, action creator function to bind value when changing display mode.
 * - setThumbnail, action creator function to bind value when changing display mode.
 *
 *
 * Author:  Henrik Grönvall
 * File:
 * Version: 0.0.1
 * Created on 2016-10-16
 */
import React from 'react';

require('./book.css');

/**
 * DisplayMode stateless function component
 * @param setListing
 * @param setThumbnail
 * @param displayMode
 * @returns {XML}
 * @constructor
 */
const DisplayMode = ({setListing,setThumbnail,displayMode}) => {
  // Switch to list mode
  const switchToListing = () => {
    setListing();
  };

  // Switch to thumbnail mode
  const switchToThumbnail = () => {
    setThumbnail();
  };

  const styles = {
    radio: {
      marginLeft: '10px',
      cursor: 'pointer',
    },

    radiospan: {
      marginLeft: '20px',
      fontFamily: 'tahoma',
      fontSize: '16px',
    },
  };

  // Render component
  return (

        Thumbnail

      <input
        type="radio"
        name="display"
        style={styles.radio}
        onChange={switchToThumbnail}
        checked={displayMode === 'THUMBNAIL'}
        value="thumbnail"
      />

        List

      <input
        type="radio"
        name="display"
        style={styles.radio}
        onChange={switchToListing}
        checked={displayMode !== 'THUMBNAIL'}
        value="list"
      />

  );
};

/**
 * DisplayMode props
 * @type {{setListing: *, setThumbnail: *, displayMode: *}}
 */
DisplayMode.propTypes = {
  setListing: React.PropTypes.func.isRequired,
  setThumbnail: React.PropTypes.func.isRequired,
  displayMode: React.PropTypes.string.isRequired,
};

/**
 * Export the DisplayMode component
 */
export default DisplayMode;
<|endoftext|>


<commit_before>import _ from 'lodash';
import Joi from 'joi';
import sendEmail from '../../../../shared/lib/send-exchange-email';
import {validate} from './common';

const schema = Joi.object().keys({
  'submit': Joi.any().optional().strip()
});

const title = 'Summary';
const key = 'summary';
const nextStep = 'end';

function summaryGetHandler(request, reply) {
  request.log(['cookie'], request.state.data);
  const data = _.get(request, 'state.data', {});
  return reply
    .view('register-form/summary', {data, title});
}

function summaryPostHandler(request, reply) {
  validate(request.payload, schema)
    .then(value => {
      const data = _.get(request, 'state.data', {});
      request.server.plugins.NunjucksConfig.nunjucksEnv.render(
        'email/registration-summary.njk',
        {data: data}
      ).then(emailText => {
        sendEmail(
          process.env.EMAIL_USERNAME,
          emailText,
          'Patient registration'
        ).then(() => {
          return reply
            .redirect(request.aka(nextStep))
            .state('data', _.merge({}, request.state.data, {[key]: value}));
        }).catch(err => {
          throw err;
        });
      });
    })
    .catch(err => {
      request.log(['error'], err);
      return reply
        .redirect(request.aka(`register-form:${key}`));
    });
}

const handlers = {
  GET: summaryGetHandler,
  POST: summaryPostHandler
};

exports.options = {
  title,
  schema,
  handlers
};

export default [key, exports.options];
<commit_msg>Separate renderTemplate and emailGP for testing<commit_after>import _ from 'lodash';
import Joi from 'joi';
import sendEmail from '../../../../shared/lib/send-exchange-email';
import {validate} from './common';

const schema = Joi.object().keys({
  'submit': Joi.any().optional().strip()
});

const title = 'Summary';
const key = 'summary';
const nextStep = 'end';

function summaryGetHandler(request, reply) {
  request.log(['cookie'], request.state.data);
  const data = _.get(request, 'state.data', {});
  return reply
    .view('register-form/summary', {data, title});
}

async function renderTemplate(env, context) {
  return await env.render(
    'email/registration-summary.njk',
    context
  );
}

function emailGP(emailText) {
  return sendEmail(
    process.env.EMAIL_USERNAME,  //TODO - Get GP email from API
    emailText,
    'Patient registration'
  );
}

function summaryPostHandler(request, reply) {
  validate(request.payload, schema)
    .then(async value => {
      const data = _.get(request, 'state.data', {});

      const emailText = await renderTemplate(
        request.server.plugins.NunjucksConfig.nunjucksEnv,
        {data: data});

      emailGP(emailText)
        .then(() => {
          return reply
            .redirect(request.aka(nextStep))
            .state('data', _.merge({}, request.state.data, {[key]: value}));
        })
        .catch(err => {
          throw err;
        });
    })
    .catch(err => {
      request.log(['error'], err);
      return reply
        .redirect(request.aka(`register-form:${key}`));
    });
}

const handlers = {
  GET: summaryGetHandler,
  POST: summaryPostHandler
};

exports.options = {
  title,
  schema,
  handlers
};

export default [key, exports.options];
<|endoftext|>


<commit_before>(function($){$.fn.focusify=function(args){var methods={ns:'focusify',st:{classname:'infocus',parent:null,sibling:null},handleFocusBlur:function(){var $this=$(this),_this=methods,$el;if(_this.st.sibling&&_this.st.parent){$el=$this.siblings(_this.st.sibling).add($this.parents(_this.st.parent));}else if(_this.st.sibling){$el=$this.siblings(_this.st.sibling);}else if(_this.st.parent){$el=$this.parents(_this.st.parent);}else{$el=$this.prev();}$el.toggleClass(_this.st.classname);},init:function(opts){var _this=methods;$.extend(_this.st,opts||{});this.each(function(){if(!$.data(this,_this.ns)){$(this).bind('focus.'+_this.ns+' blur.'+_this.ns,_this.handleFocusBlur);$.data(this,_this.ns,true);}});},destroy:function(){var _this=methods;this.each(function(){$(this).unbind('.'+_this.ns);$.removeData(this,_this.ns);});}};if(arguments.length&&args==='destroy'){methods.destroy.call(this);}else{methods.init.call(this,args);}return this;};})(jQuery);<commit_msg>Edited focusify.min.js via GitHub<commit_after>/*
 * Focusify jQuery Plugin v1.0
 * http://andrewleeart.com
 *
 * Copyright (c) 2011 Andrew A. Lee
 *
 * Dual licensed under the MIT and GPL licenses, located in
 * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
 *
 * Date: 08/12/2011
 */

(function($){$.fn.focusify=function(args){var methods={ns:'focusify',st:{classname:'infocus',parent:null,sibling:null},handleFocusBlur:function(){var $this=$(this),_this=methods,$el;if(_this.st.sibling&&_this.st.parent){$el=$this.siblings(_this.st.sibling).add($this.parents(_this.st.parent));}else if(_this.st.sibling){$el=$this.siblings(_this.st.sibling);}else if(_this.st.parent){$el=$this.parents(_this.st.parent);}else{$el=$this.prev();}$el.toggleClass(_this.st.classname);},init:function(opts){var _this=methods;$.extend(_this.st,opts||{});this.each(function(){if(!$.data(this,_this.ns)){$(this).bind('focus.'+_this.ns+' blur.'+_this.ns,_this.handleFocusBlur);$.data(this,_this.ns,true);}});},destroy:function(){var _this=methods;this.each(function(){$(this).unbind('.'+_this.ns);$.removeData(this,_this.ns);});}};if(arguments.length&&args==='destroy'){methods.destroy.call(this);}else{methods.init.call(this,args);}return this;};})(jQuery);<|endoftext|>


<commit_before>var api = require('../api');

module.exports = {
  route: 'locations[{keys:query}][{ranges}]["id","name","departures"]',
  get: function(pathSets) {
      var query = pathSets.query[0];

      return api
        .getLocations(query)
        .then(function(locations) {
          return locations.reduce(function(acc, location, i) {
            pathSets[3].forEach(function(key) {
              acc.push({ path: ['locations', query, i, key], value: location[key] });
            });

            // Location ref
            acc.push({
              path: ['locations', query, i, 'departures'],
              value: { $type: 'ref', $expires: 30, value: ['departures', '"' + location.id + '"'] }
            });

            return acc;
          }, []);
        })
        .catch(function(err) {
          console.error(err.stack);
        });
  }
};
<commit_msg>Change expires into miliseconds<commit_after>var api = require('../api');

module.exports = {
  route: 'locations[{keys:query}][{ranges}]["id","name","departures"]',
  get: function(pathSets) {
      var query = pathSets.query[0];

      return api
        .getLocations(query)
        .then(function(locations) {
          return locations.reduce(function(acc, location, i) {
            pathSets[3].forEach(function(key) {
              acc.push({ path: ['locations', query, i, key], value: location[key] });
            });

            // Location ref
            acc.push({
              path: ['locations', query, i, 'departures'],
              value: { $type: 'ref', $expires: -30 * 1000, value: ['departures', '"' + location.id + '"'] }
            });

            return acc;
          }, []);
        })
        .catch(function(err) {
          console.error(err.stack);
        });
  }
};
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'form',
  class: 'form-horizontal',
  classNameBindings: ['class'],
  attributeBindings: ['action'],
  properties: Ember.A([]),
  action: 'submit',
  submitButtonClass: 'btn btn-primary',
  submitText: 'Submit',
  cancelButtonClass: 'btn btn-default',
  cancelText: 'Cancel',

  notifyGroup(pid, property, message='', revalidate=true) {
    const childViews = this.get('childViews'),
          group     = _.detect(childViews, c => c.get('pid') === pid);
    if (!message && !revalidate) message = this.getMessage(property);
    if (revalidate)              message = this.validateProperty(property);
    group.set('message', message);
  },

  validateProperty(propertyKey) {
      this.get('model').validate({only: propertyKey});
      return this.getMessage(propertyKey);
    },

  getMessage(propertyKey) {
    const errors      = this.get('model.errors.content'),
          errorObject = _.detect(errors, 'attribute', propertyKey);
    return _.get(errorObject, 'message[0]', '');
  },

  clearAll() {
    const childViews = this.get('childViews'),
          properties = this.get('properties');
    _.each(properties, p => {
      const group = _.detect(childViews, c => c.get('pid') === p.pid);
      if (group) group.clearErrors();
    });
  },

  submit(e) {
    if (e) e.preventDefault();
    this.clearAll();
    const bool   = this.get('model').validate(),
          errors = this.get('model.errors.content');
    if (bool) return this.sendAction('submitAction');
    _.each(errors, e => {
      const pid = _.result(_.detect(this.get('properties'), p => {
        if (e) return _.contains(p.properties, e.attribute);
      }), 'pid');
      if (pid) this.notifyGroup(pid, e.attribute, e.message, false);
    });
  },

  actions: {
    cancel() {
      this.sendAction('cancelAction');
    },
  },

});
<commit_msg>Avoid name collision<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'form',
  class: 'form-horizontal',
  classNameBindings: ['class'],
  attributeBindings: ['action'],
  properties: Ember.A([]),
  action: 'submit',
  submitButtonClass: 'btn btn-primary',
  submitText: 'Submit',
  cancelButtonClass: 'btn btn-default',
  cancelText: 'Cancel',

  notifyGroup(pid, property, message='', revalidate=true) {
    const childViews = this.get('childViews'),
          group     = _.detect(childViews, c => c.get('pid') === pid);
    if (!message && !revalidate) message = this.getMessage(property);
    if (revalidate)              message = this.validateProperty(property);
    group.set('message', message);
  },

  validateProperty(propertyKey) {
      this.get('model').validate({only: propertyKey});
      return this.getMessage(propertyKey);
    },

  getMessage(propertyKey) {
    const errors      = this.get('model.errors.content'),
          errorObject = _.detect(errors, 'attribute', propertyKey);
    return _.get(errorObject, 'message[0]', '');
  },

  clearAll() {
    const childViews = this.get('childViews'),
          properties = this.get('properties');
    _.each(properties, p => {
      const group = _.detect(childViews, c => c.get('pid') === p.pid);
      if (group) group.clearErrors();
    });
  },

  submit(e) {
    if (e) e.preventDefault();
    this.clearAll();
    const bool   = this.get('model').validate(),
          errors = this.get('model.errors.content');
    if (bool) return this.sendAction('submitAction');
    _.each(errors, err => {
      const pid = _.result(_.detect(this.get('properties'), p => {
        if (err) return _.contains(p.properties, err.attribute);
      }), 'pid');
      if (pid) this.notifyGroup(pid, err.attribute, err.message, false);
    });
  },

  actions: {
    cancel() {
      this.sendAction('cancelAction');
    },
  },

});
<|endoftext|>


<commit_before>const fixtures = require('../../../fixtures')
const { assertBreadcrumbs } = require('../../../support/utils')

const url = `/companies/${fixtures.company.lambdaPlc.id}/advisers/add`

describe('Add Adviser', () => {
  it('Should display the add Lead ITA confirmation page', () => {
    cy.visit(url)

    assertBreadcrumbs({
      'Home': '/',
      'Companies': '/companies',
      'Lambda plc': '/companies/0fb3379c-341c-4da4-b825-bf8d47b26baa',
      'Confirm you are the Lead ITA': undefined,
    })

    cy.get('h1')
      .contains('Confirm you are the Lead ITA')

    cy.get('main')
      .children()
      .first()
      .get('h3').as('h3').eq(0)
      .contains('Do you want to add yourself as the first point of contact?')
      .next()
      .contains('How do I add someone else as the Lead ITA?')
      .as('detail-summary')

    cy.get('@h3').eq(1)
      .contains('What happens next?')
      .next()
      .as('list')
      .should($element => expect($element.prop('tagName')).to.equal('UL'))
      .find('li')
      .contains('Your name and team will be displayed on top of the company page, as well as in the Lead Adviser tab')
      .next()
      .contains('This will also replace Lead ITAs set on any subsidiaries of this company')
      .next()
      .contains('Other ITAs will be able to replace you as the Lead ITA for the company')

    cy.get('@list')
      .next()
      .contains('Add myself as Lead ITA')
      .as('submit')
      .next()
      .contains('Cancel')

    cy
      .contains(
        'You can only add yourself as the Lead ITA. If you think another ' +
        'International Trade Adviser is the first point of contact for this ' +
        'company, they will need to add themselves.'
      )
      .as('detail-content')
      .should('not.be.visible')

    cy.get('@detail-summary')
      .click()

    cy.get('@detail-content')
      .should('be.visible')

    cy.get('@submit')
      .click()

    cy.get('[role="alert"]')
      .contains('Lead adviser information updated')
  })
})
<commit_msg>Fixed long lines<commit_after>const fixtures = require('../../../fixtures')
const { assertBreadcrumbs } = require('../../../support/utils')

const url = `/companies/${fixtures.company.lambdaPlc.id}/advisers/add`

describe('Add Adviser', () => {
  it('Should display the add Lead ITA confirmation page', () => {
    cy.visit(url)

    assertBreadcrumbs({
      'Home': '/',
      'Companies': '/companies',
      'Lambda plc': '/companies/0fb3379c-341c-4da4-b825-bf8d47b26baa',
      'Confirm you are the Lead ITA': undefined,
    })

    cy.get('h1')
      .contains('Confirm you are the Lead ITA')

    cy.get('main')
      .children()
      .first()
      .get('h3').as('h3').eq(0)
      .contains('Do you want to add yourself as the first point of contact?')
      .next()
      .contains('How do I add someone else as the Lead ITA?')
      .as('detail-summary')

    cy.get('@h3').eq(1)
      .contains('What happens next?')
      .next()
      .as('list')
      .should($element => expect($element.prop('tagName')).to.equal('UL'))
      .find('li')
      .contains(
        'Your name and team will be displayed on top of the company page, ' +
        'as well as in the Lead Adviser tab'
      )
      .next()
      .contains(
        'This will also replace Lead ITAs set on ' +
        'any subsidiaries of this company'
      )
      .next()
      .contains(
        'Other ITAs will be able to replace you as the Lead ITA for the company'
      )

    cy.get('@list')
      .next()
      .contains('Add myself as Lead ITA')
      .as('submit')
      .next()
      .contains('Cancel')

    cy
      .contains(
        'You can only add yourself as the Lead ITA. If you think another ' +
        'International Trade Adviser is the first point of contact for this ' +
        'company, they will need to add themselves.'
      )
      .as('detail-content')
      .should('not.be.visible')

    cy.get('@detail-summary')
      .click()

    cy.get('@detail-content')
      .should('be.visible')

    cy.get('@submit')
      .click()

    cy.get('[role="alert"]')
      .contains('Lead adviser information updated')
  })
})
<|endoftext|>


<commit_before>var global = (typeof window !== 'undefined') ? window : {},
    Ember = global.Ember;

/**
  The base for all authorizers. __This serves as a starting point for
  implementing custom authorizers and must not be used directly.__

  __The authorizer preprocesses all XHR requests__ (except ones to 3rd party
  origins, see [SimpleAuth.setup](#Ember-SimpleAuth-setup)) and makes
  sure they have the required data attached that allows the server to identify
  the user making the request. This data might be a specific header, data in
  the query part of the URL, cookies etc. __The authorizer has to fit the
  authenticator__ (see
  [SimpleAuth.Authenticators.Base](#Ember-SimpleAuth-Authenticators-Base))
  as it relies on data that the authenticator retrieved during authentication
  and that it makes available through the session.

  @class Base
  @namespace SimpleAuth.Authorizers
  @module simple-auth/authorizers/base
  @extends Ember.Object
*/
export default Ember.Object.extend({
  /**
    The session the authorizer gets the data it needs to authorize requests
    from (see [SimpleAuth.Session](#Ember-SimpleAuth-Session)).

    @property session
    @readOnly
    @type SimpleAuth.Session
    @default the session instance that is created during SimpleAuth' setup (see [SimpleAuth.setup](#Ember-SimpleAuth-setup))
  */
  session: null,

  /**
    Authorizes an XHR request by adding some sort of secret information that
    allows the server to identify the user making the request (e.g. a token in
    the `Authorization` header or some other secret in the query string etc.).

    `SimpleAuth.Authorizers.Base`'s implementation does nothing.

    @method authorize
    @param {jqXHR} jqXHR The XHR request to authorize (see http://api.jquery.com/jQuery.ajax/#jqXHR)
    @param {Object} requestOptions The options as provided to the `$.ajax` method (see http://api.jquery.com/jQuery.ajaxPrefilter/)
  */
  authorize: function(jqXHR, requestOptions) {
  }
});
<commit_msg>updated docs for the base authorizer<commit_after>var global = (typeof window !== 'undefined') ? window : {},
    Ember = global.Ember;

/**
  The base for all authorizers. __This serves as a starting point for
  implementing custom authorizers and must not be used directly.__

  __The authorizer preprocesses all XHR requests__ (except ones to 3rd party
  origins, see
  [Configuration.crossOriginWhitelist](#SimpleAuth-Configuration-crossOriginWhitelist))
  and makes sure they have the required data attached that allows the server to
  identify the user making the request. This data might be an HTTP header,
  query string parameters in the URL, cookies etc. __The authorizer has to fit
  the authenticator__ (see
  [SimpleAuth.Authenticators.Base](#SimpleAuth-Authenticators-Base))
  as it relies on data that the authenticator acquires during authentication.

  @class Base
  @namespace SimpleAuth.Authorizers
  @module simple-auth/authorizers/base
  @extends Ember.Object
*/
export default Ember.Object.extend({
  /**
    The session the authorizer gets the data it needs to authorize requests
    from.

    @property session
    @readOnly
    @type SimpleAuth.Session
    @default the session instance
  */
  session: null,

  /**
    Authorizes an XHR request by adding some sort of secret information that
    allows the server to identify the user making the request (e.g. a token in
    the `Authorization` header or some other secret in the query string etc.).

    `SimpleAuth.Authorizers.Base`'s implementation does nothing.

    @method authorize
    @param {jqXHR} jqXHR The XHR request to authorize (see http://api.jquery.com/jQuery.ajax/#jqXHR)
    @param {Object} requestOptions The options as provided to the `$.ajax` method (see http://api.jquery.com/jQuery.ajaxPrefilter/)
  */
  authorize: function(jqXHR, requestOptions) {
  }
});
<|endoftext|>


<commit_before>import React from 'react'
import Form from './components/form.js'
import Input from './components/input.js'
import UnboundInput from './components/unbound_input.js'
import Submit from './components/submit.js'
import FormErrorList from './components/form_error_list.js'
import Fieldset from "./components/fieldset.js"
import FieldsetText from "./components/fieldset_text.js"

export const form = React.createFactory(Form)
export const input = React.createFactory(Input)
export const unboundInput = React.createFactory(UnboundInput)
export const submit = React.createFactory(Submit)
export const formErrorList = React.createFactory(FormErrorList)
export const fieldset = React.createFactory(Fieldset)
export const fieldsetText = React.createFactory(FieldsetText)
<commit_msg>fix factories (double quote)<commit_after>import React from 'react'
import Form from './components/form.js'
import Input from './components/input.js'
import UnboundInput from './components/unbound_input.js'
import Submit from './components/submit.js'
import FormErrorList from './components/form_error_list.js'
import Fieldset from './components/fieldset.js'
import FieldsetText from './components/fieldset_text.js'

export const form = React.createFactory(Form)
export const input = React.createFactory(Input)
export const unboundInput = React.createFactory(UnboundInput)
export const submit = React.createFactory(Submit)
export const formErrorList = React.createFactory(FormErrorList)
export const fieldset = React.createFactory(Fieldset)
export const fieldsetText = React.createFactory(FieldsetText)
<|endoftext|>


<commit_before>/*!
 * Description: StateViewer component.
 *
 * The StateViewer component will render the application state which is located
 * in Redux store.
 *
 *
 * Author:  Henrik Grönvall
 * File:
 * Version: 0.0.1
 * Created on 2016-10-16
 */
import React from 'react';

/**
 * StateView stateless function component
 * @param topic
 * @param books
 * @param currentStatus
 * @param displayMode
 * @param history
 * @returns {XML}
 * @constructor
 */
const StateViewer = ({ topic, books, currentStatus, displayMode, history }) => {
  const styles = {
    container: {
      margin: '20px',
      width: '400px',
      fontFamily: 'tahoma',
    },
    title: {
      fontSize: '24px',
      marginTop: '25px',
    },
    state: {
      marginTop: '10px',
    },
    hr: {
      marginTop: '50px',
    },
  };

  return (

        Application State

        Topic: {topic}

        Display mode:      { displayMode }

        Current status:    { currentStatus }

        Books displayed:   { books.length }

        Actions processed: { history.past.length + history.future.length + 1 }

        Current action:    { history.past.length + 1 }

  );
};

/**
 * Property definitions for the component
 * @type {{books: *, currentStatus: *, displayMode: *, history: *, topic: *}}
 */
StateViewer.propTypes = {
  books: React.PropTypes.array.isRequired,
  currentStatus: React.PropTypes.string.isRequired,
  displayMode: React.PropTypes.string.isRequired,
  history: React.PropTypes.object.isRequired,
  topic: React.PropTypes.string.isRequired,
};

/**
 * Export the StateViewer component
 */
export default StateViewer;
<commit_msg>Updated documentation<commit_after>/*!
 * Description: StateViewer component.
 *
 * The StateViewer component will render the application state which is located
 * in Redux store.
 *
 * The app component hierarchy looks like this:
 *
 * App
 *  - ControlsContainer
 *   - TopicSelectorContainer
 *    - TopicSelector (*)
 *   - DisplayModeContainer
 *    - DisplayMode
 *   - HistoryContainer
 *    - History
 *  - BooksContainer
 *   - Book
 *   - Book
 *   - ...
 *  - StateViewerContainer
 *   - StateViewer (*)
 *
 * The component gets props from the StateViewerContainer component;
 * - books, array of books,
 * - topic, string of search term,
 * - currentStatus, string displaying the state status,
 * - displayMode, string containing the text the user entered
 * - history, state history.
 *
 *
 *
 * Author:  Henrik Grönvall
 * File:
 * Version: 0.0.1
 * Created on 2016-10-16
 */
import React from 'react';

/**
 * StateView stateless function component
 * @param topic
 * @param books
 * @param currentStatus
 * @param displayMode
 * @param history
 * @returns {XML}
 * @constructor
 */
const StateViewer = ({topic,books,currentStatus,displayMode,history}) => {
  const styles = {
    container: {
      margin: '20px',
      width: '400px',
      fontFamily: 'tahoma',
    },
    title: {
      fontSize: '24px',
      marginTop: '25px',
    },
    state: {
      marginTop: '10px',
    },
    hr: {
      marginTop: '50px',
    },
  };

  return (

        Application State

        Topic: {topic}

        Display mode:      { displayMode }

        Current status:    { currentStatus }

        Books displayed:   { books.length }

        Actions processed: { history.past.length + history.future.length + 1 }

        Current action:    { history.past.length + 1 }

  );
};

/**
 * Property definitions for the component
 * @type {{books: *, currentStatus: *, displayMode: *, history: *, topic: *}}
 */
StateViewer.propTypes = {
  books: React.PropTypes.array.isRequired,
  currentStatus: React.PropTypes.string.isRequired,
  displayMode: React.PropTypes.string.isRequired,
  history: React.PropTypes.object.isRequired,
  topic: React.PropTypes.string.isRequired,
};

/**
 * Export the StateViewer component
 */
export default StateViewer;
<|endoftext|>


<commit_before>/*!
 * @author      Angelo Dini - github.com/finalangel/classjs-plugins
 * @copyright   Distributed under the BSD License.
 */

/*
 * TESTS
 */

var uniform = new Cl.Uniform();

module('cl.uniform.js', {
    setup: function () {
        var fixture = $('#qunit-fixture');
        fixture.append([
            '
',
                '<form class="form1" action="."><input type="radio" name="x" value="1" checked="checked" /><input type="radio" name="x" value="2" /></form>',
                '<form class="form2" action="."><input type="radio" name="x" value="3" checked="checked" /><input type="radio" name="x" value="4" /></form>',
                '
',
                    '<input type="radio" name="x" value="5" />',
                    '<input type="radio" name="x" value="6" />',
                    '<input type="radio" name="x" value="7" checked="checked" />',
                    '<input type="radio" name="x" value="8" />',
                '
',
            '
'
        ].join(''));
        fixture.append('<form action="." method="post" class="frm frm-upload-1"><input type="file" class="uniform" /></form>');
        fixture.append([
            '<form action="." method="post" class="frm frm-upload-2">',
                '<fieldset>',
                    '
File field
',
                    '
upload <input type="file" class="uniform" />
',
                    '
upload <input type="file" class="uniform" disabled="disabled" />
',
                '</fieldset>',
                '<fieldset>',
                    '
Select field
',
                    '
choose <select class="uniform"><option value="">Select 1</option><option>Select 2</option><option>Select 3</option></select>
',
                    '
choose <select class="uniform" disabled><option value="">Select 1</option><option>Select 2</option><option>Select 3</option></select>
',
                '</fieldset>',
                '
',
                    '<fieldset>',
                        '
Radio field
',
                        '
<input type="radio" name="radiogroup1" class="uniform" /> radiogroup 1
',
                        '
<input type="radio" name="radiogroup1" class="uniform" id="field-radiotest" required="required" /> radiogroup 1
',
                        '
<input type="radio" name="radiogroup1" class="uniform" checked="checked" /> radiogroup checked
',
                        '
<input type="radio" name="radiogroup1" class="uniform" disabled="disabled" /> radiogroup disabled
',
                    '</fieldset>',
                '
',
                '
',
                    '<fieldset>',
                        '
Checkbox field
',
                        '
<input type="checkbox" name="check1" class="uniform" /> checkbox 1
',
                        '
<input type="checkbox" name="check3" class="uniform" id="field-checktest" required="required" /> checkbox 3
',
                        '
<input type="checkbox" name="check4" class="uniform" checked="checked" /> checkbox checked
',
                        '
<input type="checkbox" name="check5" class="uniform" disabled="disabled" /> checkbox disabled
',
                    '</fieldset>',
                '
',
            '</form>'
        ].join(''));
        fixture.find('form').on('submit', function (e) {
            e.preventDefault();
        });

        new Cl.Uniform('.uniformed input:radio');
        new Cl.Uniform('.frm .uniform');
    }
});

test('Options', function() {
    var options = ['offset'];
    var defaults = [-9999];
    // tests
    $.each(options, function (index, option) {
        deepEqual(uniform.options[option], defaults[index], option + ' is available');
    });

    // custom checks
    var cls = uniform.options.cls;
    equal(cls.prefix, 'uniform', 'prefix is available');
    equal(cls.radio, 'radio', 'radio is available');
    equal(cls.checkbox, 'checkbox', 'checkbox is available');
    equal(cls.file, 'file', 'file is available');
    equal(cls.select, 'select', 'select is available');
    equal(cls.disabled, 'disabled', 'disabled is available');
    equal(cls.focus, 'focus', 'focus is available');
    equal(cls.ready, 'ready', 'ready is available');

    var lang = uniform.options.lang;
    equal(lang.fileBtn, 'Upload', 'fileBtn is available');
    equal(lang.fileStatus, 'Please select a file...', 'fileStatus is available');

    var clsLength = getLength(uniform.options.cls);
    ok(clsLength === 8, 'there are ' + clsLength + ' cls options');

    var langLength = getLength(uniform.options.lang);
    ok(langLength === 2, 'there are ' + clsLength + ' lang options');

    var tplLength = getLength(uniform.options.tpl);
    ok(tplLength === 5, 'there are ' + tplLength + ' tpl options');

    var length = getLength(uniform.options);
    ok(length === 4, 'there are ' + length + ' options');
});

test('Methods', function() {
    var methods = ['update', 'destroy'];
    // tests
    $.each(methods, function (index, method) {
        equal(typeof(uniform[method]), 'function', method + ' is available');
    });

    // check method count
    ok(methods.length === 2, 'there are ' + methods.length + ' methods');
});

test('Test for issue #41: Uniform Upload in IE', function() {
    var fixture = $('#qunit-fixture');
    var upload = fixture.find('.frm-upload-1 input[type="file"]');

    ok(upload.length === 1, 'upload field is available.');
});

test('Test Uniform File Upload', function() {
    var fixture = $('#qunit-fixture');
    var upload = fixture.find('.frm-upload-2 input[type="file"]');

    // Basic Test if HTML is available
    ok(upload.length === 2, 'all three upload fields are available.');
    ok(upload.eq(1).prop('disabled') === true, 'second upload is disabled.');

    // set Focus to active file upload
    upload.eq(0).trigger('focus');
    ok($(document.activeElement).prop('tagName') === 'INPUT', 'file upload is focusable');
    // reset Focus
    upload.eq(0).trigger('blur');

    upload.eq(1).trigger('focus');
    ok($(document.activeElement).prop('tagName') === 'BODY', 'disabled file upload is not focusable');
});

test('Test Uniform Radio button', function() {
    var fixture = $('#qunit-fixture');
    var radio = fixture.find('.frm-upload-2 input[type="radio"]');
    var fakeClick = function (el) {
        var ev = document.createEvent('MouseEvent');
        ev.initMouseEvent(
            'click',
            true /* bubble */, true /* cancelable */,
            window, null,
            0, 0, 0, 0, /* coordinates */
            false, false, false, false, /* modifier keys */
            0 /*left*/, null
        );
        el.dispatchEvent(ev);
    };

    // Basic Test if HTML is available
    ok(radio.length === 4, 'all four radio fields are available.');
    ok(radio.eq(1).prop('required') === true, 'second radio is required.');
    ok(radio.eq(2).prop('checked') === true, 'third radio is checked.');
    ok(radio.eq(3).prop('disabled') === true, 'last radio is disabled.');

    // test if span get applied
    ok(radio.eq(0).parent().prop('tagName') === 'SPAN', 'parent span got applied.');
    ok(radio.eq(0).siblings().prop('tagName') === 'SPAN', 'sibling span got applied.');
    ok(radio.eq(0).siblings().length === 1, 'there is only the knob as sibling.');
    ok(radio.eq(0).siblings().is(':visible') === false, 'knob is not visible when radio is not checked, inital state.');
    ok(radio.eq(2).siblings().is(':visible') === true, 'knob is visible when radio is checked, inital state.');
    ok(radio.eq(3).parent().hasClass('uniform-disabled') === true, 'parent gets class disabled when radio is disabled.');

    // normal focus
    radio.eq(0).trigger('focus');
    ok($(document.activeElement).prop('tagName') === 'INPUT', 'radio is focusable');
    ok(radio.eq(0).parent().hasClass('uniform-focus') === true, 'radio span has class uniform-focus');
    // reset Focus
    radio.eq(0).trigger('blur');

    // normal click
    radio.eq(1).trigger('click');
    ok($(document.activeElement).prop('tagName') === 'INPUT', 'radio is set to current focus after click on radio.');
    ok(radio.eq(1).siblings().is(':visible') === true, 'knob changed to visible after click on radio.');
    ok(radio.eq(2).siblings().is(':visible') === false, 'inital state changed after click on a radio.');

    // click on label
    // radio.eq(0).parents('label').trigger('click');
    fakeClick(radio.eq(0).parents('label')[0]); // trigger fake click because phantomjs does not bubble down to radio
    ok(radio.eq(0).siblings().is(':visible') === true, 'knob changed to visible after click on label.');

    // radio trigger change
    radio.eq(1).trigger('change');
    ok(radio.eq(1).siblings().is(':visible') === true, 'knob changed to visible after trigger change on radio.');
});

test('Test for issue #59: radios with same name across different forms', function () {
    var fixture = $('#qunit-fixture');

    equal(fixture.find('.form1').find('input:radio:checked').val(), '1', 'initial values are ok');
    equal(fixture.find('.form2').find('input:radio:checked').val(), '3', 'initial values are ok');
    // NOTE: these tests are commented because PhantomJS currently incorrectly handles radio groups that are injected/modified
    // https://github.com/ariya/phantomjs/issues/12039
    // equal(fixture.find('.not-a-form').find('input:radio:checked').val(), '7', 'initial values are ok');
});

test('Test for issue #59: radios with same name across different forms', function () {
    var fixture = $('#qunit-fixture');
    fixture.find('.form1').find('input:radio:last').prop('checked', true).trigger('change');

    equal(fixture.find('.form1').find('input:radio:checked').val(), '2', 'change in the form affects only that form');
    equal(fixture.find('.form2').find('input:radio:checked').val(), '3', 'change in the form affects only that form');
    // equal(fixture.find('.not-a-form').find('input:radio:checked').val(), '7', 'change in the form affects only that form');
});

test('Test for issue #59: radios with same name across different forms', function () {
    var fixture = $('#qunit-fixture');
    fixture.find('.not-a-form').find('input:radio:first').prop('checked', true).trigger('change');

    equal(fixture.find('.form1').find('input:radio:checked').val(), '1', 'change outside of the form affects only radios that are outside of forms');
    equal(fixture.find('.form2').find('input:radio:checked').val(), '3', 'change outside of the form affects only radios that are outside of forms');
    equal(fixture.find('.not-a-form').find('input:radio:checked').val(), '5', 'change outside of the form affects only radios that are outside of forms');
});
<commit_msg>fix test for triggered change<commit_after>/*!
 * @author      Angelo Dini - github.com/finalangel/classjs-plugins
 * @copyright   Distributed under the BSD License.
 */

/*
 * TESTS
 */

var uniform = new Cl.Uniform();

module('cl.uniform.js', {
    setup: function () {
        var fixture = $('#qunit-fixture');
        fixture.append([
            '
',
                '<form class="form1" action="."><input type="radio" name="x" value="1" checked="checked" /><input type="radio" name="x" value="2" /></form>',
                '<form class="form2" action="."><input type="radio" name="x" value="3" checked="checked" /><input type="radio" name="x" value="4" /></form>',
                '
',
                    '<input type="radio" name="x" value="5" />',
                    '<input type="radio" name="x" value="6" />',
                    '<input type="radio" name="x" value="7" checked="checked" />',
                    '<input type="radio" name="x" value="8" />',
                '
',
            '
'
        ].join(''));
        fixture.append('<form action="." method="post" class="frm frm-upload-1"><input type="file" class="uniform" /></form>');
        fixture.append([
            '<form action="." method="post" class="frm frm-upload-2">',
                '<fieldset>',
                    '
File field
',
                    '
upload <input type="file" class="uniform" />
',
                    '
upload <input type="file" class="uniform" disabled="disabled" />
',
                '</fieldset>',
                '<fieldset>',
                    '
Select field
',
                    '
choose <select class="uniform"><option value="">Select 1</option><option>Select 2</option><option>Select 3</option></select>
',
                    '
choose <select class="uniform" disabled><option value="">Select 1</option><option>Select 2</option><option>Select 3</option></select>
',
                '</fieldset>',
                '
',
                    '<fieldset>',
                        '
Radio field
',
                        '
<input type="radio" name="radiogroup1" class="uniform" /> radiogroup 1
',
                        '
<input type="radio" name="radiogroup1" class="uniform" id="field-radiotest" required="required" /> radiogroup 1
',
                        '
<input type="radio" name="radiogroup1" class="uniform" checked="checked" /> radiogroup checked
',
                        '
<input type="radio" name="radiogroup1" class="uniform" disabled="disabled" /> radiogroup disabled
',
                    '</fieldset>',
                '
',
                '
',
                    '<fieldset>',
                        '
Checkbox field
',
                        '
<input type="checkbox" name="check1" class="uniform" /> checkbox 1
',
                        '
<input type="checkbox" name="check3" class="uniform" id="field-checktest" required="required" /> checkbox 3
',
                        '
<input type="checkbox" name="check4" class="uniform" checked="checked" /> checkbox checked
',
                        '
<input type="checkbox" name="check5" class="uniform" disabled="disabled" /> checkbox disabled
',
                    '</fieldset>',
                '
',
            '</form>'
        ].join(''));
        fixture.find('form').on('submit', function (e) {
            e.preventDefault();
        });

        new Cl.Uniform('.uniformed input:radio');
        new Cl.Uniform('.frm .uniform');
    }
});

test('Options', function() {
    var options = ['offset'];
    var defaults = [-9999];
    // tests
    $.each(options, function (index, option) {
        deepEqual(uniform.options[option], defaults[index], option + ' is available');
    });

    // custom checks
    var cls = uniform.options.cls;
    equal(cls.prefix, 'uniform', 'prefix is available');
    equal(cls.radio, 'radio', 'radio is available');
    equal(cls.checkbox, 'checkbox', 'checkbox is available');
    equal(cls.file, 'file', 'file is available');
    equal(cls.select, 'select', 'select is available');
    equal(cls.disabled, 'disabled', 'disabled is available');
    equal(cls.focus, 'focus', 'focus is available');
    equal(cls.ready, 'ready', 'ready is available');

    var lang = uniform.options.lang;
    equal(lang.fileBtn, 'Upload', 'fileBtn is available');
    equal(lang.fileStatus, 'Please select a file...', 'fileStatus is available');

    var clsLength = getLength(uniform.options.cls);
    ok(clsLength === 8, 'there are ' + clsLength + ' cls options');

    var langLength = getLength(uniform.options.lang);
    ok(langLength === 2, 'there are ' + clsLength + ' lang options');

    var tplLength = getLength(uniform.options.tpl);
    ok(tplLength === 5, 'there are ' + tplLength + ' tpl options');

    var length = getLength(uniform.options);
    ok(length === 4, 'there are ' + length + ' options');
});

test('Methods', function() {
    var methods = ['update', 'destroy'];
    // tests
    $.each(methods, function (index, method) {
        equal(typeof(uniform[method]), 'function', method + ' is available');
    });

    // check method count
    ok(methods.length === 2, 'there are ' + methods.length + ' methods');
});

test('Test for issue #41: Uniform Upload in IE', function() {
    var fixture = $('#qunit-fixture');
    var upload = fixture.find('.frm-upload-1 input[type="file"]');

    ok(upload.length === 1, 'upload field is available.');
});

test('Test Uniform File Upload', function() {
    var fixture = $('#qunit-fixture');
    var upload = fixture.find('.frm-upload-2 input[type="file"]');

    // Basic Test if HTML is available
    ok(upload.length === 2, 'all three upload fields are available.');
    ok(upload.eq(1).prop('disabled') === true, 'second upload is disabled.');

    // set Focus to active file upload
    upload.eq(0).trigger('focus');
    ok($(document.activeElement).prop('tagName') === 'INPUT', 'file upload is focusable');
    // reset Focus
    upload.eq(0).trigger('blur');

    upload.eq(1).trigger('focus');
    ok($(document.activeElement).prop('tagName') === 'BODY', 'disabled file upload is not focusable');
});

test('Test Uniform Radio button', function() {
    var fixture = $('#qunit-fixture');
    var radio = fixture.find('.frm-upload-2 input[type="radio"]');
    var fakeClick = function (el) {
        var ev = document.createEvent('MouseEvent');
        ev.initMouseEvent(
            'click',
            true /* bubble */, true /* cancelable */,
            window, null,
            0, 0, 0, 0, /* coordinates */
            false, false, false, false, /* modifier keys */
            0 /*left*/, null
        );
        el.dispatchEvent(ev);
    };

    // Basic Test if HTML is available
    ok(radio.length === 4, 'all four radio fields are available.');
    ok(radio.eq(1).prop('required') === true, 'second radio is required.');
    ok(radio.eq(2).prop('checked') === true, 'third radio is checked.');
    ok(radio.eq(3).prop('disabled') === true, 'last radio is disabled.');

    // test if span get applied
    ok(radio.eq(0).parent().prop('tagName') === 'SPAN', 'parent span got applied.');
    ok(radio.eq(0).siblings().prop('tagName') === 'SPAN', 'sibling span got applied.');
    ok(radio.eq(0).siblings().length === 1, 'there is only the knob as sibling.');
    ok(radio.eq(0).siblings().is(':visible') === false, 'knob is not visible when radio is not checked, inital state.');
    ok(radio.eq(2).siblings().is(':visible') === true, 'knob is visible when radio is checked, inital state.');
    ok(radio.eq(3).parent().hasClass('uniform-disabled') === true, 'parent gets class disabled when radio is disabled.');

    // normal focus
    radio.eq(0).trigger('focus');
    ok($(document.activeElement).prop('tagName') === 'INPUT', 'radio is focusable');
    ok(radio.eq(0).parent().hasClass('uniform-focus') === true, 'radio span has class uniform-focus');
    // reset Focus
    radio.eq(0).trigger('blur');

    // normal click
    radio.eq(1).trigger('click');
    ok($(document.activeElement).prop('tagName') === 'INPUT', 'radio is set to current focus after click on radio.');
    ok(radio.eq(1).siblings().is(':visible') === true, 'knob changed to visible after click on radio.');
    ok(radio.eq(2).siblings().is(':visible') === false, 'inital state changed after click on a radio.');

    // click on label
    // radio.eq(0).parents('label').trigger('click');
    fakeClick(radio.eq(0).parents('label')[0]); // trigger fake click because phantomjs does not bubble down to radio
    ok(radio.eq(0).siblings().is(':visible') === true, 'knob changed to visible after click on label.');

    // radio trigger change
    radio.eq(1).prop('checked', true).trigger('change');
    ok(radio.eq(1).siblings().is(':visible') === true, 'knob changed to visible after trigger change on radio.');
});

test('Test for issue #59: radios with same name across different forms', function () {
    var fixture = $('#qunit-fixture');

    equal(fixture.find('.form1').find('input:radio:checked').val(), '1', 'initial values are ok');
    equal(fixture.find('.form2').find('input:radio:checked').val(), '3', 'initial values are ok');
    // NOTE: these tests are commented because PhantomJS currently incorrectly handles radio groups that are injected/modified
    // https://github.com/ariya/phantomjs/issues/12039
    // equal(fixture.find('.not-a-form').find('input:radio:checked').val(), '7', 'initial values are ok');
});

test('Test for issue #59: radios with same name across different forms', function () {
    var fixture = $('#qunit-fixture');
    fixture.find('.form1').find('input:radio:last').prop('checked', true).trigger('change');

    equal(fixture.find('.form1').find('input:radio:checked').val(), '2', 'change in the form affects only that form');
    equal(fixture.find('.form2').find('input:radio:checked').val(), '3', 'change in the form affects only that form');
    // equal(fixture.find('.not-a-form').find('input:radio:checked').val(), '7', 'change in the form affects only that form');
});

test('Test for issue #59: radios with same name across different forms', function () {
    var fixture = $('#qunit-fixture');
    fixture.find('.not-a-form').find('input:radio:first').prop('checked', true).trigger('change');

    equal(fixture.find('.form1').find('input:radio:checked').val(), '1', 'change outside of the form affects only radios that are outside of forms');
    equal(fixture.find('.form2').find('input:radio:checked').val(), '3', 'change outside of the form affects only radios that are outside of forms');
    equal(fixture.find('.not-a-form').find('input:radio:checked').val(), '5', 'change outside of the form affects only radios that are outside of forms');
});
<|endoftext|>