<commit_before>import React, { PropTypes } from 'react';
import uncontrollable from 'uncontrollable';
import cn from 'classnames';
import {
    accessor
  , elementType
  , dateFormat
  , dateRangeFormat
  , views as componentViews } from './utils/propTypes';

import { notify } from './utils/helpers';
import { navigate, views } from './utils/constants';
import defaultFormats from './formats';
import viewLabel from './utils/viewLabel';
import moveDate from './utils/move';
import VIEWS from './Views';
import Toolbar from './Toolbar';
import EventWrapper from './EventWrapper';
import BackgroundWrapper from './BackgroundWrapper';

import omit from 'lodash/omit';
import defaults from 'lodash/defaults';
import transform from 'lodash/transform';
import mapValues from 'lodash/mapValues';

function viewNames(_views){
  return !Array.isArray(_views) ? Object.keys(_views) : _views
}

function isValidView(view, { views: _views }) {
  let names = viewNames(_views)
  return names.indexOf(view) !== -1
}

let now = new Date();

/**
 * react-big-calendar is full featured Calendar component for managing events and dates. It uses
 * modern `flexbox` for layout making it super responsive and performant. Leaving most of the layout heavy lifting
 * to the browser. __note:__ The default styles use `height: 100%` which means your container must set an explicit
 * height (feel free to adjust the styles to suit your specific needs).
 *
 * Big Calendar is unopiniated about editing and moving events, prefering to let you implement it in a way that makes
 * the most sense to your app. It also tries not to be prescriptive about your event data structures, just tell it
 * how to find the start and end datetimes and you can pass it whatever you want.
 *
 * One thing to note is that, `react-big-calendar` treats event start/end dates as an _exclusive_ range.
 * which means that the event spans up to, but not including, the end date. In the case
 * of displaying events on whole days, end dates are rounded _up_ to the next day. So an
 * event ending on `Apr 8th 12:00:00 am` will not appear on the 8th, whereas one ending
 * on `Apr 8th 12:01:00 am` will. If you want _inclusive_ ranges consider providing a
 * function `endAccessor` that returns the end date + 1 day for those events that end at midnight.
 */
let Calendar = React.createClass({

  propTypes: {

    /**
     * Props passed to main calendar `<div>`.
     */
    elementProps: PropTypes.object,

    /**
     * The current date value of the calendar. Determines the visible view range
     *
     * @controllable onNavigate
     */
    date: PropTypes.instanceOf(Date),

    /**
     * The current view of the calendar.
     *
     * @default 'month'
     * @controllable onView
     */
    view: PropTypes.string,

    /**
     * An array of event objects to display on the calendar
     */
    events: PropTypes.arrayOf(PropTypes.object),

    /**
     * Callback fired when the `date` value changes.
     *
     * @controllable date
     */
    onNavigate: PropTypes.func,

    /**
     * Callback fired when the `view` value changes.
     *
     * @controllable date
     */
    onView: PropTypes.func,

    /**
     * A callback fired when a date selection is made. Only fires when `selectable` is `true`.
     *
     * ```js
     * function(
     *   slotInfo: object {
     *     start: Date,
     *     end: Date,
     *     slots: array<Date>
     *   }
     * )
     * ```
     */
    onSelectSlot: PropTypes.func,

    /**
     * Callback fired when a calendar event is selected.
     *
     * ```js
     * function(event: object, e: SyntheticEvent)
     * ```
     */
    onSelectEvent: PropTypes.func,

    /**
     * Callback fired when dragging a selection in the Time views.
     *
     * Returning `false` from the handler will prevent a selection.
     *
     * ```js
     * function ({ start: Date, end: Date }) : boolean
     * ```
     */
    onSelecting: PropTypes.func,

    /**
     * An array of built-in view names to allow the calendar to display.
     *
     * @type Calendar.views
     * @default ['month', 'week', 'day', 'agenda']
     */
    views: componentViews,

    /**
     * The string name of the destination view for drill-down actions, such
     * as clicking a date header, or the truncated events links. If
     * `getDrilldownView` is also specified it will be used instead.
     *
     * Set to `null` to disable drill-down actions.
     *
     * ```js
     * <BigCalendar
     *   drilldownView="agenda"
     * />
     * ```
     */
    drilldownView: React.PropTypes.string,

    /**
     * Functionally equivilent to `drilldownView` but accepts a function
     * that can return a view name. It's useful for customizing the drill-down
     * actions depending on the target date and triggering view.
     *
     * Return `null` to disable drill-down actions.
     *
     * ```js
     * <BigCalendar
     *   getDrilldownView={(targetDate, currentViewName, configuredViewNames) =>
     *     if (currentViewName === 'month' && configuredViewNames.includes('week'))
     *       return 'week'
     *
     *     return null;
     *   }}
     * />
     * ```
     */
    getDrilldownView: React.PropTypes.func,

    /**
     * Determines whether the toolbar is displayed
     */
    toolbar: PropTypes.bool,

    /**
     * Show truncated events in an overlay when you click the "+_x_ more" link.
     */
    popup: PropTypes.bool,

    /**
     * Distance in pixels, from the edges of the viewport, the "show more" overlay should be positioned.
     *
     * ```js
     * <BigCalendar popupOffset={30}/>
     * <BigCalendar popupOffset={{x: 30, y: 20}}/>
     * ```
     */
    popupOffset: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.shape({ x: PropTypes.number, y: PropTypes.number })
    ]),
    /**
     * Allows mouse selection of ranges of dates/times.
     *
     * The 'ignoreEvents' option prevents selection code from running when a
     * drag begins over an event. Useful when you want custom event click or drag
     * logic
     */
    selectable: React.PropTypes.oneOf([true, false, 'ignoreEvents']),

    /**
     * Determines the selectable time increments in week and day views
     */
    step: React.PropTypes.number,

    /**
     * The number of slots per "section" in the time grid views. Adjust with `step`
     * to change the default of 1 hour long groups, with 30 minute slots.
     */
    timeslots: React.PropTypes.number,

    /**
     *Switch the calendar to a `right-to-left` read direction.
     */
    rtl: PropTypes.bool,

    /**
     * Optionally provide a function that returns an object of className or style props
     * to be applied to the the event node.
     *
     * ```js
     * function(
     * 	event: object,
     * 	start: date,
     * 	end: date,
     * 	isSelected: bool
     * ) -> { className: string?, style: object? }
     * ```
     */
    eventPropGetter: PropTypes.func,

    /**
     * Accessor for the event title, used to display event information. Should
     * resolve to a `renderable` value.
     *
     * @type {(func|string)}
     */
    titleAccessor: accessor,

    /**
     * Determines whether the event should be considered an "all day" event and ignore time.
     * Must resolve to a `boolean` value.
     *
     * @type {(func|string)}
     */
    allDayAccessor: accessor,

    /**
     * The start date/time of the event. Must resolve to a JavaScript `Date` object.
     *
     * @type {(func|string)}
     */
    startAccessor: accessor,

    /**
     * The end date/time of the event. Must resolve to a JavaScript `Date` object.
     *
     * @type {(func|string)}
     */
    endAccessor: accessor,

    /**
     * Constrains the minimum _time_ of the Day and Week views.
     */
    min: PropTypes.instanceOf(Date),

    /**
     * Constrains the maximum _time_ of the Day and Week views.
     */
    max: PropTypes.instanceOf(Date),

    /**
     * Determines how far down the scroll pane is initially scrolled down.
     */
    scrollToTime: PropTypes.instanceOf(Date),

    /**
     * Specify a specific culture code for the Calendar.
     *
     * **Note: it's generally better to handle this globally via your i18n library.**
     */
    culture: React.PropTypes.string,

    /**
     * Localizer specific formats, tell the Calendar how to format and display dates.
     *
     * `format` types are dependent on the configured localizer; both Moment and Globalize
     * accept strings of tokens according to their own specification, such as: `'DD mm yyyy'`.
     *
     * ```jsx
     * let formats = {
     *   dateFormat: 'dd',
     *
     *   dayFormat: (date, culture, localizer) =>
     *     localizer.format(date, 'DDD', culture),
     *
     *   dayRangeHeaderFormat: ({ start, end }, culture, local) =>
     *     local.format(start, { date: 'short' }, culture) + ' — ' +
     *     local.format(end, { date: 'short' }, culture)
     * }
     *
     * <Calendar formats={formats} />
     * ```
     *
     * All localizers accept a function of
     * the form `(date: Date, culture: ?string, localizer: Localizer) -> string`
     */
    formats: PropTypes.shape({
      /**
       * Format for the day of the month heading in the Month view.
       * e.g. "01", "02", "03", etc
       */
      dateFormat,

      /**
       * A day of the week format for Week and Day headings,
       * e.g. "Wed 01/04"
       *
       */
      dayFormat: dateFormat,

      /**
       * Week day name format for the Month week day headings,
       * e.g: "Sun", "Mon", "Tue", etc
       *
       */
      weekdayFormat: dateFormat,

      /**
       * The timestamp cell formats in Week and Time views, e.g. "4:00 AM"
       */
      timeGutterFormat: dateFormat,

      /**
       * Toolbar header format for the Month view, e.g "2015 April"
       *
       */
      monthHeaderFormat: dateFormat,

      /**
       * Toolbar header format for the Week views, e.g. "Mar 29 - Apr 04"
       */
      dayRangeHeaderFormat: dateRangeFormat,

      /**
       * Toolbar header format for the Day view, e.g. "Wednesday Apr 01"
       */
      dayHeaderFormat: dateFormat,

      /**
       * Toolbar header format for the Agenda view, e.g. "4/1/2015 — 5/1/2015"
       */
      agendaHeaderFormat: dateFormat,

      /**
       * A time range format for selecting time slots, e.g "8:00am — 2:00pm"
       */
      selectRangeFormat: dateRangeFormat,

      agendaDateFormat: dateFormat,
      agendaTimeFormat: dateFormat,
      agendaTimeRangeFormat: dateRangeFormat,

      /**
       * Time range displayed on events.
       */
      eventTimeRangeFormat: dateRangeFormat
    }),

    /**
     * Customize how different sections of the calendar render by providing custom Components.
     * In particular the `Event` component can be specified for the entire calendar, or you can
     * provide an individual component for each view type.
     *
     * ```jsx
     * let components = {
     *   event: MyEvent, // used by each view (Month, Day, Week)
     *   toolbar: MyToolbar,
     *   agenda: {
     *   	 event: MyAgendaEvent // with the agenda view use a different component to render events
     *   }
     * }
     * <Calendar components={components} />
     * ```
     */
    components: PropTypes.shape({
      event: elementType,
      eventWrapper: elementType,
      dayWrapper: elementType,
      dateCellWrapper: elementType,

      toolbar: elementType,

      agenda: PropTypes.shape({
        date: elementType,
        time: elementType,
        event: elementType
      }),

      day: PropTypes.shape({
        header: elementType,
        event: elementType
      }),
      week: PropTypes.shape({
        header: elementType,
        event: elementType
      }),
      month: PropTypes.shape({
        header: elementType,
        event: elementType
      })
    }),

    /**
     * String messages used throughout the component, override to provide localizations
     */
    messages: PropTypes.shape({
      allDay: PropTypes.node,
      previous: PropTypes.node,
      next: PropTypes.node,
      today: PropTypes.node,
      month: PropTypes.node,
      week: PropTypes.node,
      day: PropTypes.node,
      agenda: PropTypes.node,
      showMore: PropTypes.func
    })
  },

  getDefaultProps() {
    return {
      elementProps: {},
      popup: false,
      toolbar: true,
      view: views.MONTH,
      views: [views.MONTH, views.WEEK, views.DAY, views.AGENDA],
      date: now,
      step: 30,

      drilldownView: views.DAY,

      titleAccessor: 'title',
      allDayAccessor: 'allDay',
      startAccessor: 'start',
      endAccessor: 'end'
    };
  },

  getViews() {
    const views = this.props.views;

    if (Array.isArray(views)) {
      return transform(views, (obj, name) => obj[name] = VIEWS[name], {});
    }

    if (typeof views === 'object') {
      return mapValues(views, (value, key) => {
        if (value === true) {
          return VIEWS[key];
        }

        return value;
      });
    }

    return VIEWS;
  },

  getView() {
    const views = this.getViews();

    return views[this.props.view];
  },

  getDrilldownView(date) {
    const { view, drilldownView, getDrilldownView } = this.props

    if (!getDrilldownView) return drilldownView

    return getDrilldownView(date, view, Object.keys(this.getViews()));
  },

  render() {
    let {
        view, toolbar, events
      , culture
      , components = {}
      , formats = {}
      , style
      , className
      , elementProps
      , date: current
      , ...props } = this.props;

    formats = defaultFormats(formats)

    let View = this.getView();
    let names = viewNames(this.props.views)

    let viewComponents = defaults(
      components[view] || {},
      omit(components, names),
      {
        eventWrapper: EventWrapper,
        dayWrapper: BackgroundWrapper,
        dateCellWrapper: BackgroundWrapper
      }
    )

    let ToolbarToRender = components.toolbar || Toolbar

    return (
      <div
        {...elementProps}
        className={cn('rbc-calendar', className, {
          'rbc-rtl': props.rtl
        })}
        style={style}
      >
        {toolbar &&
          <ToolbarToRender
            date={current}
            view={view}
            views={names}
            label={viewLabel(current, view, formats, culture)}
            onViewChange={this.handleViewChange}
            onNavigate={this.handleNavigate}
            messages={this.props.messages}
          />
        }
        <View
          ref='view'
          {...props}
          {...formats}
          culture={culture}
          formats={undefined}
          events={events}
          date={current}
          components={viewComponents}
          getDrilldownView={this.getDrilldownView}
          onNavigate={this.handleNavigate}
          onDrillDown={this.handleDrillDown}
          onSelectEvent={this.handleSelectEvent}
          onSelectSlot={this.handleSelectSlot}
          onShowMore={this._showMore}
        />
      </div>
    );
  },

  handleNavigate(action, newDate) {
    let { view, date, onNavigate } = this.props;
    let ViewComponent = this.getView();

    date = moveDate(action, newDate || date, ViewComponent)

    onNavigate(date, view)
  },

  handleViewChange(view) {
    if (view !== this.props.view && isValidView(view, this.props))
      this.props.onView(view)
  },

  handleSelectEvent(...args) {
    notify(this.props.onSelectEvent, args)
  },

  handleSelectSlot(slotInfo) {
    notify(this.props.onSelectSlot, slotInfo)
  },

  handleDrillDown(date, view) {
    if (view)
      this.handleViewChange(view)

    this.handleNavigate(navigate.DATE, date)
  }
});

export default uncontrollable(Calendar, {
  view: 'onView',
  date: 'onNavigate',
  selected: 'onSelectEvent'
})
<commit_msg>fix typo<commit_after>import React, { PropTypes } from 'react';
import uncontrollable from 'uncontrollable';
import cn from 'classnames';
import {
    accessor
  , elementType
  , dateFormat
  , dateRangeFormat
  , views as componentViews } from './utils/propTypes';

import { notify } from './utils/helpers';
import { navigate, views } from './utils/constants';
import defaultFormats from './formats';
import viewLabel from './utils/viewLabel';
import moveDate from './utils/move';
import VIEWS from './Views';
import Toolbar from './Toolbar';
import EventWrapper from './EventWrapper';
import BackgroundWrapper from './BackgroundWrapper';

import omit from 'lodash/omit';
import defaults from 'lodash/defaults';
import transform from 'lodash/transform';
import mapValues from 'lodash/mapValues';

function viewNames(_views){
  return !Array.isArray(_views) ? Object.keys(_views) : _views
}

function isValidView(view, { views: _views }) {
  let names = viewNames(_views)
  return names.indexOf(view) !== -1
}

let now = new Date();

/**
 * react-big-calendar is full featured Calendar component for managing events and dates. It uses
 * modern `flexbox` for layout making it super responsive and performant. Leaving most of the layout heavy lifting
 * to the browser. __note:__ The default styles use `height: 100%` which means your container must set an explicit
 * height (feel free to adjust the styles to suit your specific needs).
 *
 * Big Calendar is unopiniated about editing and moving events, prefering to let you implement it in a way that makes
 * the most sense to your app. It also tries not to be prescriptive about your event data structures, just tell it
 * how to find the start and end datetimes and you can pass it whatever you want.
 *
 * One thing to note is that, `react-big-calendar` treats event start/end dates as an _exclusive_ range.
 * which means that the event spans up to, but not including, the end date. In the case
 * of displaying events on whole days, end dates are rounded _up_ to the next day. So an
 * event ending on `Apr 8th 12:00:00 am` will not appear on the 8th, whereas one ending
 * on `Apr 8th 12:01:00 am` will. If you want _inclusive_ ranges consider providing a
 * function `endAccessor` that returns the end date + 1 day for those events that end at midnight.
 */
let Calendar = React.createClass({

  propTypes: {

    /**
     * Props passed to main calendar `<div>`.
     */
    elementProps: PropTypes.object,

    /**
     * The current date value of the calendar. Determines the visible view range
     *
     * @controllable onNavigate
     */
    date: PropTypes.instanceOf(Date),

    /**
     * The current view of the calendar.
     *
     * @default 'month'
     * @controllable onView
     */
    view: PropTypes.string,

    /**
     * An array of event objects to display on the calendar
     */
    events: PropTypes.arrayOf(PropTypes.object),

    /**
     * Callback fired when the `date` value changes.
     *
     * @controllable date
     */
    onNavigate: PropTypes.func,

    /**
     * Callback fired when the `view` value changes.
     *
     * @controllable date
     */
    onView: PropTypes.func,

    /**
     * A callback fired when a date selection is made. Only fires when `selectable` is `true`.
     *
     * ```js
     * function(
     *   slotInfo: object {
     *     start: Date,
     *     end: Date,
     *     slots: array<Date>
     *   }
     * )
     * ```
     */
    onSelectSlot: PropTypes.func,

    /**
     * Callback fired when a calendar event is selected.
     *
     * ```js
     * function(event: object, e: SyntheticEvent)
     * ```
     */
    onSelectEvent: PropTypes.func,

    /**
     * Callback fired when dragging a selection in the Time views.
     *
     * Returning `false` from the handler will prevent a selection.
     *
     * ```js
     * function ({ start: Date, end: Date }) : boolean
     * ```
     */
    onSelecting: PropTypes.func,

    /**
     * An array of built-in view names to allow the calendar to display.
     *
     * @type Calendar.views
     * @default ['month', 'week', 'day', 'agenda']
     */
    views: componentViews,

    /**
     * The string name of the destination view for drill-down actions, such
     * as clicking a date header, or the truncated events links. If
     * `getDrilldownView` is also specified it will be used instead.
     *
     * Set to `null` to disable drill-down actions.
     *
     * ```js
     * <BigCalendar
     *   drilldownView="agenda"
     * />
     * ```
     */
    drilldownView: React.PropTypes.string,

    /**
     * Functionally equivalent to `drilldownView`, but accepts a function
     * that can return a view name. It's useful for customizing the drill-down
     * actions depending on the target date and triggering view.
     *
     * Return `null` to disable drill-down actions.
     *
     * ```js
     * <BigCalendar
     *   getDrilldownView={(targetDate, currentViewName, configuredViewNames) =>
     *     if (currentViewName === 'month' && configuredViewNames.includes('week'))
     *       return 'week'
     *
     *     return null;
     *   }}
     * />
     * ```
     */
    getDrilldownView: React.PropTypes.func,

    /**
     * Determines whether the toolbar is displayed
     */
    toolbar: PropTypes.bool,

    /**
     * Show truncated events in an overlay when you click the "+_x_ more" link.
     */
    popup: PropTypes.bool,

    /**
     * Distance in pixels, from the edges of the viewport, the "show more" overlay should be positioned.
     *
     * ```js
     * <BigCalendar popupOffset={30}/>
     * <BigCalendar popupOffset={{x: 30, y: 20}}/>
     * ```
     */
    popupOffset: PropTypes.oneOfType([
      PropTypes.number,
      PropTypes.shape({ x: PropTypes.number, y: PropTypes.number })
    ]),
    /**
     * Allows mouse selection of ranges of dates/times.
     *
     * The 'ignoreEvents' option prevents selection code from running when a
     * drag begins over an event. Useful when you want custom event click or drag
     * logic
     */
    selectable: React.PropTypes.oneOf([true, false, 'ignoreEvents']),

    /**
     * Determines the selectable time increments in week and day views
     */
    step: React.PropTypes.number,

    /**
     * The number of slots per "section" in the time grid views. Adjust with `step`
     * to change the default of 1 hour long groups, with 30 minute slots.
     */
    timeslots: React.PropTypes.number,

    /**
     *Switch the calendar to a `right-to-left` read direction.
     */
    rtl: PropTypes.bool,

    /**
     * Optionally provide a function that returns an object of className or style props
     * to be applied to the the event node.
     *
     * ```js
     * function(
     * 	event: object,
     * 	start: date,
     * 	end: date,
     * 	isSelected: bool
     * ) -> { className: string?, style: object? }
     * ```
     */
    eventPropGetter: PropTypes.func,

    /**
     * Accessor for the event title, used to display event information. Should
     * resolve to a `renderable` value.
     *
     * @type {(func|string)}
     */
    titleAccessor: accessor,

    /**
     * Determines whether the event should be considered an "all day" event and ignore time.
     * Must resolve to a `boolean` value.
     *
     * @type {(func|string)}
     */
    allDayAccessor: accessor,

    /**
     * The start date/time of the event. Must resolve to a JavaScript `Date` object.
     *
     * @type {(func|string)}
     */
    startAccessor: accessor,

    /**
     * The end date/time of the event. Must resolve to a JavaScript `Date` object.
     *
     * @type {(func|string)}
     */
    endAccessor: accessor,

    /**
     * Constrains the minimum _time_ of the Day and Week views.
     */
    min: PropTypes.instanceOf(Date),

    /**
     * Constrains the maximum _time_ of the Day and Week views.
     */
    max: PropTypes.instanceOf(Date),

    /**
     * Determines how far down the scroll pane is initially scrolled down.
     */
    scrollToTime: PropTypes.instanceOf(Date),

    /**
     * Specify a specific culture code for the Calendar.
     *
     * **Note: it's generally better to handle this globally via your i18n library.**
     */
    culture: React.PropTypes.string,

    /**
     * Localizer specific formats, tell the Calendar how to format and display dates.
     *
     * `format` types are dependent on the configured localizer; both Moment and Globalize
     * accept strings of tokens according to their own specification, such as: `'DD mm yyyy'`.
     *
     * ```jsx
     * let formats = {
     *   dateFormat: 'dd',
     *
     *   dayFormat: (date, culture, localizer) =>
     *     localizer.format(date, 'DDD', culture),
     *
     *   dayRangeHeaderFormat: ({ start, end }, culture, local) =>
     *     local.format(start, { date: 'short' }, culture) + ' — ' +
     *     local.format(end, { date: 'short' }, culture)
     * }
     *
     * <Calendar formats={formats} />
     * ```
     *
     * All localizers accept a function of
     * the form `(date: Date, culture: ?string, localizer: Localizer) -> string`
     */
    formats: PropTypes.shape({
      /**
       * Format for the day of the month heading in the Month view.
       * e.g. "01", "02", "03", etc
       */
      dateFormat,

      /**
       * A day of the week format for Week and Day headings,
       * e.g. "Wed 01/04"
       *
       */
      dayFormat: dateFormat,

      /**
       * Week day name format for the Month week day headings,
       * e.g: "Sun", "Mon", "Tue", etc
       *
       */
      weekdayFormat: dateFormat,

      /**
       * The timestamp cell formats in Week and Time views, e.g. "4:00 AM"
       */
      timeGutterFormat: dateFormat,

      /**
       * Toolbar header format for the Month view, e.g "2015 April"
       *
       */
      monthHeaderFormat: dateFormat,

      /**
       * Toolbar header format for the Week views, e.g. "Mar 29 - Apr 04"
       */
      dayRangeHeaderFormat: dateRangeFormat,

      /**
       * Toolbar header format for the Day view, e.g. "Wednesday Apr 01"
       */
      dayHeaderFormat: dateFormat,

      /**
       * Toolbar header format for the Agenda view, e.g. "4/1/2015 — 5/1/2015"
       */
      agendaHeaderFormat: dateFormat,

      /**
       * A time range format for selecting time slots, e.g "8:00am — 2:00pm"
       */
      selectRangeFormat: dateRangeFormat,

      agendaDateFormat: dateFormat,
      agendaTimeFormat: dateFormat,
      agendaTimeRangeFormat: dateRangeFormat,

      /**
       * Time range displayed on events.
       */
      eventTimeRangeFormat: dateRangeFormat
    }),

    /**
     * Customize how different sections of the calendar render by providing custom Components.
     * In particular the `Event` component can be specified for the entire calendar, or you can
     * provide an individual component for each view type.
     *
     * ```jsx
     * let components = {
     *   event: MyEvent, // used by each view (Month, Day, Week)
     *   toolbar: MyToolbar,
     *   agenda: {
     *   	 event: MyAgendaEvent // with the agenda view use a different component to render events
     *   }
     * }
     * <Calendar components={components} />
     * ```
     */
    components: PropTypes.shape({
      event: elementType,
      eventWrapper: elementType,
      dayWrapper: elementType,
      dateCellWrapper: elementType,

      toolbar: elementType,

      agenda: PropTypes.shape({
        date: elementType,
        time: elementType,
        event: elementType
      }),

      day: PropTypes.shape({
        header: elementType,
        event: elementType
      }),
      week: PropTypes.shape({
        header: elementType,
        event: elementType
      }),
      month: PropTypes.shape({
        header: elementType,
        event: elementType
      })
    }),

    /**
     * String messages used throughout the component, override to provide localizations
     */
    messages: PropTypes.shape({
      allDay: PropTypes.node,
      previous: PropTypes.node,
      next: PropTypes.node,
      today: PropTypes.node,
      month: PropTypes.node,
      week: PropTypes.node,
      day: PropTypes.node,
      agenda: PropTypes.node,
      showMore: PropTypes.func
    })
  },

  getDefaultProps() {
    return {
      elementProps: {},
      popup: false,
      toolbar: true,
      view: views.MONTH,
      views: [views.MONTH, views.WEEK, views.DAY, views.AGENDA],
      date: now,
      step: 30,

      drilldownView: views.DAY,

      titleAccessor: 'title',
      allDayAccessor: 'allDay',
      startAccessor: 'start',
      endAccessor: 'end'
    };
  },

  getViews() {
    const views = this.props.views;

    if (Array.isArray(views)) {
      return transform(views, (obj, name) => obj[name] = VIEWS[name], {});
    }

    if (typeof views === 'object') {
      return mapValues(views, (value, key) => {
        if (value === true) {
          return VIEWS[key];
        }

        return value;
      });
    }

    return VIEWS;
  },

  getView() {
    const views = this.getViews();

    return views[this.props.view];
  },

  getDrilldownView(date) {
    const { view, drilldownView, getDrilldownView } = this.props

    if (!getDrilldownView) return drilldownView

    return getDrilldownView(date, view, Object.keys(this.getViews()));
  },

  render() {
    let {
        view, toolbar, events
      , culture
      , components = {}
      , formats = {}
      , style
      , className
      , elementProps
      , date: current
      , ...props } = this.props;

    formats = defaultFormats(formats)

    let View = this.getView();
    let names = viewNames(this.props.views)

    let viewComponents = defaults(
      components[view] || {},
      omit(components, names),
      {
        eventWrapper: EventWrapper,
        dayWrapper: BackgroundWrapper,
        dateCellWrapper: BackgroundWrapper
      }
    )

    let ToolbarToRender = components.toolbar || Toolbar

    return (
      <div
        {...elementProps}
        className={cn('rbc-calendar', className, {
          'rbc-rtl': props.rtl
        })}
        style={style}
      >
        {toolbar &&
          <ToolbarToRender
            date={current}
            view={view}
            views={names}
            label={viewLabel(current, view, formats, culture)}
            onViewChange={this.handleViewChange}
            onNavigate={this.handleNavigate}
            messages={this.props.messages}
          />
        }
        <View
          ref='view'
          {...props}
          {...formats}
          culture={culture}
          formats={undefined}
          events={events}
          date={current}
          components={viewComponents}
          getDrilldownView={this.getDrilldownView}
          onNavigate={this.handleNavigate}
          onDrillDown={this.handleDrillDown}
          onSelectEvent={this.handleSelectEvent}
          onSelectSlot={this.handleSelectSlot}
          onShowMore={this._showMore}
        />
      </div>
    );
  },

  handleNavigate(action, newDate) {
    let { view, date, onNavigate } = this.props;
    let ViewComponent = this.getView();

    date = moveDate(action, newDate || date, ViewComponent)

    onNavigate(date, view)
  },

  handleViewChange(view) {
    if (view !== this.props.view && isValidView(view, this.props))
      this.props.onView(view)
  },

  handleSelectEvent(...args) {
    notify(this.props.onSelectEvent, args)
  },

  handleSelectSlot(slotInfo) {
    notify(this.props.onSelectSlot, slotInfo)
  },

  handleDrillDown(date, view) {
    if (view)
      this.handleViewChange(view)

    this.handleNavigate(navigate.DATE, date)
  }
});

export default uncontrollable(Calendar, {
  view: 'onView',
  date: 'onNavigate',
  selected: 'onSelectEvent'
})
<|endoftext|>


<commit_before>/*
 *  CardDeck.js
 *  2014/06/19
 *  @auther minimo
 *  This Program is MIT license.
 */

//盤上カードコントロール
tm.define("shotgun.CardDeck", {
    superClass: tm.app.Object2D,

    //カード配列
    cards: null,

    //手札
    hands: null,
    numHand: 0,

    init: function(suit, num) {
        //親クラスの初期化
        this.superInit();

        //デッキ構築
        this.cards = [];
        for (var i = 0; i < 4; i++) {
            for (var j = 0; j < 13; j++) {
                var card = shotgun.Card(i, j).addChildTo(this);
                card.setPosition(SC_W/2, -SC_H/2);
                this.cards[i*13+j] = card;
            }
        }

        //手札配列
        this.hands = [];
    },

    //開始時演出
    startup: function() {
        var len = this.cards.length;
        for (var i = 0; i < len; i++) {
            this.cards[i].setPosition( rand(0, SC_W), -rand(200, SC_H));
        }
    },

    //シャッフル
    //flagがtrueの場合、全カードのシャッフル。falseの場合、場に有るカードのみ
    shuffle: function(flag) {
        var num = this.cards.length;

        //ドロップしたカードを場に戻す
        if (flag) {
            for (var i = 0; i < num; i++) {
                var c = this.cards[i];
                if (c.drop) c.setPosition(rand(0, SC_W), -100);
            }
        }

		for( var i = 0; i < 100; i++ ){
			var a = rand(0, num-1);
			var b = rand(0, num-1);
			if (a == b)continue;
            if (!flag){
                if (this.cards[a].drop || this.cards[a].hand) continue;
                if (this.cards[b].drop || this.cards[b].hand) continue;
            }

			var tmp = this.cards[a];
			this.cards[a] = this.cards[b];
			this.cards[b] = tmp;
		}
		//表示順を考慮する為、逆に追加
		for( var i = num-1; i > -1; i-- ){
            if (!flag){
                if (this.cards[i].drop || this.cards[i].hand) continue;
            }
		    this.cards[i].remove().addChildTo(this);
		}

        for (var i = 0; i < num; i++) {
            if (!flag){
                if (this.cards[i].drop || this.cards[i].hand) continue;
            }
            var x = rand(SC_W*0.1, SC_W*0.9);
            var y = rand(SC_H*0.2, SC_H*0.6);
            var r = rand(0, 360);
            this.cards[i].tweener.clear().to({x: x, y: y, rotation: r}, 1000, "easeOutQuint");
        }
        tm.asset.AssetManager.get("dist").clone().play();
    },

    //カードの取得
    pickCard: function(x, y) {
        for (var i = 0; i < this.cards.length; i++) {
            var c = this.cards[i];
            if (c.drop || c.hand)continue;
            if (c.hitTestPoint({x: x, y: y}))return c;
        }
        return null;
    },

    //手札へ追加
    addHand: function(card) {
        if (this.hands.length > 4)return;
        if (!(card instanceof shotgun.Card)) return;

        card.hand = true;
        this.hands.push(card);

        var that = this;
        card.remove().addChildTo(this);
        card.tweener.clear().to({x: (CARD_W/2)*CARD_SCALE+(this.hands.length-1)*70, y: SC_H*0.8, rotation: 0}, 500, "easeOutQuint");
        card.tweener.call(function(){that.numHand++;});
        tm.asset.AssetManager.get("deal").clone().play();
    },

    //手札のクリア
    clearHand: function() {
		for( var i = 0; i < 5; i++ ){
		    var c = this.hands[i];
		    if (c) {
		        c.hand = false;
		        c.drop = true;
		        c.tweener.clear().wait(300).moveBy(0, 300, 500);
		    }
		}
		this.hands = [];
		this.numHand = 0;
    },

    //手札のソート
    sortHand: function() {
        if (this.hands.length < 5)return;

		for( var i = 0; i < 5; i++ ){
		    this.hands[i].tweener.clear().move((CARD_W/2)*CARD_SCALE, SC_H*0.8, 200).wait(200);
		}
		this.hands.sort(compairFunc);
		for( var i = 0; i < 5; i++ ){
		    var c = this.hands[i];
		    if (c) {
		        c.remove().addChildTo(this);
		        c.tweener.move((CARD_W/2)*CARD_SCALE+i*70, SC_H*0.8, 300);
		    }
		}
    },

    //役の判定
    checkHand: function() {
        if (this.hands.length < 5)return MISS;

		//フラッシュ判別
		var flash = true;
		var suit = this.hands[0].suit;
		for (var i = 1; i < 5; i++) {
			if (suit != this.hands[i].suit) flash = false;
		}
		//ストレート判別
		var straight = true;
		var start = this.hands[0].number+1;
		for (var i = 1; i < 5; i++) {
			if (start != this.hands[i].number) straight = false;
			start++;
		}
		//特殊なストレート
		if (straight == false) {
			straight = true;
			if (this.hands[0].number == 1 && this.hands[1].number == 10) {
				var start = this.hands[1].number+1;
				for (var i = 2; i < 5; i++) {
					if (start != this.hands[i].number) straight = false;
					start++;
				}
			}else{
				straight = false;
			}
		}

		//ストレートの場合は役確定
		if (straight) {
			//ストレートフラッシュ判定
			if (flash) {
				//ロイヤルストレートフラッシュ判定
				if (this.hands[0].number == 1 && this.hands[1].number == 10) return ROYALSTRAIGHTFLASH;
				return STRAIGHTFLASH;
			}
			return STRAIGHT;
		}

		//フラッシュの場合は役確定
		if (flash) return FLASH;

		//スリーカード、フォーカード判別
		if (this.hands[0].number == this.hands[3].number
		 || this.hands[1].number == this.hands[4].number) return FOURCARD;
		var three = false;
		if (this.hands[0].number == this.hands[2].number
		 || this.hands[1].number == this.hands[3].number
		 || this.hands[2].number == this.hands[4].number) three = true;

		//スリーカード成立の場合は前か後二枚を判別
		if (three) {
			if (this.hands[0].number == this.hands[2].number) {
				if (this.hands[3].number == this.hands[4].number) return FULLHOUSE;
			}
			if (this.hands[2].number == this.hands[4].number) {
				if (this.hands[0].number == this.hands[1].number) return FULLHOUSE;
			}
			return THREECARD;
		}

		//ペア判別
		var pair = 0;
		for (var i = 0; i < 5; i++) {
			for (var j = i+1; j < 5; j++) {
				if (this.hands[i].number == this.hands[j].number) pair++;
			}
		}
		if (pair == 1) return ONEPAIR;
		if (pair == 2) return TWOPAIR;
		return NOHAND;
    },
});

shotgun.CardDeck.prototype.accessor("left", {
    "get": function() {
        var num = 0;
        for (var i = 0; i < this.cards.length; i++) {
            if (!this.cards[i].drop) num++;
        }
        return num;
    },
});

//カードソート用比較関数
compairFunc = function(a,b){
	if( a.number == b.number ){
		if( a.suit == b.suit )return 0;
		return a.suit-b.suit;
	}
	return a.number-b.number;
}
<commit_msg>card deck busy flag<commit_after>/*
 *  CardDeck.js
 *  2014/06/19
 *  @auther minimo
 *  This Program is MIT license.
 */

//盤上カードコントロール
tm.define("shotgun.CardDeck", {
    superClass: tm.app.Object2D,

    //カード配列
    cards: null,

    //手札
    hands: null,
    numHand: 0,

    busy: false,    //処理中フラグ

    init: function(suit, num) {
        //親クラスの初期化
        this.superInit();

        //デッキ構築
        this.cards = [];
        for (var i = 0; i < 4; i++) {
            for (var j = 0; j < 13; j++) {
                var card = shotgun.Card(i, j).addChildTo(this);
                card.setPosition(SC_W/2, -SC_H/2);
                this.cards[i*13+j] = card;
            }
        }

        //手札配列
        this.hands = [];

        //Tweener初期化
        this.tweener.clear();
    },

    //開始時演出
    startup: function() {
        var len = this.cards.length;
        for (var i = 0; i < len; i++) {
            this.cards[i].setPosition( rand(0, SC_W), -rand(200, SC_H));
        }
    },

    //シャッフル
    //flagがtrueの場合、全カードのシャッフル。falseの場合、場に有るカードのみ
    shuffle: function(flag) {
        var num = this.cards.length;

        //ドロップしたカードを場に戻す
        if (flag) {
            for (var i = 0; i < num; i++) {
                var c = this.cards[i];
                if (c.drop) {
                    c.setPosition(rand(0, SC_W), -100);
                    c.drop = false;
                }
            }
        }

		for( var i = 0; i < 100; i++ ){
			var a = rand(0, num-1);
			var b = rand(0, num-1);
			if (a == b)continue;
            if (!flag){
                if (this.cards[a].drop || this.cards[a].hand) continue;
                if (this.cards[b].drop || this.cards[b].hand) continue;
            }

			var tmp = this.cards[a];
			this.cards[a] = this.cards[b];
			this.cards[b] = tmp;
		}
		//表示順を考慮する為、逆に追加
		for( var i = num-1; i > -1; i-- ){
            if (!flag){
                if (this.cards[i].drop || this.cards[i].hand) continue;
            }
		    this.cards[i].remove().addChildTo(this);
		}

        for (var i = 0; i < num; i++) {
            if (!flag){
                if (this.cards[i].drop || this.cards[i].hand) continue;
            }
            var x = rand(SC_W*0.1, SC_W*0.9);
            var y = rand(SC_H*0.2, SC_H*0.6);
            var r = rand(0, 360);
            this.cards[i].tweener.clear().to({x: x, y: y, rotation: r}, 1000, "easeOutQuint");
        }
        tm.asset.AssetManager.get("dist").clone().play();
    },

    //カードの取得
    pickCard: function(x, y) {
        for (var i = 0; i < this.cards.length; i++) {
            var c = this.cards[i];
            if (c.drop || c.hand)continue;
            if (c.hitTestPoint({x: x, y: y}))return c;
        }
        return null;
    },

    //手札へ追加
    addHand: function(card) {
        if (this.hands.length > 4)return;
        if (!(card instanceof shotgun.Card)) return;

        card.hand = true;
        this.hands.push(card);

        var that = this;
        card.remove().addChildTo(this);
        card.tweener.clear().to({x: (CARD_W/2)*CARD_SCALE+(this.hands.length-1)*70, y: SC_H*0.8, rotation: 0}, 500, "easeOutQuint");
        card.tweener.call(function(){that.numHand++;});
        tm.asset.AssetManager.get("deal").clone().play();
    },

    //手札のクリア
    clearHand: function() {
        this.busy = true;
		for( var i = 0; i < 5; i++ ){
		    var c = this.hands[i];
		    if (c) {
		        c.hand = false;
		        c.drop = true;
		        c.tweener.clear().wait(300).moveBy(0, 300, 500);
		    }
		}
		this.hands = [];
		this.numHand = 0;
		var that = this;
		this.tweener.clear().wait(350).call(function(){that.busy = false;});
    },

    //手札のソート
    sortHand: function() {
        if (this.hands.length < 5)return;

		for( var i = 0; i < 5; i++ ){
		    this.hands[i].tweener.clear().move((CARD_W/2)*CARD_SCALE, SC_H*0.8, 100).wait(100);
		}
		this.hands.sort(compairFunc);
		for( var i = 0; i < 5; i++ ){
		    var c = this.hands[i];
		    if (c) {
		        c.remove().addChildTo(this);
		        c.tweener.move((CARD_W/2)*CARD_SCALE+i*70, SC_H*0.8, 100);
		    }
		}
    },

    //役の判定
    checkHand: function() {
        if (this.hands.length < 5)return MISS;

		//フラッシュ判別
		var flash = true;
		var suit = this.hands[0].suit;
		for (var i = 1; i < 5; i++) {
			if (suit != this.hands[i].suit) flash = false;
		}
		//ストレート判別
		var straight = true;
		var start = this.hands[0].number+1;
		for (var i = 1; i < 5; i++) {
			if (start != this.hands[i].number) straight = false;
			start++;
		}
		//特殊なストレート
		if (straight == false) {
			straight = true;
			if (this.hands[0].number == 1 && this.hands[1].number == 10) {
				var start = this.hands[1].number+1;
				for (var i = 2; i < 5; i++) {
					if (start != this.hands[i].number) straight = false;
					start++;
				}
			}else{
				straight = false;
			}
		}

		//ストレートの場合は役確定
		if (straight) {
			//ストレートフラッシュ判定
			if (flash) {
				//ロイヤルストレートフラッシュ判定
				if (this.hands[0].number == 1 && this.hands[1].number == 10) return ROYALSTRAIGHTFLASH;
				return STRAIGHTFLASH;
			}
			return STRAIGHT;
		}

		//フラッシュの場合は役確定
		if (flash) return FLASH;

		//スリーカード、フォーカード判別
		if (this.hands[0].number == this.hands[3].number
		 || this.hands[1].number == this.hands[4].number) return FOURCARD;
		var three = false;
		if (this.hands[0].number == this.hands[2].number
		 || this.hands[1].number == this.hands[3].number
		 || this.hands[2].number == this.hands[4].number) three = true;

		//スリーカード成立の場合は前か後二枚を判別
		if (three) {
			if (this.hands[0].number == this.hands[2].number) {
				if (this.hands[3].number == this.hands[4].number) return FULLHOUSE;
			}
			if (this.hands[2].number == this.hands[4].number) {
				if (this.hands[0].number == this.hands[1].number) return FULLHOUSE;
			}
			return THREECARD;
		}

		//ペア判別
		var pair = 0;
		for (var i = 0; i < 5; i++) {
			for (var j = i+1; j < 5; j++) {
				if (this.hands[i].number == this.hands[j].number) pair++;
			}
		}
		if (pair == 1) return ONEPAIR;
		if (pair == 2) return TWOPAIR;
		return NOHAND;
    },
});

shotgun.CardDeck.prototype.accessor("left", {
    "get": function() {
        var num = 0;
        for (var i = 0; i < this.cards.length; i++) {
            if (!this.cards[i].drop) num++;
        }
        return num;
    },
});

//カードソート用比較関数
compairFunc = function(a,b){
	if( a.number == b.number ){
		if( a.suit == b.suit )return 0;
		return a.suit-b.suit;
	}
	return a.number-b.number;
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Endpoint class to return a valid handpoint for offline to handle
 * requires serverless service and http Event data to be merged in
 * Works with Serverless version 1.0
 *
 * bsoylu 8/16/2016
 */

// Node dependencies
const fs = require('fs');
const path = require('path');

// project dependencies
const debugLog = require('./debugLog');
const endpointStruct = require('./offline-endpoint.json');

// velocity template defaults
const defaultRequestTemplate = fs.readFileSync(
  path.resolve(__dirname, './offline-default.req.vm'),
  'utf8',
);
const defaultResponseTemplate = fs.readFileSync(
  path.resolve(__dirname, './offline-default.res.vm'),
  'utf8',
);

class Endpoint {
  constructor(httpData, options) {
    this.httpData = httpData;
    this.options = options;
  }

  /*
  * determine whether we have function level overrides for velocity templates
  * if not we will use defaults
  */
  setVmTemplates(fullEndpoint) {
    // determine requestTemplate
    // first check if requestTemplate is set through serverless
    const fep = fullEndpoint;

    try {
      // determine request template override
      const reqFilename = `${this.options.handlerPath}.req.vm`;
      // check if serverless framework populates the object itself
      if (typeof this.httpData.request === 'object' && typeof this.httpData.request.template === 'object') {
        const templatesConfig = this.httpData.request.template;
        Object.keys(templatesConfig).forEach(key => {
          fep.requestTemplates[key] = templatesConfig[key];
        });
      }
      // load request template if exists if not use default from serverless offline
      else if (fs.existsSync(reqFilename)) {
        fep.requestTemplates['application/json'] = fs.readFileSync(reqFilename, 'utf8');
      }
      else {
        fep.requestTemplates['application/json'] = defaultRequestTemplate;
      }

      // determine response template
      const resFilename = `${this.options.handlerPath}.res.vm`;
      fep.responseContentType = this.getResponseContentType(fep);
      debugLog('Response Content-Type ', fep.responseContentType);
      // load response template from http response template, or load file if exists other use default
      if (fep.response && fep.response.template) {
        fep.responses.default.responseTemplates[fep.responseContentType] = fep.response.template;
      }
      else if (fs.existsSync(resFilename)) {
        fep.responses.default.responseTemplates[fep.responseContentType] = fs.readFileSync(resFilename, 'utf8');
      }
      else {
        fep.responses.default.responseTemplates[fep.responseContentType] = defaultResponseTemplate;
      }
    }
    catch (err) {
      this.errorHandler(err);
    }

    return fep;
  }

  getResponseContentType(fep) {
    let responseContentType = 'application/json';

    if (fep.response && fep.response.headers['Content-Type']) {
      responseContentType = fep.response.headers['Content-Type'].replace(/'/gm, '');
    }

    return responseContentType;
  }

  /*
   * Generic error handler
   */
  errorHandler(err) {
    debugLog(`Error: ${err}`);
  }

  /*
   * return the fully generated Endpoint
   */
  generate() {

    let fullEndpoint = Object.assign({}, endpointStruct, this.httpData);

    if (this.httpData.integration && this.httpData.integration === 'lambda') {
      // determine request and response templates or use defaults
      fullEndpoint = this.setVmTemplates(fullEndpoint);
    }

    return fullEndpoint;
  }

}

module.exports = Endpoint;
<commit_msg>Read json file as string, to create new instances (clone)<commit_after>'use strict';

/**
 * Endpoint class to return a valid handpoint for offline to handle
 * requires serverless service and http Event data to be merged in
 * Works with Serverless version 1.0
 *
 * bsoylu 8/16/2016
 */

// Node dependencies
const fs = require('fs');
const path = require('path');

// project dependencies
const debugLog = require('./debugLog');

function readFile(filename) {
  return fs.readFileSync(path.resolve(__dirname, filename), 'utf8');
}

// we'll read the json as string, so we are able to clone it
const endpointStruct = readFile('./offline-endpoint.json');
// velocity template defaults
const defaultRequestTemplate = readFile('./offline-default.req.vm');
const defaultResponseTemplate = readFile('./offline-default.res.vm');

class Endpoint {
  constructor(httpData, options) {
    this.httpData = httpData;
    this.options = options;
  }

  /*
  * determine whether we have function level overrides for velocity templates
  * if not we will use defaults
  */
  setVmTemplates(fullEndpoint) {
    // determine requestTemplate
    // first check if requestTemplate is set through serverless
    const fep = fullEndpoint;

    try {
      // determine request template override
      const reqFilename = `${this.options.handlerPath}.req.vm`;
      // check if serverless framework populates the object itself
      if (typeof this.httpData.request === 'object' && typeof this.httpData.request.template === 'object') {
        const templatesConfig = this.httpData.request.template;
        Object.keys(templatesConfig).forEach(key => {
          fep.requestTemplates[key] = templatesConfig[key];
        });
      }
      // load request template if exists if not use default from serverless offline
      else if (fs.existsSync(reqFilename)) {
        fep.requestTemplates['application/json'] = fs.readFileSync(reqFilename, 'utf8');
      }
      else {
        fep.requestTemplates['application/json'] = defaultRequestTemplate;
      }

      // determine response template
      const resFilename = `${this.options.handlerPath}.res.vm`;
      fep.responseContentType = this.getResponseContentType(fep);
      debugLog('Response Content-Type ', fep.responseContentType);
      // load response template from http response template, or load file if exists other use default
      if (fep.response && fep.response.template) {
        fep.responses.default.responseTemplates[fep.responseContentType] = fep.response.template;
      }
      else if (fs.existsSync(resFilename)) {
        fep.responses.default.responseTemplates[fep.responseContentType] = fs.readFileSync(resFilename, 'utf8');
      }
      else {
        fep.responses.default.responseTemplates[fep.responseContentType] = defaultResponseTemplate;
      }
    }
    catch (err) {
      this.errorHandler(err);
    }

    return fep;
  }

  getResponseContentType(fep) {
    let responseContentType = 'application/json';

    if (fep.response && fep.response.headers['Content-Type']) {
      responseContentType = fep.response.headers['Content-Type'].replace(/'/gm, '');
    }

    return responseContentType;
  }

  /*
   * Generic error handler
   */
  errorHandler(err) {
    debugLog(`Error: ${err}`);
  }

  /*
   * return the fully generated Endpoint
   */
  generate() {
    // JSON.parse(endpointStruct) -> new instance, deep clone
    let fullEndpoint = Object.assign({}, JSON.parse(endpointStruct), this.httpData);

    if (this.httpData.integration && this.httpData.integration === 'lambda') {
      // determine request and response templates or use defaults
      fullEndpoint = this.setVmTemplates(fullEndpoint);
    }

    return fullEndpoint;
  }

}

module.exports = Endpoint;
<|endoftext|>


<commit_before>/**
	_moon.ExpandableInput_, which extends
	moon.ExpandableListItem, is a drop-down
	input that prompts the user to input text.
*/
enyo.kind({
	name: "moon.ExpandableInput",
	kind: "moon.ExpandableListItem",
	classes: "moon-expandable-input",
	events: {
		/**
			Fires when the current text changes.

			_inEvent.value_ contains the value of the input.
		*/
		onChange: ""
	},
	published: {
		//* Text to be displayed in the _currentValue_ control if no text is input
		placeholder: "",
		//* Initial value
		value: ""
	},
	//* @protected
	components: [
		{
			name: "header", kind: "moon.Item", spotlight: true,
			onSpotlightFocus: "headerFocus", onSpotlightSelect: "expandDrawer", ontap: "expandDrawer",
			classes: "moon-expandable-input-header"
		},
		{
			name: "drawer", kind: "enyo.Drawer", onStep: "drawerAnimationStep", components: [{
				name: "client",
				kind: "moon.InputDecorator",
				onSpotlightFocus: "inputFocus",
				onSpotlightSelect: "expandDrawer",
				spotlight: true,
				components: [
					{
						name: "clientInput",
						kind: "moon.Input",
					}
				]}
			]
		},
		{
			name: "currentValue", kind: "moon.Item", ontap: "expandDrawer", spotlight: false, content: "",
			classes: "moon-expandable-input-current-value"
		},
		{
			name: "bottom", kind: "enyo.Control", onSpotlightFocus: "spotlightFocusBottom", spotlight: true
		}
	],
	create: function() {
		this.inherited(arguments);
		this.$.clientInput.setValue(this.value);
		this.placeholderChanged();
		this.openChanged();
	},
	initComponents: function() {
		this.controlParentName = "drawer";
		this.discoverControlParent();
		this.inherited(arguments);
	},
	updateContent: function() {
		// no input text
		if(this.$.clientInput.value == "") {
			this.$.currentValue.setContent(this.placeholder);
		// text changed
		} else if(this.$.clientInput.value !== this.value) {
			this.setValue(this.$.clientInput.value);
			this.fireChangeEvent();
		// update the content of currentValue
		} else if(this.value != this.$.currentValue.content) {
			this.$.currentValue.setContent(this.value);
		}
	},
	//* When _this.value_ changes, update the value and content
	valueChanged: function(inOld) {
		this.$.clientInput.setValue(this.value);
		this.updateContent();
	},
	//* If there is no value, uses _this.placeholder_ as current text.
	placeholderChanged: function() {
		this.$.clientInput.setPlaceholder(this.placeholder);
		this.updateContent();
	},
	//* When _this.open_ changes, shows/hides _this.$.currentValue_.
	openChanged: function() {
		this.inherited(arguments);
		this.$.currentValue.setShowing(!this.open);
		this.$.bottom.setShowing(this.open);
	},
	//* expand a drawer, focus or blur moon.Input
	expandDrawer: function(inSender, inEvent) {
		var open = null;
		this.updateContent();
		this.expandContract();

		open = this.getOpen();
		if(!open) {
			this.blur();
			this.$.clientInput.blur();
		} else {
			this.$.clientInput.focus();
			enyo.Spotlight.spot(this.$.client);
		}
	},
	//* focus moon.Input when input decorator gets focus
	inputFocus: function(inSender, inEvent) {
		if(inEvent.dir == "DOWN") {
			this.$.clientInput.focus();
			enyo.Spotlight.spot(this.$.client);
		}
	},
	//* Fires an _onChange_ event.
	fireChangeEvent: function() {
		this.doChange({
			value:this.value,
		});
	}
});
<commit_msg>GF-6248: To handle the case when "UP" key pressed<commit_after>/**
	_moon.ExpandableInput_, which extends
	moon.ExpandableListItem, is a drop-down
	input that prompts the user to input text.
*/
enyo.kind({
	name: "moon.ExpandableInput",
	kind: "moon.ExpandableListItem",
	classes: "moon-expandable-input",
	events: {
		/**
			Fires when the current text changes.

			_inEvent.value_ contains the value of the input.
		*/
		onChange: ""
	},
	published: {
		//* Text to be displayed in the _currentValue_ control if no text is input
		placeholder: "",
		//* Initial value
		value: ""
	},
	//* @protected
	components: [
		{
			name: "header", kind: "moon.Item", spotlight: true,
			onSpotlightFocus: "headerFocus", onSpotlightSelect: "expandDrawer", ontap: "expandDrawer",
			classes: "moon-expandable-input-header"
		},
		{
			name: "drawer", kind: "enyo.Drawer", onStep: "drawerAnimationStep", components: [{
				name: "client",
				kind: "moon.InputDecorator",
				onSpotlightFocus: "inputFocus",
				onSpotlightSelect: "expandDrawer",
				spotlight: true,
				components: [
					{
						name: "clientInput",
						kind: "moon.Input",
					}
				]}
			]
		},
		{
			name: "currentValue", kind: "moon.Item", ontap: "expandDrawer", spotlight: false, content: "",
			classes: "moon-expandable-input-current-value"
		},
		{
			name: "bottom", kind: "enyo.Control", onSpotlightFocus: "spotlightFocusBottom", spotlight: true
		}
	],
	create: function() {
		this.inherited(arguments);
		this.$.clientInput.setValue(this.value);
		this.placeholderChanged();
		this.openChanged();
	},
	initComponents: function() {
		this.controlParentName = "drawer";
		this.discoverControlParent();
		this.inherited(arguments);
	},
	updateContent: function() {
		// no input text
		if(this.$.clientInput.value == "") {
			this.$.currentValue.setContent(this.placeholder);
		// text changed
		} else if(this.$.clientInput.value !== this.value) {
			this.setValue(this.$.clientInput.value);
			this.fireChangeEvent();
		// update the content of currentValue
		} else if(this.value != this.$.currentValue.content) {
			this.$.currentValue.setContent(this.value);
		}
	},
	//* When _this.value_ changes, update the value and content
	valueChanged: function(inOld) {
		this.$.clientInput.setValue(this.value);
		this.updateContent();
	},
	//* If there is no value, uses _this.placeholder_ as current text.
	placeholderChanged: function() {
		this.$.clientInput.setPlaceholder(this.placeholder);
		this.updateContent();
	},
	//* When _this.open_ changes, shows/hides _this.$.currentValue_.
	openChanged: function() {
		this.inherited(arguments);
		this.$.currentValue.setShowing(!this.open);
		this.$.bottom.setShowing(this.open);
	},
	//* expand a drawer, focus or blur moon.Input
	expandDrawer: function(inSender, inEvent) {
		var open = null;
		this.updateContent();
		this.expandContract();

		open = this.getOpen();
		if(!open) {
			this.blur();
			this.$.clientInput.blur();
		} else {
			this.$.clientInput.focus();
			enyo.Spotlight.spot(this.$.client);
		}
	},
	//* When closing drawer via keypress with "UP" direction, update value
	headerFocus: function(inSender, inEvent) {
		if(this.getOpen() && inEvent && inEvent.dir && inEvent.dir === "UP") {
			this.updateContent();
			this.inherited(arguments);
			return true;
		} else if(!this.getOpen()) {
			this.inherited(arguments);
		}
	},
	//* focus moon.Input when input decorator gets focus
	inputFocus: function(inSender, inEvent) {
		if(this.getOpen() && inEvent && inEvent.dir && inEvent.dir == "DOWN") {
			this.$.clientInput.focus();
			enyo.Spotlight.spot(this.$.client);
		}
	},
	//* Fires an _onChange_ event.
	fireChangeEvent: function() {
		this.doChange({
			value:this.value,
		});
	}
});
<|endoftext|>


<commit_before>
core.Class("api.Processor", {

	construct: function(settings) {

		this.settings = {};
		for (var d in this.defaults) {
			this.settings[d] = this.defaults[d];
		}

		for (var s in settings) {
			this.settings[s] = settings[s];
		}

	},

	members: {

		process: function(data) {

			data['constructor'].params = this.__processParams(data['constructor'].params);

			if (data.members != null) {
				data.members = this.__processSection(data.members);
				data.hasMembers = true;
			}

			if (data.statics != null) {
				data.statics = this.__processSection(data.statics);
				data.hasStatics = true;
			}

			return data;

		},

		__processSection: function(object) {

			var arr = [];

			for (var id in object) {

				var data = object[id];
				data.name = id;

				if (data.params != null) {
					data.params = this.__processParams(data.params);
				}

				arr.push(data);

			}

			return arr;

		},

		__processParams: function(params) {

			var arr = [],
				id;

			for (id in params) {
				arr.push({});
			}

			for (id in params) {

				var pos = params[id].position;

				if (pos != null) {

					var data = params[id];
					data.name = id;
					if (data.type instanceof Array) {
						data.type = data.type.join(' | ');
					} else {
						data.type = 'undefined';
					}
					arr[pos] = data;

				}

			}

			return arr;

		}

	}

});

<commit_msg>Cleanup<commit_after>
core.Class("api.Processor", {

	construct: function(settings) {

		this.settings = {};
		for (var d in this.defaults) {
			this.settings[d] = this.defaults[d];
		}

		for (var s in settings) {
			this.settings[s] = settings[s];
		}

	},

	members: {

		process: function(data) {

			if ("constructor" in data) {
				data["constructor"].params = this.__processParams(data["constructor"].params);
			}

			if ("members" in data) {
				data.members = this.__processSection(data.members);
			}

			if ("statics" in data) {
				data.statics = this.__processSection(data.statics);
			}

			return data;

		},

		__processSection: function(object) {

			var arr = [];

			for (var id in object) {

				var data = object[id];
				data.name = id;

				if (data.params != null) {
					data.params = this.__processParams(data.params);
				}

				arr.push(data);

			}

			return arr;

		},

		__processParams: function(params) {

			var arr = [],
				id;

			for (id in params) {
				arr.push({});
			}

			for (id in params) {

				var pos = params[id].position;

				if (pos != null) {

					var data = params[id];
					data.name = id;
					if (data.type instanceof Array) {
						data.type = data.type.join(' | ');
					} else {
						data.type = 'undefined';
					}
					arr[pos] = data;

				}

			}

			return arr;

		}

	}

});

<|endoftext|>


<commit_before>"use strict";
/**
 * Since only a single constructor is being exported as module.exports this comment isn't documented.
 * The class and module are the same thing, the contructor comment takes precedence.
 * @module hexagonal-map
 */

var babylon = require("babylonjs/babylon.max.js");
var hexToRgb = require("../HexToRGB.js");
/*
 * Defines an isometric hexagonal board for web games
 */

/**
 * Pretty much the controller of a hexagonal map scene using the provided canvas and context objects
 * @constructor
 * @param { external:cartesian-hexagonal } hexDimension - The DTO defining the hex <--> cartesian relation
 * @param canvas - The canvas element to initialize babylon.js with
 * @param backgroundColor - the color to set the Babylon.js background
 * @example var hexMap = new (require(hexagonal-map))(hexDimension, canvas, contexts, mouseClicked);
 */
module.exports = function HexBoard(canvas, window, backgroundColor) {
  //Protect the constructor from being called as a normal method
  if (!(this instanceof HexBoard)) {
    return new HexBoard(canvas, window);
  }

  //A reference to the board for functions
  var board = this;

  //Setup babylonjs
  this.engine = new babylon.Engine(canvas, true);

  //Run the engines render loop
  this.engine.runRenderLoop(function() {
    if (board.scene) {
      board.scene.render();
    }
  });

    board.scene = new babylon.Scene(board.engine);

    // Change the scene background color
  var rgb = hexToRgb(backgroundColor);
    board.scene.clearColor = = new babylon.Color3(
    rgb.r / 256,
    rgb.g / 256,
    rgb.b / 256
  );

    // This creates and positions a free camera
    //var camera = new babylon.FreeCamera("camera1", new babylon.Vector3(0, 0, 1000), scene);
    //  Create an ArcRotateCamera aimed at 0,0,0, with no alpha, beta or radius, so be careful.  It will look broken.
    board.camera = new babylon.ArcRotateCamera(
      "ArcRotateCamera",
      0,
      0,
      0,
      babylon.Vector3.Zero(),
      board.scene
    );

    board.camera.upVector = new babylon.Vector3(0, 0, 1);

    board.camera.upperBetaLimit = Math.PI;
    board.camera.allowUpsideDown = true;

    //Make an invisible plane to hit test for the scene's X, Y co-ordinates (not the screens X, Y co-ordinates)
    board.pickerPlane = new babylon.Plane.FromPositionAndNormal(
      babylon.Vector3.Zero(),
      new babylon.Vector3(0, 0, 1)
    );

    //Initialize variables
    board.cameraTargetX = 0; //The X point on the Z = 0 plane the camera is pointed
    board.cameraTargetY = 0; //The Y point on the Z = 0 plane the camera is pointed

    board.camera.setPosition(new babylon.Vector3(0, 1000, 1000));
    // This targets the camera to scene origin
    board.camera.setTarget(babylon.Vector3.Zero());

  // Delegate mouse interactions
  var down = false;
  var mousemoved = false;
  var mouseDownPickResult;
  var clickedItem; //The item which has "claimed" the mouse down event
  var initialDownX;
  var initialDownY;

  // Watch for browser/canvas resize events
  if (window) {
    window.addEventListener("resize", function() {
      board.engine.resize();

      //recenter
      //Figure out what the old U, V in the middle was for our original size
      var hexagonalCoordinates = board.hexDimensions.getReferencePoint(
        board.cameraTargetX,
        board.cameraTargetY
      );

      board.centerOnCell(hexagonalCoordinates.u, hexagonalCoordinates.v);
    });
  }

  canvas.onmousedown = function(e) {
    e.preventDefault();
    down = true;
    mousemoved = false;

    var pageX = e.pageX;
    var pageY = e.pageY;

    if (e.touches) {
      pageX = e.touches[0].pageX;
      pageY = e.touches[0].pageY;
    }
    var relativeX = pageX - canvas.offsetLeft;
    initialDownX = relativeX;
    var relativeY = pageY - canvas.offsetTop;
    initialDownY = relativeY;
    //Pick the point on the invisible picker plane at the screen co-ordinates under the mouse
    var tRay = board.scene.createPickingRay(
      relativeX,
      relativeY,
      babylon.Matrix.Identity(),
      board.camera
    );
    mouseDownPickResult = board.intersectRayPlane(tRay, board.pickerPlane);
    var mousePickResult = board.scene.pick(relativeX, relativeY, function(
      mesh
    ) {
      return !!mesh.data && !!mesh.data.hasMouseInteraction;
    });
    if (mousePickResult.hit) {
      clickedItem = mousePickResult.pickedMesh;
    }
  };

  canvas.onmousemove = function(e) {
    e.preventDefault();
    if (down === false) {
      return;
    }
    var pageX = e.pageX;
    var pageY = e.pageY;

    if (e.touches) {
      pageX = e.touches[0].pageX;
      pageY = e.touches[0].pageY;
    }

    var relativeX = pageX - canvas.offsetLeft;
    var relativeY = pageY - canvas.offsetTop;

    //Check for a minimum drag distance before this is counted as a drag
    if (
      !(
        Math.abs(initialDownX - relativeX) > 5 ||
        Math.abs(initialDownY - relativeY) > 5
      )
    ) {
      return;
    }

    //Pick the point on the invisible picker plane at the screen co-ordinates under the mouse
    var tRay = board.scene.createPickingRay(
      relativeX,
      relativeY,
      babylon.Matrix.Identity(),
      board.camera
    );
    var pickResult = board.intersectRayPlane(tRay, board.pickerPlane);

    if (clickedItem) {
      //An item has claimed further mouse drag
      clickedItem.mouseDragged(
        relativeX,
        relativeY,
        pickResult.x,
        pickResult.y
      );
      if (board.mouseDragged) {
        board.mouseDragged(
          relativeX,
          relativeY,
          pickResult.x,
          pickResult.y,
          true
        );
      }
    } else {
      if (board.mouseDragged) {
        board.mouseDragged(
          relativeX,
          relativeY,
          pickResult.x,
          pickResult.y,
          false
        );
      }
      //Figure out where the camera needs to be targeted, for the initial mouse down position to stay under the mouse

      //The current point under the mouse is related to the current center of the screen, as the initial point under the mouse needs to be related to the new center
      //Find how that relates to the point on the plane in the middle of the screen
      var planeDx = pickResult.x - board.cameraTargetX;
      var planeDy = pickResult.y - board.cameraTargetY;

      //Solve for the new cameraTarget co-ordinates relative to the original mouse down point
      board.cameraTargetX = mouseDownPickResult.x - planeDx;
      board.cameraTargetY = mouseDownPickResult.y - planeDy;

      board.updatePostion();
    }
    mousemoved = true;
  };

  canvas.addEventListener("touchmove", canvas.onmousemove, false);
  canvas.addEventListener("touchstart", canvas.onmousedown, false);

  canvas.onmouseleave = function(e) {
    e.preventDefault();
    if (down === false) {
      return;
    }
    down = false;
    var pageX = e.pageX;
    var pageY = e.pageY;

    if (e.changedTouches) {
      pageX = e.changedTouches[0].pageX;
      pageY = e.changedTouches[0].pageY;
    }
    var relativeX = pageX - canvas.offsetLeft;
    var relativeY = pageY - canvas.offsetTop;
    var tRay = board.scene.createPickingRay(
      relativeX,
      relativeY,
      babylon.Matrix.Identity(),
      board.camera
    );
    var pickResult = board.intersectRayPlane(tRay, board.pickerPlane);

    if (clickedItem) {
      clickedItem.mouseReleased(
        relativeX,
        relativeY,
        pickResult.x,
        pickResult.y,
        mousemoved
      );
      //Emit a mouseUp event, with the clickable item
      board.emit('mouseUp', {canvasX:relativeX, canvasY,relativeY,mapX:pickResult.x,mapY:pickResult.y,clickedItem:clickItem,mousemoved:mousemoved});
      if (board.mouseClicked) {
        board.mouseClicked(
          relativeX,
          relativeY,
          pickResult.x,
          pickResult.y,
          true,
          mousemoved
        );
      }
    } else if (board.mouseClicked) {
      board.mouseClicked(
        relativeX,
        relativeY,
        pickResult.x,
        pickResult.y,
        false,
        mousemoved
      );
    }
    clickedItem = null;
    mousemoved = false;
  };
  canvas.onmouseup = canvas.onmouseleave;
  canvas.addEventListener("touchend", canvas.onmouseup, false);

  /**
     * Clears the canvas so the HexBoard may be re-used
     */
  this.clear = function() {
    board.scene.dispose();
  };

  /**
     * Initializes the groups and objects from the contexts, plus the drag variables
     */
  this.init = function() {
    // This creates a light, aiming 0,1,0 - to the sky.
    var light = new babylon.HemisphericLight(
      "light1",
      new babylon.Vector3(0, 0, 1),
      board.scene
    );

    // Dim the light a small amount
    light.intensity = 0.5;
  };

  /**
     * Set the hexDimensions object used for centering the screen on a cell
     * @param { external:cartesian-hexagonal } hexDimension - The DTO defining the hex <--> cartesian relation
     */
  this.setHexDimensions = function(hexDimensions) {
    board.hexDimensions = hexDimensions;
  };

  /**
     * Internal shared functionallity of paning, updates the camera and emits an event
     */
  this.updatePostion = function() {
    board.camera.target.x = board.cameraTargetX;
    board.camera.target.y = board.cameraTargetY;
    this.emitEvent('pan', {x:board.cameraTargetX, y:board.cameraTargetY});
  };

/**
 * Pans the camera to the given position on the plane of interest
 */
this.pan = function(x, y) {
board.cameraTargetX = x;
board.cameraTargetY = y;
this.updatePosition();
};

  /**
      * Utility function to center the board on a cell
      */
  this.centerOnCell = function(u, v) {
    var pixelCoordinates = board.hexDimensions.getPixelCoordinates(u, v);
    board.cameraTargetX = pixelCoordinates.x;
    board.cameraTargetY = pixelCoordinates.y;
    this.updatePostion();
  };

  /**
     * Helper function to get intersection between ray and plane
     */
  this.intersectRayPlane = function(pRay, pPlane) {
    var tIsecPoint = null;
    var tDot = babylon.Vector3.Dot(pRay.direction, pPlane.normal);
    if (tDot !== 0.0) {
      var t = -pPlane.signedDistanceTo(pRay.origin) / tDot;
      if (t >= 0.0) {
        var tDirS = pRay.direction.scale(t);
        tIsecPoint = pRay.origin.add(tDirS);
      }
    }
    return tIsecPoint;
  };
};

let EventEmitter = require('wolfy87-eventemitter');
module.exports.prototype = new EventEmitter();
<commit_msg>Continue work<commit_after>"use strict";
/**
 * Since only a single constructor is being exported as module.exports this comment isn't documented.
 * The class and module are the same thing, the contructor comment takes precedence.
 * @module hexagonal-map
 */

var babylon = require("babylonjs/babylon.max.js");
var hexToRgb = require("../HexToRGB.js");
/*
 * Defines an isometric hexagonal board for web games
 */

/**
 * Initializes the Babylon.js scene, delegates mouse control, provides an API to control the camera relative to the X/Y plane
 * @constructor
 * @param { external:cartesian-hexagonal } hexDimension - The DTO defining the hex <--> cartesian relation
 * @param canvas - The canvas element to initialize babylon.js with
 * @param backgroundColor - the color to set the Babylon.js background
 * @example var hexMap = new (require(hexagonal-map))(hexDimension, canvas, contexts, mouseClicked);
 */
module.exports = function HexBoard(canvas, window, backgroundColor) {
  //Protect the constructor from being called as a normal method
  if (!(this instanceof HexBoard)) {
    return new HexBoard(canvas, window, backgroundColor);
  }

  //A reference to the board for functions
  var board = this;

  //Setup babylonjs
  this.engine = new babylon.Engine(canvas, true);

  //Run the engines render loop
  this.engine.runRenderLoop(function() {
    if (board.scene) {
      board.scene.render();
    }
  });

  board.scene = new babylon.Scene(board.engine);

  // Change the scene background color
  var rgb = hexToRgb(backgroundColor);
  board.scene.clearColor = new babylon.Color3(
    rgb.r / 256,
    rgb.g / 256,
    rgb.b / 256
  );

  // This creates and positions a free camera
  //var camera = new babylon.FreeCamera("camera1", new babylon.Vector3(0, 0, 1000), scene);
  //  Create an ArcRotateCamera aimed at 0,0,0, with no alpha, beta or radius, so be careful.  It will look broken.
  board.camera = new babylon.ArcRotateCamera(
    "ArcRotateCamera",
    0,
    0,
    0,
    babylon.Vector3.Zero(),
    board.scene
  );

  board.camera.upVector = new babylon.Vector3(0, 0, 1);

  board.camera.upperBetaLimit = Math.PI;
  board.camera.allowUpsideDown = true;

  //Make an invisible plane to hit test for the scene's X, Y co-ordinates (not the screens X, Y co-ordinates)
  board.pickerPlane = new babylon.Plane.FromPositionAndNormal(
    babylon.Vector3.Zero(),
    new babylon.Vector3(0, 0, 1)
  );

  //Initialize variables
  board.cameraTargetX = 0; //The X point on the Z = 0 plane the camera is pointed
  board.cameraTargetY = 0; //The Y point on the Z = 0 plane the camera is pointed

  board.camera.setPosition(new babylon.Vector3(0, 1000, 1000));
  // This targets the camera to scene origin
  board.camera.setTarget(babylon.Vector3.Zero());

  // Delegate mouse interactions
  var down = false;
  var mousemoved = false;
  var clickedItem; //The item which has "claimed" the mouse down event
  var initialDownX;
  var initialDownY;

  // Watch for browser/canvas resize events
  if (window) {
    window.addEventListener("resize", function() {
      board.engine.resize();

      //recenter
      //Figure out what the old U, V in the middle was for our original size
      var hexagonalCoordinates = board.hexDimensions.getReferencePoint(
        board.cameraTargetX,
        board.cameraTargetY
      );

      board.centerOnCell(hexagonalCoordinates.u, hexagonalCoordinates.v);
    });
  }

  /**
   * Save the board position the click event happened over
   * and check if there is an interactive item under the mouse
   */
  canvas.onmousedown = function(e) {
    e.preventDefault();
    down = true;
    mousemoved = false;

    var pageX = e.pageX;
    var pageY = e.pageY;

    if (e.touches) {
      pageX = e.touches[0].pageX;
      pageY = e.touches[0].pageY;
    }
    var relativeX = pageX - canvas.offsetLeft;
    initialDownX = relativeX;
    var relativeY = pageY - canvas.offsetTop;
    initialDownY = relativeY;

    let tRay = board.scene.createPickingRay(
      relativeX,
      relativeY,
      babylon.Matrix.Identity(),
      board.camera
    );
    let pickResult = board.intersectRayPlane(tRay, board.pickerPlane);

    var mousePickResult = board.scene.pick(relativeX, relativeY, function(
      mesh
    ) {
      return !!mesh.data && !!mesh.data.hasMouseInteraction;
    });

    if (mousePickResult.hit) {
      clickedItem = mousePickResult.pickedMesh;
    }

    if (clickedItem) {
      clickedItem.emit("mouseDown", {
        canvasX: relativeX,
        canvasY: relativeY,
        mapX: pickResult.x,
        mapY: pickResult.y,
        clickedItem: clickedItem
      });
    }
    board.emit("mouseDown", {
      canvasX: relativeX,
      canvasY: relativeY,
      mapX: pickResult.x,
      mapY: pickResult.y,
      clickedItem: clickedItem
    });
  };

  /**
   * If the mouse has moved the minimum distance,
   * Then emit a moved event from the clicked item (if there is one),
   * and from the board. Finaly note the mouse moved.
   */
  canvas.onmousemove = function(e) {
    e.preventDefault();
    if (down === false) {
      return;
    }
    var pageX = e.pageX;
    var pageY = e.pageY;

    if (e.touches) {
      pageX = e.touches[0].pageX;
      pageY = e.touches[0].pageY;
    }

    var relativeX = pageX - canvas.offsetLeft;
    var relativeY = pageY - canvas.offsetTop;

    //Check for a minimum drag distance before this is counted as a drag
    if (
      !(
        Math.abs(initialDownX - relativeX) > 5 ||
        Math.abs(initialDownY - relativeY) > 5
      )
    ) {
      return;
    }

    //Pick the point on the invisible picker plane at the screen co-ordinates under the mouse
    var tRay = board.scene.createPickingRay(
      relativeX,
      relativeY,
      babylon.Matrix.Identity(),
      board.camera
    );
    var pickResult = board.intersectRayPlane(tRay, board.pickerPlane);

    if (clickedItem) {
      clickedItem.emit("mouseMoved", {
        canvasX: relativeX,
        canvasY: relativeY,
        mapX: pickResult.x,
        mapY: pickResult.y,
        clickedItem: clickedItem
      });
    }
    board.emit("mouseMoved", {
      canvasX: relativeX,
      canvasY: relativeY,
      mapX: pickResult.x,
      mapY: pickResult.y,
      clickedItem: clickedItem
    });
    mousemoved = true;
  };

  canvas.addEventListener("touchmove", canvas.onmousemove, false);
  canvas.addEventListener("touchstart", canvas.onmousedown, false);

  canvas.onmouseleave = function(e) {
    e.preventDefault();
    if (down === false) {
      return;
    }
    down = false;
    var pageX = e.pageX;
    var pageY = e.pageY;

    if (e.changedTouches) {
      pageX = e.changedTouches[0].pageX;
      pageY = e.changedTouches[0].pageY;
    }
    let relativeX = pageX - canvas.offsetLeft;
    let relativeY = pageY - canvas.offsetTop;
    let tRay = board.scene.createPickingRay(
      relativeX,
      relativeY,
      babylon.Matrix.Identity(),
      board.camera
    );
    let pickResult = board.intersectRayPlane(tRay, board.pickerPlane);

    if (clickedItem) {
      clickedItem.mouseReleased(
        relativeX,
        relativeY,
        pickResult.x,
        pickResult.y,
        mousemoved
      );
      //Emit a mouseUp event, with the clickable item
      board.emit("mouseUp", {
        canvasX: relativeX,
        canvasY: relativeY,
        mapX: pickResult.x,
        mapY: pickResult.y,
        clickedItem: clickedItem,
        mousemoved: mousemoved
      });
      if (board.mouseClicked) {
        board.mouseClicked(
          relativeX,
          relativeY,
          pickResult.x,
          pickResult.y,
          true,
          mousemoved
        );
      }
    } else if (board.mouseClicked) {
      board.mouseClicked(
        relativeX,
        relativeY,
        pickResult.x,
        pickResult.y,
        false,
        mousemoved
      );
    }
    clickedItem = null;
    mousemoved = false;
  };
  canvas.onmouseup = canvas.onmouseleave;
  canvas.addEventListener("touchend", canvas.onmouseup, false);

  /**
   * Clears the canvas so the HexBoard may be re-used
   */
  this.clear = function() {
    board.scene.dispose();
  };

  /**
   * Initializes the groups and objects from the contexts, plus the drag variables
   */
  this.init = function() {
    // This creates a light, aiming 0,1,0 - to the sky.
    var light = new babylon.HemisphericLight(
      "light1",
      new babylon.Vector3(0, 0, 1),
      board.scene
    );

    // Dim the light a small amount
    light.intensity = 0.5;
  };

  /**
   * Set the hexDimensions object used for centering the screen on a cell
   * @param { external:cartesian-hexagonal } hexDimension - The DTO defining the hex <--> cartesian relation
   */
  this.setHexDimensions = function(hexDimensions) {
    board.hexDimensions = hexDimensions;
  };

  /**
     * Internal shared functionallity of paning, updates the camera and emits an event
     */
  this.updatePostion = function() {
    board.camera.target.x = board.cameraTargetX;
    board.camera.target.y = board.cameraTargetY;
    this.emitEvent("pan", { x: board.cameraTargetX, y: board.cameraTargetY });
  };

  /**
   * Pans the camera to the given position on the plane of interest
   */
  this.pan = function(x, y) {
    board.cameraTargetX = x;
    board.cameraTargetY = y;
    this.updatePosition();
  };

  /**
   * Utility function to center the board on a cell
   */
  this.centerOnCell = function(u, v) {
    var pixelCoordinates = board.hexDimensions.getPixelCoordinates(u, v);
    board.cameraTargetX = pixelCoordinates.x;
    board.cameraTargetY = pixelCoordinates.y;
    this.updatePostion();
  };

  /**
   * Helper function to get intersection between ray and plane
   */
  this.intersectRayPlane = function(pRay, pPlane) {
    var tIsecPoint = null;
    var tDot = babylon.Vector3.Dot(pRay.direction, pPlane.normal);
    if (tDot !== 0.0) {
      var t = -pPlane.signedDistanceTo(pRay.origin) / tDot;
      if (t >= 0.0) {
        var tDirS = pRay.direction.scale(t);
        tIsecPoint = pRay.origin.add(tDirS);
      }
    }
    return tIsecPoint;
  };
};

let EventEmitter = require("wolfy87-eventemitter");
module.exports.prototype = new EventEmitter();
<|endoftext|>


<commit_before>
/*development mode*/

window.requestAnimFrame = (function () {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60);
        };
})();

Function.prototype.inherit = function (parent, child) {
    function wrapper() {
    }
    wrapper.prototype = parent.prototype;
    this.prototype = new wrapper();
    $.extend(this.prototype, child);
};

function Html_Tag(node, params) {
    this.params = (!params) ? {} : params;
    this.node = $(node);
    this.node[0].itemInstance = this;

    $.fn.getItem = function () {
        if (($(this)[0]) && $(this)[0].itemInstance) {
            return $(this)[0].itemInstance;
        } else {
            return null;
        }
    };
}

Html_Tag.prototype = {
    getAttr: function (name, defVal) {
        defVal = (!defVal) ? null : defVal;
        return (this.node.attr(name)) ? this.node.attr(name) : defVal;
    },
    getAttrAsBool: function (name, defVal) {
        defVal = (!defVal) ? false : true;
        return ((this.node.attr(name)) ? parseInt(this.node.attr(name)) : defVal) ? true : false;
    },
    getAttrAsInt: function (name, defVal) {
        var value = this.node.attr(name);
        if (value) {
            return parseInt(value);
        } else {
            return (defVal) ? defVal : null;
        }
    },
    normKeyEvent: function (event) {
        event = (!event) ? window.event : event;
        event.keyCode = (!event.keyCode) ? event.charCode : event.keyCode;
        event.keyCode = (!event.keyCode) ? event.which : event.keyCode;
        return event;
    }
};
<commit_msg>refactoring<commit_after>window.requestAnimFrame = (function () {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        function (callback) {
            window.setTimeout(callback, 1000 / 60);
        };
})();

Function.prototype.inherit = function (parent, child) {
    function Wrapper() {
    }

    Wrapper.prototype = parent.prototype;
    this.prototype = new Wrapper();
    $.extend(this.prototype, child);
};

function Html_Tag(node, params) {
    this.params = (!params) ? {} : params;
    this.node = $(node);
    this.node[0].itemInstance = this;

    $.fn.getItem = function () {
        if (($(this)[0]) && $(this)[0].itemInstance) {
            return $(this)[0].itemInstance;
        } else {
            return null;
        }
    };
}

Html_Tag.prototype = {
    getAttr: function (name, defVal) {
        defVal = (!defVal) ? null : defVal;
        return (this.node.attr(name)) ? this.node.attr(name) : defVal;
    },
    /**
     * @returns {jQuery}
     */
    getNode: function () {
        return this.node;
    }
};
<|endoftext|>


<commit_before>// Controller documentation available at https://www.weepower.com/script/core#fnmake

Wee.fn.make('common', {
	_construct: function() {
		// ...
	},
	init: function() {
		this.$private.method();
	}
}, {
	method: function() {
		// ...
	}
});<commit_msg>Add navigation<commit_after>Wee.fn.make('common', {
	init: function() {
		this.$private.mobileNav();
	}
}, {
	mobileNav: function() {
		$('ref:mobileNavToggle').on('click', function() {
			$('ref:mobileNav').toggleClass('-is-active');
		});
	}
});<|endoftext|>


<commit_before>this.cutie = this.cutie || {};

(function(module){
	/**
	 * Holds a list of ASCII values for commently-accessed keybard key.s.
	 * @namespace cutie.KeyCodes
	 * @type {Object}
	 * @property {Number} UP The up arrow key on the keyboard.
	 * @property {Number} DOWN The down arrow key on the keyboard.
	 * @property {Number} LEFT The left arrow key on the keyboard.
	 * @property {Number} RIGHT The right arrow key on the keyboard.
	 * @property {Number} W The 'w' key on the keyboard.
	 * @property {Number} A The 'a' key on the keyboard.
	 * @property {Number} S The 's' key on the keyboard.
	 * @property {Number} D The 'd' key on the keyboard.
	 * @property {Number} SHIFT The shift key on the keyboard.
	 * @property {Number} RETURN The enter/return key on the keyboard.
	 * @property {Number} CTRL The control key on the keyboard.
	 * @property {Number} TAB The tab key on the keyboard.
	 * @property {Number} Q The 'q' key on the keyboard.
	 * @property {Number} E The 'e' key on the keyboard.
	 * @property {Number} Z The 'z' key on the keyboard.
	 * @property {Number} X The 'x' key on the keyboard.
	 * @property {Number} C The 'c' key on the keyboard.
	 * @property {Number} V The 'v' key on the keyboard.
	 * @property {Number} F The 'f' key on the keyboard.
	 * @property {Number} ZERO The '0' key on the keyboard.
	 * @property {Number} ONE The '1' key on the keyboard.
	 * @property {Number} TWO The '2' key on the keyboard.
	 * @property {Number} THREE The '3' key on the keyboard.
	 * @property {Number} FOUR The '4' key on the keyboard.
	 * @property {Number} FIVE The '5' key on the keyboard.
	 * @property {Number} SIX The '6' key on the keyboard.
	 * @property {Number} SEVEN The '7' key on the keyboard.
	 * @property {Number} EIGHT The '8' key on the keyboard.
	 * @property {Number} NINE The '9' key on the keyboard.
	 */
	var KeyCodes = {

		"UP": 38,
		"DOWN": 40,
		"LEFT": 37,
		"RIGHT": 39,
		"W": 87,
		"A": 65,
		"S": 83,
		"D": 68,
		"SHIFT": 16,
		"RETURN": 13,
		"CTRL": 17,
		"TAB": 9,
		"Q": 81,
		"E": 69,
		"Z": 90,
		"X": 88,
		"C": 67,
		"V": 86,
		"F": 70,
		"ZERO": 48,
		"ONE": 49,
		"TWO": 50,
		"THREE": 51,
		"FOUR": 52,
		"FIVE": 53,
		"SIX": 54,
		"SEVEN": 55,
		"EIGHT": 56,
		"NINE":57
	};

	module.KeyCodes = KeyCodes;
})(this.cutie);<commit_msg>Converted tabs to spaces in KeyCodes.<commit_after>this.cutie = this.cutie || {};

(function(module){
    /**
     * Holds a list of ASCII values for commently-accessed keybard key.s.
     * @namespace cutie.KeyCodes
     * @type {Object}
     * @property {Number} UP The up arrow key on the keyboard.
     * @property {Number} DOWN The down arrow key on the keyboard.
     * @property {Number} LEFT The left arrow key on the keyboard.
     * @property {Number} RIGHT The right arrow key on the keyboard.
     * @property {Number} W The 'w' key on the keyboard.
     * @property {Number} A The 'a' key on the keyboard.
     * @property {Number} S The 's' key on the keyboard.
     * @property {Number} D The 'd' key on the keyboard.
     * @property {Number} SHIFT The shift key on the keyboard.
     * @property {Number} RETURN The enter/return key on the keyboard.
     * @property {Number} CTRL The control key on the keyboard.
     * @property {Number} TAB The tab key on the keyboard.
     * @property {Number} Q The 'q' key on the keyboard.
     * @property {Number} E The 'e' key on the keyboard.
     * @property {Number} Z The 'z' key on the keyboard.
     * @property {Number} X The 'x' key on the keyboard.
     * @property {Number} C The 'c' key on the keyboard.
     * @property {Number} V The 'v' key on the keyboard.
     * @property {Number} F The 'f' key on the keyboard.
     * @property {Number} ZERO The '0' key on the keyboard.
     * @property {Number} ONE The '1' key on the keyboard.
     * @property {Number} TWO The '2' key on the keyboard.
     * @property {Number} THREE The '3' key on the keyboard.
     * @property {Number} FOUR The '4' key on the keyboard.
     * @property {Number} FIVE The '5' key on the keyboard.
     * @property {Number} SIX The '6' key on the keyboard.
     * @property {Number} SEVEN The '7' key on the keyboard.
     * @property {Number} EIGHT The '8' key on the keyboard.
     * @property {Number} NINE The '9' key on the keyboard.
     */
    var KeyCodes = {

        "UP": 38,
        "DOWN": 40,
        "LEFT": 37,
        "RIGHT": 39,
        "W": 87,
        "A": 65,
        "S": 83,
        "D": 68,
        "SHIFT": 16,
        "RETURN": 13,
        "CTRL": 17,
        "TAB": 9,
        "Q": 81,
        "E": 69,
        "Z": 90,
        "X": 88,
        "C": 67,
        "V": 86,
        "F": 70,
        "ZERO": 48,
        "ONE": 49,
        "TWO": 50,
        "THREE": 51,
        "FOUR": 52,
        "FIVE": 53,
        "SIX": 54,
        "SEVEN": 55,
        "EIGHT": 56,
        "NINE":57
    };

    module.KeyCodes = KeyCodes;
})(this.cutie);<|endoftext|>