<commit_before>// @flow
import React, { Component, Fragment } from 'react';
import { observer } from 'mobx-react';
import {
  defineMessages,
  intlShape,
  FormattedMessage,
  FormattedHTMLMessage,
} from 'react-intl';
import SVGInline from 'react-svg-inline';
import Wallet from '../../../domains/Wallet';
import settingsIcon from '../../../assets/images/wallet-nav/wallet-settings-2-ic.inline.svg';
import { SIMPLE_DECIMAL_PLACES_IN_ADA } from '../../../config/numbersConfig';
import DropdownMenu from './DropdownMenu';
import DonutRing from './DonutRing';
import styles from './WalletRow.scss';

export const DELEGATION_ACTIONS = {
  CHANGE_DELEGATION: 'changeDelegation',
  REMOVE_DELEGATION: 'removeDelegation',
};

const messages = defineMessages({
  walletAmount: {
    id: 'staking.delegationCenter.walletAmount',
    defaultMessage: '!!!{amount} ada',
    description:
      'Amount of each wallet for the Delegation center body section.',
  },
  inactiveStakePercentageActivate: {
    id: 'staking.delegationCenter.inactiveStakePercentageActivate',
    defaultMessage:
      '!!!activate {inactiveStakePercentage}% of inactive stake',
    description:
      'Inactive stake percentage of each wallet for the Delegation center body section.',
  },
  delegated: {
    id: 'staking.delegationCenter.delegated',
    defaultMessage: '!!!Delegated',
    description: 'Delegated label for the Delegation center body section.',
  },
  notDelegated: {
    id: 'staking.delegationCenter.notDelegated',
    defaultMessage: '!!!Not-delegated',
    description: 'Not-delegated label for the Delegation center body section.',
  },
  changeDelegation: {
    id: 'staking.delegationCenter.changeDelegation',
    defaultMessage: '!!!Change delegation',
    description:
      'Change delegation label for the Delegation center body section.',
  },
  removeDelegation: {
    id: 'staking.delegationCenter.removeDelegation',
    defaultMessage: '!!!Remove delegation',
    description:
      'Remove delegation label for the Delegation center body section.',
  },
  toStakePoolCategory: {
    id: 'staking.delegationCenter.toStakePoolCategory',
    defaultMessage: '!!!To [{delegatedPoolCategory}] stake pool',
    description:
      'Delegated stake pool category label for the Delegation center body section.',
  },
  delegate: {
    id: 'staking.delegationCenter.delegate',
    defaultMessage: '!!!Delegate',
    description: 'Delegate label for the Delegation center body section.',
  },
  yourStake: {
    id: 'staking.delegationCenter.yourStake',
    defaultMessage: '!!!your stake',
    description: 'Your stake label for the Delegation center body section.',
  },
});

type Props = { wallet: Wallet };

@observer
export default class WalletRow extends Component<Props> {
  static contextTypes = {
    intl: intlShape.isRequired,
  };

  render() {
    const { intl } = this.context;
    const {
      wallet: {
        name,
        amount,
        inactiveStakePercentage,
        isDelegated,
        delegatedPoolCategory,
      },
    } = this.props;
    const inactiveStakePercentageValue = inactiveStakePercentage || 0;
    const delegated = intl.formatMessage(messages.delegated);
    const notDelegated = intl.formatMessage(messages.notDelegated);
    const changeDelegation = intl.formatMessage(messages.changeDelegation);
    const removeDelegation = intl.formatMessage(messages.removeDelegation);
    const yourStake = intl.formatMessage(messages.yourStake);
    const delegationActionOptions = [
      {
        label: changeDelegation,
        value: DELEGATION_ACTIONS.CHANGE_DELEGATION,
        className: styles.normalOption,
      },
      {
        label: removeDelegation,
        value: DELEGATION_ACTIONS.REMOVE_DELEGATION,
        className: styles.removeOption,
      },
    ];

    return (

{name}

            <FormattedMessage
              {...messages.walletAmount}
              values={{
                amount: amount.toFormat(SIMPLE_DECIMAL_PLACES_IN_ADA),
              }}
            />
            {inactiveStakePercentageValue > 0 && (
              <Fragment>

                  <DonutRing
                    percentage={100 - inactiveStakePercentageValue}
                    sqSize={11}
                    strokeWidth={3}
                  />

                <FormattedHTMLMessage
                  {...messages.inactiveStakePercentageActivate}
                  values={{
                    inactiveStakePercentage: inactiveStakePercentageValue,
                  }}
                />
              </Fragment>
            )}

            {isDelegated ? delegated : notDelegated}
            <DropdownMenu
              label={
                <SVGInline svg={settingsIcon} className={styles.gearIcon} />
              }
              menuItems={delegationActionOptions}
              onMenuItemClick={value =>
                console.log('----here---fuck---', value)
              }
            />

            {isDelegated ? (
              <FormattedHTMLMessage
                {...messages.toStakePoolCategory}
                values={{ delegatedPoolCategory }}
              />
            ) : (

                <FormattedHTMLMessage {...messages.delegate} /> {yourStake}

            )}

    );
  }
}
<commit_msg>[DDW-651]: Remove unnecessary console log statement<commit_after>// @flow
import React, { Component, Fragment } from 'react';
import { observer } from 'mobx-react';
import {
  defineMessages,
  intlShape,
  FormattedMessage,
  FormattedHTMLMessage,
} from 'react-intl';
import SVGInline from 'react-svg-inline';
import Wallet from '../../../domains/Wallet';
import settingsIcon from '../../../assets/images/wallet-nav/wallet-settings-2-ic.inline.svg';
import { SIMPLE_DECIMAL_PLACES_IN_ADA } from '../../../config/numbersConfig';
import DropdownMenu from './DropdownMenu';
import DonutRing from './DonutRing';
import styles from './WalletRow.scss';

export const DELEGATION_ACTIONS = {
  CHANGE_DELEGATION: 'changeDelegation',
  REMOVE_DELEGATION: 'removeDelegation',
};

const messages = defineMessages({
  walletAmount: {
    id: 'staking.delegationCenter.walletAmount',
    defaultMessage: '!!!{amount} ada',
    description:
      'Amount of each wallet for the Delegation center body section.',
  },
  inactiveStakePercentageActivate: {
    id: 'staking.delegationCenter.inactiveStakePercentageActivate',
    defaultMessage:
      '!!!activate {inactiveStakePercentage}% of inactive stake',
    description:
      'Inactive stake percentage of each wallet for the Delegation center body section.',
  },
  delegated: {
    id: 'staking.delegationCenter.delegated',
    defaultMessage: '!!!Delegated',
    description: 'Delegated label for the Delegation center body section.',
  },
  notDelegated: {
    id: 'staking.delegationCenter.notDelegated',
    defaultMessage: '!!!Not-delegated',
    description: 'Not-delegated label for the Delegation center body section.',
  },
  changeDelegation: {
    id: 'staking.delegationCenter.changeDelegation',
    defaultMessage: '!!!Change delegation',
    description:
      'Change delegation label for the Delegation center body section.',
  },
  removeDelegation: {
    id: 'staking.delegationCenter.removeDelegation',
    defaultMessage: '!!!Remove delegation',
    description:
      'Remove delegation label for the Delegation center body section.',
  },
  toStakePoolCategory: {
    id: 'staking.delegationCenter.toStakePoolCategory',
    defaultMessage: '!!!To [{delegatedPoolCategory}] stake pool',
    description:
      'Delegated stake pool category label for the Delegation center body section.',
  },
  delegate: {
    id: 'staking.delegationCenter.delegate',
    defaultMessage: '!!!Delegate',
    description: 'Delegate label for the Delegation center body section.',
  },
  yourStake: {
    id: 'staking.delegationCenter.yourStake',
    defaultMessage: '!!!your stake',
    description: 'Your stake label for the Delegation center body section.',
  },
});

type Props = { wallet: Wallet };

@observer
export default class WalletRow extends Component<Props> {
  static contextTypes = {
    intl: intlShape.isRequired,
  };

  render() {
    const { intl } = this.context;
    const {
      wallet: {
        name,
        amount,
        inactiveStakePercentage,
        isDelegated,
        delegatedPoolCategory,
      },
    } = this.props;
    const inactiveStakePercentageValue = inactiveStakePercentage || 0;
    const delegated = intl.formatMessage(messages.delegated);
    const notDelegated = intl.formatMessage(messages.notDelegated);
    const changeDelegation = intl.formatMessage(messages.changeDelegation);
    const removeDelegation = intl.formatMessage(messages.removeDelegation);
    const yourStake = intl.formatMessage(messages.yourStake);
    const delegationActionOptions = [
      {
        label: changeDelegation,
        value: DELEGATION_ACTIONS.CHANGE_DELEGATION,
        className: styles.normalOption,
      },
      {
        label: removeDelegation,
        value: DELEGATION_ACTIONS.REMOVE_DELEGATION,
        className: styles.removeOption,
      },
    ];

    return (

{name}

            <FormattedMessage
              {...messages.walletAmount}
              values={{
                amount: amount.toFormat(SIMPLE_DECIMAL_PLACES_IN_ADA),
              }}
            />
            {inactiveStakePercentageValue > 0 && (
              <Fragment>

                  <DonutRing
                    percentage={100 - inactiveStakePercentageValue}
                    sqSize={11}
                    strokeWidth={3}
                  />

                <FormattedHTMLMessage
                  {...messages.inactiveStakePercentageActivate}
                  values={{
                    inactiveStakePercentage: inactiveStakePercentageValue,
                  }}
                />
              </Fragment>
            )}

            {isDelegated ? delegated : notDelegated}
            <DropdownMenu
              label={
                <SVGInline svg={settingsIcon} className={styles.gearIcon} />
              }
              menuItems={delegationActionOptions}
              onMenuItemClick={() => null}
            />

            {isDelegated ? (
              <FormattedHTMLMessage
                {...messages.toStakePoolCategory}
                values={{ delegatedPoolCategory }}
              />
            ) : (

                <FormattedHTMLMessage {...messages.delegate} /> {yourStake}

            )}

    );
  }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import s from './ServiceEdit.css'
import icons from '../../icons/css/icons.css'
import { gender } from '../../lib/eligibilities'
import { age } from '../../lib/eligibilities'
import { uuid } from '../../lib/uuid'
import TimeRangePicker from '../TimeRangePicker'
import ToggleButton from '../ToggleButton'

/* The existing times range 0-2359. This was the easiest way I could think of to make sure that the previous day always weighted less than the next day. */
const scheduleSorter = {
  "-":        -1,
  "Sunday":    0,
  "Monday":    10000,
  "Tuesday":   20000,
  "Wednesday": 30000,
  "Thursday":  40000,
  "Friday":    50000,
  "Saturday":  60000
}

class ServiceEdit extends Component {

  blankSchedule = () => {
    const { service } = this.props
    return {
      opensAt: "0000",
      closesAt: "0000",
      id: uuid(),
      locationId: service.locationId,
      organizationId: service.organization,
      serviceId: service.id,
      weekday: "-"
    }
  }

  updateService = (field, value) => {
    const { service, handleChange } = this.props
    const newService = service

    newService[field] = value
    handleChange(newService)
  }

  deleteService = () => {
    const { service, handleDelete } = this.props

    handleDelete(service)
  }

  handleServiceChange = (field, event) => {
    this.updateService(field, event.target.value)
  }

  handleGender = (value) => {
    const { eligibility } = this.props.service
    const newEligibility = eligibility

    newEligibility.gender = value.key
    this.updateService('eligibility', newEligibility)
  }

  handleAge = (value) => {
    const { eligibility } = this.props.service
    const newEligibility = eligibility
    let newAge = newEligibility.age || ''

    if (newAge.includes(value.key)) {
      newAge = newAge.replace(value.key, '')
    } else {
      newAge = newAge + value.key
    }

    newEligibility.age = newAge
    this.updateService('eligibility', newEligibility)
  }

  getAgeClass = (value) => {
    let classes = [s.selectableButton]
    const { eligibility } = this.props.service
    let stateVal = eligibility ? (eligibility.age || '') : ''

    return stateVal.includes(value.key)
  }

  getGenderClass = (value) => {
    let classes = [s.selectableButton]
    const { eligibility } = this.props.service
    let stateVal = eligibility ? eligibility.gender : ''

    return stateVal == value.key
  }

  getCategoryClass = (value) => {
    let classes = [s.selectableButton]
    const { taxonomy } = this.props.service

    return taxonomy.toLowerCase() == value
  }

  handleTimeChange = (event, value_changed, metadata) => {
    const { schedules } = this.props.service
    const newSchedules = schedules

    if (value_changed == 'start') {
      newSchedules[metadata.scheduleNum]['opensAt'] = event.target.value.replace(':', '')
    } else if (value_changed == 'end') {
      newSchedules[metadata.scheduleNum]['closesAt'] = event.target.value.replace(':', '')
    } else {
      if (event.target.value == '-'){
        window.alert("You must choose a weekday for a schedule")
        return
      }
      newSchedules[metadata.scheduleNum]['weekday'] = event.target.value
    }

    this.updateService('schedules', newSchedules)
  }

  handleTimeDelete = (index) => {
    const { schedules } = this.props.service
    const newSchedules = schedules

    newSchedules.splice(index, 1)

    this.updateService('schedules', newSchedules)
  }

  sortSchedules = (schedules) => {
    return schedules.sort(function(a, b) {
      return (scheduleSorter[a.weekday] + parseInt(a.opensAt)) - (scheduleSorter[b.weekday] + parseInt(b.opensAt))
    })
  }

  newSchedule = () => {
    const { schedules } = this.props.service
    const newSchedules = schedules

    newSchedules.push(this.blankSchedule())

    this.updateService('schedules', newSchedules)
  }

  render() {
    const { service, taxonomies } = this.props

    return (

            Service Name
            <input
              className={s.input}
              type="text"
              value={service.name}
              onChange={(e) => this.handleServiceChange('name', e)}
            />

            Service Description
            <input
              className={s.input}
              type="text"
              value={service.description}
              onChange={(e) => this.handleServiceChange('description', e)}
            />

            Application Process
            <textarea
              className={s.input}
              type="text"
              value={service.applicationProcess}
              onChange={(e) => this.handleServiceChange('applicationProcess', e)}
            />

            Category:
            {(taxonomies).map((category, i) => (

                <ToggleButton
                  key={`category-${i}`}
                  enabled={this.getCategoryClass(category.name.toLowerCase())}
                  extraClasses={`${s.categoryIcon} ${category.icon}`}
                  onClick={(e) => this.updateService('taxonomy', category.name.toLowerCase())}
                  label={category.name}
                />

            ))}

Select all that apply:

          <GenderBox
            gender={service.eligibility && service.eligibility.gender}
            getGenderClass={this.getGenderClass}
            handleGender={this.handleGender}/>

          <AgeBox
            getAgeClass={this.getAgeClass}
            handleAge={this.handleAge} />

          Schedules
          <button
            className={s.addToSubsection}
            onClick={this.newSchedule}
            title={`Click to add a new schedule`}>
            + Add
          </button>

            Schedule:
            {(this.sortSchedules(service.schedules)).map((schedule, index) => (
              <ScheduleBox
                key={`schedule-${index}`}
                index={index}
                schedule={schedule}
                handleTimeChange={this.handleTimeChange}
                handleTimeDelete={this.handleTimeDelete} />
            ))}

            <button
              className={s.buttonStyle}
              onClick={this.deleteService}
            >
            Delete this Service
            </button>

    )
  }
}

const GenderBox = (props) => (

    Gender Eligibility:
    {gender.map((gender, i) => (

       <ToggleButton
         key={`gender-${gender.name}`}
         enabled={props.getGenderClass(gender)}
         extraClasses={`${s.categoryIcon} ${gender.icon}`}
         onClick={(e) => props.handleGender(gender)}
         label={gender.name}
       />

    ))}

)

const AgeBox = (props) => (

    Age Eligibility:
    {age.map((age, i) => (

       <ToggleButton
         key={`age-${age.name}`}
         enabled={props.getAgeClass(age)}
         onClick={(e) => props.handleAge(age)}
         label={age.name}
       />

    ))}

)

const ScheduleBox = (props) => (

    <TimeRangePicker
      key={`timePicker-${props.index}`}
      weekday={props.schedule.weekday}
      startTime={props.schedule.opensAt}
      endTime={props.schedule.closesAt}
      handleUpdate={props.handleTimeChange}
      handleDelete={props.handleTimeDelete}
      metadata={{ scheduleNum: props.index, day: props.index}}/>

)

export default ServiceEdit
<commit_msg>Save eligibility as an array<commit_after>import React, { Component } from 'react'
import s from './ServiceEdit.css'
import icons from '../../icons/css/icons.css'
import { gender } from '../../lib/eligibilities'
import { age } from '../../lib/eligibilities'
import { uuid } from '../../lib/uuid'
import TimeRangePicker from '../TimeRangePicker'
import ToggleButton from '../ToggleButton'

/* The existing times range 0-2359. This was the easiest way I could think of to make sure that the previous day always weighted less than the next day. */
const scheduleSorter = {
  "-":        -1,
  "Sunday":    0,
  "Monday":    10000,
  "Tuesday":   20000,
  "Wednesday": 30000,
  "Thursday":  40000,
  "Friday":    50000,
  "Saturday":  60000
}

class ServiceEdit extends Component {

  blankSchedule = () => {
    const { service } = this.props
    return {
      opensAt: "0000",
      closesAt: "0000",
      id: uuid(),
      locationId: service.locationId,
      organizationId: service.organization,
      serviceId: service.id,
      weekday: "-"
    }
  }

  updateService = (field, value) => {
    const { service, handleChange } = this.props
    const newService = service

    newService[field] = value
    handleChange(newService)
  }

  deleteService = () => {
    const { service, handleDelete } = this.props

    handleDelete(service)
  }

  handleServiceChange = (field, event) => {
    this.updateService(field, event.target.value)
  }

  handleGender = (value) => {
    const { eligibility } = this.props.service
    const newEligibility = eligibility

    newEligibility.gender = value.key
    this.updateService('eligibility', newEligibility)
  }

  handleAge = (value) => {
    const { eligibility } = this.props.service
    const newEligibility = eligibility
    let newAge = newEligibility.age || []

    if (newAge.includes(value.key)) {
      newAge = newAge.filter(age => age !== value.key)
    } else {
      newAge = [...newAge, value.key];
    }

    newEligibility.age = newAge
    this.updateService('eligibility', newEligibility)
  }

  getAgeClass = (value) => {
    let classes = [s.selectableButton]
    const { eligibility } = this.props.service
    let stateVal = eligibility ? (eligibility.age || []) : []

    return stateVal.includes(value.key)
  }

  getGenderClass = (value) => {
    let classes = [s.selectableButton]
    const { eligibility } = this.props.service
    let stateVal = eligibility ? eligibility.gender : ''

    return stateVal == value.key
  }

  getCategoryClass = (value) => {
    let classes = [s.selectableButton]
    const { taxonomy } = this.props.service

    return taxonomy.toLowerCase() == value
  }

  handleTimeChange = (event, value_changed, metadata) => {
    const { schedules } = this.props.service
    const newSchedules = schedules

    if (value_changed == 'start') {
      newSchedules[metadata.scheduleNum]['opensAt'] = event.target.value.replace(':', '')
    } else if (value_changed == 'end') {
      newSchedules[metadata.scheduleNum]['closesAt'] = event.target.value.replace(':', '')
    } else {
      if (event.target.value == '-'){
        window.alert("You must choose a weekday for a schedule")
        return
      }
      newSchedules[metadata.scheduleNum]['weekday'] = event.target.value
    }

    this.updateService('schedules', newSchedules)
  }

  handleTimeDelete = (index) => {
    const { schedules } = this.props.service
    const newSchedules = schedules

    newSchedules.splice(index, 1)

    this.updateService('schedules', newSchedules)
  }

  sortSchedules = (schedules) => {
    return schedules.sort(function(a, b) {
      return (scheduleSorter[a.weekday] + parseInt(a.opensAt)) - (scheduleSorter[b.weekday] + parseInt(b.opensAt))
    })
  }

  newSchedule = () => {
    const { schedules } = this.props.service
    const newSchedules = schedules

    newSchedules.push(this.blankSchedule())

    this.updateService('schedules', newSchedules)
  }

  render() {
    const { service, taxonomies } = this.props

    return (

            Service Name
            <input
              className={s.input}
              type="text"
              value={service.name}
              onChange={(e) => this.handleServiceChange('name', e)}
            />

            Service Description
            <input
              className={s.input}
              type="text"
              value={service.description}
              onChange={(e) => this.handleServiceChange('description', e)}
            />

            Application Process
            <textarea
              className={s.input}
              type="text"
              value={service.applicationProcess}
              onChange={(e) => this.handleServiceChange('applicationProcess', e)}
            />

            Category:
            {(taxonomies).map((category, i) => (

                <ToggleButton
                  key={`category-${i}`}
                  enabled={this.getCategoryClass(category.name.toLowerCase())}
                  extraClasses={`${s.categoryIcon} ${category.icon}`}
                  onClick={(e) => this.updateService('taxonomy', category.name.toLowerCase())}
                  label={category.name}
                />

            ))}

Select all that apply:

          <GenderBox
            gender={service.eligibility && service.eligibility.gender}
            getGenderClass={this.getGenderClass}
            handleGender={this.handleGender}/>

          <AgeBox
            getAgeClass={this.getAgeClass}
            handleAge={this.handleAge} />

          Schedules
          <button
            className={s.addToSubsection}
            onClick={this.newSchedule}
            title={`Click to add a new schedule`}>
            + Add
          </button>

            Schedule:
            {(this.sortSchedules(service.schedules)).map((schedule, index) => (
              <ScheduleBox
                key={`schedule-${index}`}
                index={index}
                schedule={schedule}
                handleTimeChange={this.handleTimeChange}
                handleTimeDelete={this.handleTimeDelete} />
            ))}

            <button
              className={s.buttonStyle}
              onClick={this.deleteService}
            >
            Delete this Service
            </button>

    )
  }
}

const GenderBox = (props) => (

    Gender Eligibility:
    {gender.map((gender, i) => (

       <ToggleButton
         key={`gender-${gender.name}`}
         enabled={props.getGenderClass(gender)}
         extraClasses={`${s.categoryIcon} ${gender.icon}`}
         onClick={(e) => props.handleGender(gender)}
         label={gender.name}
       />

    ))}

)

const AgeBox = (props) => (

    Age Eligibility:
    {age.map((age, i) => (

       <ToggleButton
         key={`age-${age.name}`}
         enabled={props.getAgeClass(age)}
         onClick={(e) => props.handleAge(age)}
         label={age.name}
       />

    ))}

)

const ScheduleBox = (props) => (

    <TimeRangePicker
      key={`timePicker-${props.index}`}
      weekday={props.schedule.weekday}
      startTime={props.schedule.opensAt}
      endTime={props.schedule.closesAt}
      handleUpdate={props.handleTimeChange}
      handleDelete={props.handleTimeDelete}
      metadata={{ scheduleNum: props.index, day: props.index}}/>

)

export default ServiceEdit
<|endoftext|>


<commit_before>/*jslint nomen:true*/
/*global define*/
define(['jquery', 'underscore', 'orotranslation/js/translator', './choice-filter',
        'orolocale/js/locale-settings', '../datevariables-widget'
    ], function ($, _, __, ChoiceFilter, localeSettings) {
    'use strict';

    /**
     * Date filter: filter type as option + interval begin and end dates
     *
     * @export  orofilter/js/filter/date-filter
     * @class   orofilter.filter.DateFilter
     * @extends orofilter.filter.ChoiceFilter
     */
    return ChoiceFilter.extend({
        /**
         * Template selector for filter criteria
         *
         * @property
         */
        templateSelector: '#date-filter-template',

        /**
         * Template selector for date field parts
         *
         * @property
         */
        fieldTemplateSelector: '#select-field-template',

        /**
         * Template selector for dropdown container
         *
         * @property
         */
        dropdownTemplateSelector: '#date-filter-dropdown-template',

        /**
         * Selectors for filter data
         *
         * @property
         */
        criteriaValueSelectors: {
            type: 'select[name!=date_part]',
            part: 'select[name=date_part]',
            value: {
                start: 'input[name="start"]',
                end:   'input[name="end"]'
            }
        },

        /**
         * CSS class for visual date input elements
         *
         * @property
         */
        inputClass: 'date-visual-element',

        /**
         * Date widget options
         *
         * @property
         */
        dateWidgetOptions: {
            changeMonth: true,
            changeYear:  true,
            yearRange:  '-80:+1',
            dateFormat: localeSettings.getVendorDateTimeFormat('jquery_ui', 'date', 'mm/dd/yy'),
            altFormat:  'yy-mm-dd',
            className:      'date-filter-widget',
            showButtonPanel: true
        },

        /**
         * Additional date widget options that might be passed to filter
         * http://api.jqueryui.com/datepicker/
         *
         * @property
         */
        externalWidgetOptions: {},

        /**
         * References to date widgets
         *
         * @property
         */
        dateWidgets: {
            start: null,
            end: null
        },

        /**
         * Date filter type values
         *
         * @property
         */
        typeValues: {
            between:    1,
            notBetween: 2,
            moreThan:   3,
            lessThan:   4
        },

        defaultTabs: [
            {
                name: 'calendar',
                label: 'oro.filter.date.tab.calendar'
            },
            {
                name: 'variables',
                label: 'oro.filter.date.tab.variables'
            }
        ],

        /**
         * Date widget selector
         *
         * @property
         */
        dateWidgetSelector: 'div#ui-datepicker-div.ui-datepicker',

        /**
         * Date parts
         *
         * @property
         */
        dateParts: [],

        hasPartsElement: false,

        /**
         * @inheritDoc
         */
        initialize: function () {
            _.extend(this.dateWidgetOptions, this.externalWidgetOptions);

            //parts rendered only if theme exist
            this.hasPartsElement = (this.templateTheme != "");

            // init empty value object if it was not initialized so far
            if (_.isUndefined(this.emptyValue)) {
                this.emptyValue = {
                    type: (_.isEmpty(this.choices) ? '' : _.first(this.choices).value),
                    part: 'value',
                    value: {
                        start: '',
                        end: ''
                    }
                };
            }

            if (_.isUndefined(this.dateParts)) {
                this.dateParts = [];
            }
            // temp code to keep backward compatible
            if ($.isPlainObject(this.dateParts)) {
                this.dateParts = _.map(this.dateParts, function (option, i) {
                    return {value: i.toString(), label: option};
                });
            }

            if (_.isUndefined(this.emptyPart)) {
                var firstPart = _.first(this.dateParts).value;
                this.emptyPart = {
                    type: (_.isEmpty(this.dateParts) ? '' : firstPart),
                    value: firstPart
                };
            }

            ChoiceFilter.prototype.initialize.apply(this, arguments);
        },

        onChangeFilterType: function (e) {
            var select = this.$el.find(e.currentTarget);
            var selectedValue = select.val() || select.data('value');

            this.changeFilterType(selectedValue);
        },

        changeFilterType: function (type) {
            // filter filter range types
            if (this.dateWidgets.start_vars && type.length > 1) {
                this.$el.find(this.criteriaValueSelectors.value.start).val('');
                this.dateWidgets.start_vars.dateVariables('setPart', type);
            }
            if (this.dateWidgets.end_vars && type.length > 1) {
                this.$el.find(this.criteriaValueSelectors.value.end).val('');
                this.dateWidgets.end_vars.dateVariables('setPart', type);
            }

            type = parseInt(type, 10);

            // check it's valid integer
            if (type === parseInt(type)) {
                this.$el.find('.filter-separator').show().end().find('input').show();
            }

            if (this.typeValues.moreThan === type) {
                this.$el.find('.filter-separator').hide();
                this.$el.find(this.criteriaValueSelectors.value.end).val('').hide();
            } else if (this.typeValues.lessThan === type) {
                this.$el.find('.filter-separator').hide();
                this.$el.find(this.criteriaValueSelectors.value.start).val('').hide();
            }
        },

        /**
         * @inheritDoc
         */
        _renderCriteria: function () {
            var value = _.extend({}, this.emptyValue, this.getValue());
            var part  = {value: value.part, type: value.part};

            var selectedChoiceLabel = this._getSelectedChoiceLabel('choices', value);
            var selectedPartLabel   = this._getSelectedChoiceLabel('dateParts', part);
            this.dateWidgetOptions.part = part.type;

            var datePartTemplate = this._getTemplate(this.fieldTemplateSelector);
            var dropdownTemplate = this._getTemplate(this.dropdownTemplateSelector);
            var parts = [];

            // add date parts only if embed template used
            if (this.templateTheme !== "") {
                parts.push(
                    datePartTemplate({
                        name: this.name + '_part',
                        choices: this.dateParts,
                        selectedChoice: value.part,
                        selectedChoiceLabel: selectedPartLabel
                    })
                );
            }

            parts.push(
                datePartTemplate({
                    name: this.name,
                    choices: this.choices,
                    selectedChoice: value.type,
                    selectedChoiceLabel: selectedChoiceLabel
                })
            );

            var displayValue = this._formatDisplayValue(value);
            var $filter = $(
                this.template({
                    inputClass: this.inputClass,
                    value: displayValue,
                    parts: parts
                })
            );

            this._appendFilter($filter);
            this.$(this.criteriaSelector).attr('tabindex', '0');

            this.changeFilterType(value.type);

            $filter.find('select:first').bind('change', _.bind(this.onChangeFilterType, this));

            _.each(this.criteriaValueSelectors.value, _.bind(this._appendDropdown, this, dropdownTemplate));

            if (!this._isDateVariable(displayValue.value.start)) {
                this.dateWidgets.start.datepicker('setDate', displayValue.value.start);
            }
            if (!this._isDateVariable(displayValue.value.end)) {
                this.dateWidgets.end.datepicker('setDate', displayValue.value.end);
            }

            this.$('.nav-tabs a').click(function (e) {
                e.preventDefault();
                $(this).tab('show');
            });

            this._criteriaRenderd = true;
        },

        /**
         * @param {string} value
         * @returns {boolean}
         * @private
         */
        _isDateVariable: function (value) {
            var dateVars = this.dateWidgetOptions.dateVars;
            for (var i in dateVars.value) {
                if (dateVars.value.hasOwnProperty(i) && dateVars.value[i] == value) {
                    return true;
                }
            }

            return false;
        },

        /**
         * @param {function} template
         * @param {string} actualSelector
         * @param {string} name
         * @private
         */
        _appendDropdown: function (template, actualSelector, name) {
            var $calendar, $el = this.$el,
                $input = this.$(actualSelector),
                $dropdown = $input.wrap('<div class="dropdown datefilter">').parent(),
                tabSuffix = '-' + this.cid + '-' + name,
                widgetOptions = _.extend({onSelect: function (date) {
                    $input.val(date).trigger('change');
                }}, this.dateWidgetOptions);

            var tabs = [];
            _.each(widgetOptions.tabs || this.defaultTabs, function(tab) {
                var currentTab   = _.clone(tab);
                currentTab.label = __(currentTab.label);
                tabs.push(currentTab);
            });
            $input.after(template({
                tabs:   tabs,
                suffix: tabSuffix
            }));

            $input.on('focus, click', function () {
                $el.find('.dropdown.open').removeClass('open');
                $dropdown.addClass('open');
                $calendar.datepicker('refresh');
            });

            $calendar = this.dateWidgets[name] = this._initializeDateWidget('#calendar' + tabSuffix, widgetOptions);
            $calendar.addClass(widgetOptions.className)
                .click(function (e) {
                    e.stopImmediatePropagation();
                });

            $calendar.data('datepicker').inline = false;
            $calendar.datepicker('refresh');
            $calendar.on('click', '.ui-datepicker-close', function() {
                $dropdown.removeClass('open');
            });

            widgetOptions = _.extend({
                $input: $input
            }, this.dateWidgetOptions);
            this.dateWidgets[name + '_vars'] = this._initializeDateVariablesWidget('#variables' + tabSuffix, widgetOptions);
        },

        /**
         * Initialize date widget
         *
         * @param {String} widgetSelector
         * @param {Object} options
         * @return {*}
         * @protected
         */
        _initializeDateWidget: function (widgetSelector, options) {
            return this.$(widgetSelector).datepicker(options);
        },

        /**
         * Initialize date variables widget
         *
         * @param {String} widgetSelector
         * @param {Object} options
         * @return {*}
         * @protected
         */
        _initializeDateVariablesWidget: function (widgetSelector, options) {
            this.$(widgetSelector).dateVariables(options);

            var widget = this.$(widgetSelector).dateVariables('widget');
            widget.addClass(options.className);

            return widget;
        },

        /**
         * @inheritDoc
         */
        _getCriteriaHint: function () {
            var hint = '',
                option, start, end, type,
                value = (arguments.length > 0) ? this._getDisplayValue(arguments[0]) : this._getDisplayValue();
            if (value.value) {
                start = value.value.start;
                end   = value.value.end;
                type  = value.type ? value.type.toString() : '';

                switch (type) {
                    case this.typeValues.moreThan.toString():
                        hint += [__('more than'), start].join(' ');
                        break;
                    case this.typeValues.lessThan.toString():
                        hint += [__('less than'), end].join(' ');
                        break;
                    case this.typeValues.notBetween.toString():
                        if (start && end) {
                            option = this._getChoiceOption(this.typeValues.notBetween);
                            hint += [option.label, start, __('and'), end].join(' ');
                        } else if (start) {
                            hint += [__('before'), start].join(' ');
                        } else if (end) {
                            hint += [__('after'), end].join(' ');
                        }
                        break;
                    case this.typeValues.between.toString():
                    default:
                        if (start && end) {
                            option = this._getChoiceOption(this.typeValues.between);
                            hint += [option.label, start, __('and'), end].join(' ');
                        } else if (start) {
                            hint += [__('from'), start].join(' ');
                        } else if (end) {
                            hint += [__('to'), end].join(' ');
                        }
                        break;
                }
                if (hint) {
                    return hint;
                }
            }

            return this.placeholder;
        },

        /**
         * @inheritDoc
         */
        _formatDisplayValue: function (value) {
            var fromFormat = this.dateWidgetOptions.altFormat;
            var toFormat = this.dateWidgetOptions.dateFormat;

            if (value.value && value.value.start) {
                value.value.start = this._replaceDateVars(value.value.start, 'display');
            }
            if (value.value && value.value.end) {
                value.value.end = this._replaceDateVars(value.value.end, 'display');
            }

            return this._formatValueDates(value, fromFormat, toFormat);
        },

        /**
         * @inheritDoc
         */
        _formatRawValue: function (value) {
            var fromFormat = this.dateWidgetOptions.dateFormat;
            var toFormat = this.dateWidgetOptions.altFormat;

            if (value.value && value.value.start) {
                value.value.start = this._replaceDateVars(value.value.start, 'raw');
            }
            if (value.value && value.value.end) {
                value.value.end = this._replaceDateVars(value.value.end, 'raw');
            }

            return this._formatValueDates(value, fromFormat, toFormat);
        },

        /**
         * Format dates in a vault to another format
         *
         * @param {Object} value
         * @param {String} fromFormat
         * @param {String} toFormat
         * @return {Object}
         * @protected
         */
        _formatValueDates: function (value, fromFormat, toFormat) {
            if (value.value && value.value.start) {
                value.value.start = this._formatDate(value.value.start, fromFormat, toFormat);
            }
            if (value.value && value.value.end) {
                value.value.end = this._formatDate(value.value.end, fromFormat, toFormat);
            }
            return value;
        },

        _replaceDateVars: function (value, mode) {
            // replace date variables with constant values
            var dateVars = this.dateWidgetOptions.dateVars;

            if (mode == 'raw') {
                for (var part in dateVars) {
                    if (dateVars.hasOwnProperty(part)) {
                        for (var varCode in dateVars[part]) {
                            if (dateVars[part].hasOwnProperty(varCode)) {
                                value = value.replace(new RegExp(dateVars[part][varCode], 'g'), '{{' + varCode+'}}');
                            }
                        }
                    }
                }
            } else {
                for (var part in dateVars) {
                    if (dateVars.hasOwnProperty(part)) {
                        for (var varCode in dateVars[part]) {
                            if (dateVars[part].hasOwnProperty(varCode)) {
                                value = value.replace(new RegExp('\{+' + varCode + '\}+', 'gi'), dateVars[part][varCode]);
                            }
                        }
                    }
                }
            }

            return value;
        },

        /**
         * Formats date string to another format
         *
         * @param {String} value
         * @param {String} fromFormat
         * @param {String} toFormat
         * @return {String}
         * @protected
         */
        _formatDate: function (value, fromFormat, toFormat) {
            var fromValue = $.datepicker.parseDate(fromFormat, value);
            if (!fromValue) {
                fromValue = $.datepicker.parseDate(toFormat, value);
                if (!fromValue) {
                    return value;
                }
            }
            return $.datepicker.formatDate(toFormat, fromValue);
        },

        /**
         * @inheritDoc
         */
        _writeDOMValue: function (value) {
            this._setInputValue(this.criteriaValueSelectors.value.start, value.value.start);
            this._setInputValue(this.criteriaValueSelectors.value.end, value.value.end);
            this._setInputValue(this.criteriaValueSelectors.type, value.type);
            if (value.part) {
                this._setInputValue(this.criteriaValueSelectors.part, value.part);
            }
            return this;
        },

        /**
         * @inheritDoc
         */
        _readDOMValue: function () {
            return {
                type: this._getInputValue(this.criteriaValueSelectors.type),
                //empty default parts value if parts not exist
                part: this.hasPartsElement ? this._getInputValue(this.criteriaValueSelectors.part) : 'value',
                value: {
                    start: this._getInputValue(this.criteriaValueSelectors.value.start),
                    end:   this._getInputValue(this.criteriaValueSelectors.value.end)
                }
            };
        },

        /**
         * @inheritDoc
         */
        _focusCriteria: function () {
            this.$(this.criteriaSelector).focus();
        },

        /**
         * @inheritDoc
         */
        _hideCriteria: function () {
            ChoiceFilter.prototype._hideCriteria.apply(this, arguments);
        },

        _getSelectedChoiceLabel: function (property, value) {
            var selectedChoiceLabel = '';
            if (!_.isEmpty(this[property])) {
                var foundChoice = _.find(this[property], function (choice) {
                    return (choice.value == value.type);
                });
                selectedChoiceLabel = foundChoice.label;
            }

            return selectedChoiceLabel;
        }
    });
});
<commit_msg>BAP-4988: Broken data selector in Reports&Segment filter<commit_after>/*jslint nomen:true*/
/*global define*/
define(['jquery', 'underscore', 'orotranslation/js/translator', './choice-filter',
        'orolocale/js/locale-settings', '../datevariables-widget'
    ], function ($, _, __, ChoiceFilter, localeSettings) {
    'use strict';

    /**
     * Date filter: filter type as option + interval begin and end dates
     *
     * @export  orofilter/js/filter/date-filter
     * @class   orofilter.filter.DateFilter
     * @extends orofilter.filter.ChoiceFilter
     */
    return ChoiceFilter.extend({
        /**
         * Template selector for filter criteria
         *
         * @property
         */
        templateSelector: '#date-filter-template',

        /**
         * Template selector for date field parts
         *
         * @property
         */
        fieldTemplateSelector: '#select-field-template',

        /**
         * Template selector for dropdown container
         *
         * @property
         */
        dropdownTemplateSelector: '#date-filter-dropdown-template',

        /**
         * Selectors for filter data
         *
         * @property
         */
        criteriaValueSelectors: {
            type: 'select[name!=date_part]',
            part: 'select[name=date_part]',
            value: {
                start: 'input[name="start"]',
                end:   'input[name="end"]'
            }
        },

        /**
         * CSS class for visual date input elements
         *
         * @property
         */
        inputClass: 'date-visual-element',

        /**
         * Date widget options
         *
         * @property
         */
        dateWidgetOptions: {
            changeMonth: true,
            changeYear:  true,
            yearRange:  '-80:+1',
            dateFormat: localeSettings.getVendorDateTimeFormat('jquery_ui', 'date', 'mm/dd/yy'),
            altFormat:  'yy-mm-dd',
            className:      'date-filter-widget',
            showButtonPanel: true
        },

        /**
         * Additional date widget options that might be passed to filter
         * http://api.jqueryui.com/datepicker/
         *
         * @property
         */
        externalWidgetOptions: {},

        /**
         * References to date widgets
         *
         * @property
         */
        dateWidgets: {
            start: null,
            end: null
        },

        /**
         * Date filter type values
         *
         * @property
         */
        typeValues: {
            between:    1,
            notBetween: 2,
            moreThan:   3,
            lessThan:   4
        },

        defaultTabs: [
            {
                name: 'calendar',
                label: 'oro.filter.date.tab.calendar'
            },
            {
                name: 'variables',
                label: 'oro.filter.date.tab.variables'
            }
        ],

        /**
         * Date widget selector
         *
         * @property
         */
        dateWidgetSelector: 'div#ui-datepicker-div.ui-datepicker',

        /**
         * Date parts
         *
         * @property
         */
        dateParts: [],

        hasPartsElement: false,

        /**
         * @inheritDoc
         */
        initialize: function () {
            _.extend(this.dateWidgetOptions, this.externalWidgetOptions);

            //parts rendered only if theme exist
            this.hasPartsElement = (this.templateTheme != "");

            // init empty value object if it was not initialized so far
            if (_.isUndefined(this.emptyValue)) {
                this.emptyValue = {
                    type: (_.isEmpty(this.choices) ? '' : _.first(this.choices).value),
                    part: 'value',
                    value: {
                        start: '',
                        end: ''
                    }
                };
            }

            if (_.isUndefined(this.dateParts)) {
                this.dateParts = [];
            }
            // temp code to keep backward compatible
            if ($.isPlainObject(this.dateParts)) {
                this.dateParts = _.map(this.dateParts, function (option, i) {
                    return {value: i.toString(), label: option};
                });
            }

            if (_.isUndefined(this.emptyPart)) {
                var firstPart = _.first(this.dateParts).value;
                this.emptyPart = {
                    type: (_.isEmpty(this.dateParts) ? '' : firstPart),
                    value: firstPart
                };
            }

            ChoiceFilter.prototype.initialize.apply(this, arguments);
        },

        onChangeFilterType: function (e) {
            var select = this.$el.find(e.currentTarget);
            var selectedValue = select.val() || select.data('value');

            this.changeFilterType(selectedValue);
        },

        changeFilterType: function (type) {
            // filter filter range types
            if (this.dateWidgets.start_vars && type.length > 1) {
                this.$el.find(this.criteriaValueSelectors.value.start).val('');
                this.dateWidgets.start_vars.dateVariables('setPart', type);
            }
            if (this.dateWidgets.end_vars && type.length > 1) {
                this.$el.find(this.criteriaValueSelectors.value.end).val('');
                this.dateWidgets.end_vars.dateVariables('setPart', type);
            }

            type = parseInt(type, 10);

            // check it's valid integer
            if (type === parseInt(type)) {
                this.$el.find('.filter-separator').show().end().find('input').show();
            }

            if (this.typeValues.moreThan === type) {
                this.$el.find('.filter-separator').hide();
                this.$el.find(this.criteriaValueSelectors.value.end).val('').hide();
            } else if (this.typeValues.lessThan === type) {
                this.$el.find('.filter-separator').hide();
                this.$el.find(this.criteriaValueSelectors.value.start).val('').hide();
            }
        },

        /**
         * @inheritDoc
         */
        _renderCriteria: function () {
            var value = _.extend({}, this.emptyValue, this.getValue());
            var part  = {value: value.part, type: value.part};

            var selectedChoiceLabel = this._getSelectedChoiceLabel('choices', value);
            var selectedPartLabel   = this._getSelectedChoiceLabel('dateParts', part);
            this.dateWidgetOptions.part = part.type;

            var datePartTemplate = this._getTemplate(this.fieldTemplateSelector);
            var dropdownTemplate = this._getTemplate(this.dropdownTemplateSelector);
            var parts = [];

            // add date parts only if embed template used
            if (this.templateTheme !== "") {
                parts.push(
                    datePartTemplate({
                        name: this.name + '_part',
                        choices: this.dateParts,
                        selectedChoice: value.part,
                        selectedChoiceLabel: selectedPartLabel
                    })
                );
            }

            parts.push(
                datePartTemplate({
                    name: this.name,
                    choices: this.choices,
                    selectedChoice: value.type,
                    selectedChoiceLabel: selectedChoiceLabel
                })
            );

            var displayValue = this._formatDisplayValue(value);
            var $filter = $(
                this.template({
                    inputClass: this.inputClass,
                    value: displayValue,
                    parts: parts
                })
            );

            this._appendFilter($filter);
            this.$(this.criteriaSelector).attr('tabindex', '0');

            this.changeFilterType(value.type);

            $filter.find('select:first').bind('change', _.bind(this.onChangeFilterType, this));

            _.each(this.criteriaValueSelectors.value, _.bind(this._appendDropdown, this, dropdownTemplate));

            if (!this._isDateVariable(displayValue.value.start)) {
                this.dateWidgets.start.datepicker('setDate', displayValue.value.start);
            }
            if (!this._isDateVariable(displayValue.value.end)) {
                this.dateWidgets.end.datepicker('setDate', displayValue.value.end);
            }

            this.$('.nav-tabs a').click(function (e) {
                e.preventDefault();
                $(this).tab('show');
            });

            this._criteriaRenderd = true;
        },

        /**
         * @param {string} value
         * @returns {boolean}
         * @private
         */
        _isDateVariable: function (value) {
            var dateVars = this.dateWidgetOptions.dateVars;
            for (var i in dateVars.value) {
                if (dateVars.value.hasOwnProperty(i) &&
                    (dateVars.value[i] === value || '{{' + i + '}}' === value)) {
                    return true;
                }
            }

            return false;
        },

        /**
         * @param {function} template
         * @param {string} actualSelector
         * @param {string} name
         * @private
         */
        _appendDropdown: function (template, actualSelector, name) {
            var $calendar, $el = this.$el,
                $input = this.$(actualSelector),
                $dropdown = $input.wrap('<div class="dropdown datefilter">').parent(),
                tabSuffix = '-' + this.cid + '-' + name,
                widgetOptions = _.extend({onSelect: function (date) {
                    $input.val(date).trigger('change');
                }}, this.dateWidgetOptions);

            var tabs = [];
            _.each(widgetOptions.tabs || this.defaultTabs, function(tab) {
                var currentTab   = _.clone(tab);
                currentTab.label = __(currentTab.label);
                tabs.push(currentTab);
            });
            $input.after(template({
                tabs:   tabs,
                suffix: tabSuffix
            }));

            $input.on('focus, click', function () {
                $el.find('.dropdown.open').removeClass('open');
                $dropdown.addClass('open');
                $calendar.datepicker('refresh');
            });

            $calendar = this.dateWidgets[name] = this._initializeDateWidget('#calendar' + tabSuffix, widgetOptions);
            $calendar.addClass(widgetOptions.className)
                .click(function (e) {
                    e.stopImmediatePropagation();
                });

            $calendar.data('datepicker').inline = false;
            $calendar.datepicker('refresh');
            $calendar.on('click', '.ui-datepicker-close', function() {
                $dropdown.removeClass('open');
            });

            widgetOptions = _.extend({
                $input: $input
            }, this.dateWidgetOptions);
            this.dateWidgets[name + '_vars'] = this._initializeDateVariablesWidget('#variables' + tabSuffix, widgetOptions);
        },

        /**
         * Initialize date widget
         *
         * @param {String} widgetSelector
         * @param {Object} options
         * @return {*}
         * @protected
         */
        _initializeDateWidget: function (widgetSelector, options) {
            return this.$(widgetSelector).datepicker(options);
        },

        /**
         * Initialize date variables widget
         *
         * @param {String} widgetSelector
         * @param {Object} options
         * @return {*}
         * @protected
         */
        _initializeDateVariablesWidget: function (widgetSelector, options) {
            this.$(widgetSelector).dateVariables(options);

            var widget = this.$(widgetSelector).dateVariables('widget');
            widget.addClass(options.className);

            return widget;
        },

        /**
         * @inheritDoc
         */
        _getCriteriaHint: function () {
            var hint = '',
                option, start, end, type,
                value = (arguments.length > 0) ? this._getDisplayValue(arguments[0]) : this._getDisplayValue();
            if (value.value) {
                start = value.value.start;
                end   = value.value.end;
                type  = value.type ? value.type.toString() : '';

                switch (type) {
                    case this.typeValues.moreThan.toString():
                        hint += [__('more than'), start].join(' ');
                        break;
                    case this.typeValues.lessThan.toString():
                        hint += [__('less than'), end].join(' ');
                        break;
                    case this.typeValues.notBetween.toString():
                        if (start && end) {
                            option = this._getChoiceOption(this.typeValues.notBetween);
                            hint += [option.label, start, __('and'), end].join(' ');
                        } else if (start) {
                            hint += [__('before'), start].join(' ');
                        } else if (end) {
                            hint += [__('after'), end].join(' ');
                        }
                        break;
                    case this.typeValues.between.toString():
                    default:
                        if (start && end) {
                            option = this._getChoiceOption(this.typeValues.between);
                            hint += [option.label, start, __('and'), end].join(' ');
                        } else if (start) {
                            hint += [__('from'), start].join(' ');
                        } else if (end) {
                            hint += [__('to'), end].join(' ');
                        }
                        break;
                }
                if (hint) {
                    return hint;
                }
            }

            return this.placeholder;
        },

        /**
         * @inheritDoc
         */
        _formatDisplayValue: function (value) {
            var fromFormat = this.dateWidgetOptions.altFormat;
            var toFormat = this.dateWidgetOptions.dateFormat;

            if (value.value && value.value.start) {
                value.value.start = this._replaceDateVars(value.value.start, 'display');
            }
            if (value.value && value.value.end) {
                value.value.end = this._replaceDateVars(value.value.end, 'display');
            }

            return this._formatValueDates(value, fromFormat, toFormat);
        },

        /**
         * @inheritDoc
         */
        _formatRawValue: function (value) {
            var fromFormat = this.dateWidgetOptions.dateFormat;
            var toFormat = this.dateWidgetOptions.altFormat;

            if (value.value && value.value.start) {
                value.value.start = this._replaceDateVars(value.value.start, 'raw');
            }
            if (value.value && value.value.end) {
                value.value.end = this._replaceDateVars(value.value.end, 'raw');
            }

            return this._formatValueDates(value, fromFormat, toFormat);
        },

        /**
         * Format dates in a vault to another format
         *
         * @param {Object} value
         * @param {String} fromFormat
         * @param {String} toFormat
         * @return {Object}
         * @protected
         */
        _formatValueDates: function (value, fromFormat, toFormat) {
            if (value.value && value.value.start) {
                value.value.start = this._formatDate(value.value.start, fromFormat, toFormat);
            }
            if (value.value && value.value.end) {
                value.value.end = this._formatDate(value.value.end, fromFormat, toFormat);
            }
            return value;
        },

        _replaceDateVars: function (value, mode) {
            // replace date variables with constant values
            var dateVars = this.dateWidgetOptions.dateVars;

            if (mode == 'raw') {
                for (var part in dateVars) {
                    if (dateVars.hasOwnProperty(part)) {
                        for (var varCode in dateVars[part]) {
                            if (dateVars[part].hasOwnProperty(varCode)) {
                                value = value.replace(new RegExp(dateVars[part][varCode], 'g'), '{{' + varCode+'}}');
                            }
                        }
                    }
                }
            } else {
                for (var part in dateVars) {
                    if (dateVars.hasOwnProperty(part)) {
                        for (var varCode in dateVars[part]) {
                            if (dateVars[part].hasOwnProperty(varCode)) {
                                value = value.replace(new RegExp('\{+' + varCode + '\}+', 'gi'), dateVars[part][varCode]);
                            }
                        }
                    }
                }
            }

            return value;
        },

        /**
         * Formats date string to another format
         *
         * @param {String} value
         * @param {String} fromFormat
         * @param {String} toFormat
         * @return {String}
         * @protected
         */
        _formatDate: function (value, fromFormat, toFormat) {
            var fromValue;
            if (this._isDateVariable(value)) {
                return value;
            }
            fromValue = $.datepicker.parseDate(fromFormat, value);
            if (!fromValue) {
                fromValue = $.datepicker.parseDate(toFormat, value);
                if (!fromValue) {
                    return '';
                }
            }
            return $.datepicker.formatDate(toFormat, fromValue);
        },

        /**
         * @inheritDoc
         */
        _writeDOMValue: function (value) {
            this._setInputValue(this.criteriaValueSelectors.value.start, value.value.start);
            this._setInputValue(this.criteriaValueSelectors.value.end, value.value.end);
            this._setInputValue(this.criteriaValueSelectors.type, value.type);
            if (value.part) {
                this._setInputValue(this.criteriaValueSelectors.part, value.part);
            }
            return this;
        },

        /**
         * @inheritDoc
         */
        _readDOMValue: function () {
            return {
                type: this._getInputValue(this.criteriaValueSelectors.type),
                //empty default parts value if parts not exist
                part: this.hasPartsElement ? this._getInputValue(this.criteriaValueSelectors.part) : 'value',
                value: {
                    start: this._getInputValue(this.criteriaValueSelectors.value.start),
                    end:   this._getInputValue(this.criteriaValueSelectors.value.end)
                }
            };
        },

        /**
         * @inheritDoc
         */
        _focusCriteria: function () {
            this.$(this.criteriaSelector).focus();
        },

        /**
         * @inheritDoc
         */
        _hideCriteria: function () {
            ChoiceFilter.prototype._hideCriteria.apply(this, arguments);
        },

        _getSelectedChoiceLabel: function (property, value) {
            var selectedChoiceLabel = '';
            if (!_.isEmpty(this[property])) {
                var foundChoice = _.find(this[property], function (choice) {
                    return (choice.value == value.type);
                });
                selectedChoiceLabel = foundChoice.label;
            }

            return selectedChoiceLabel;
        }
    });
});
<|endoftext|>


<commit_before>const Command = require("../base/Command");

class Versus extends Command {
    constructor(Bot) {
        super(Bot, {
            name: "versus",
            category: "SWGoH",
            enabled: true,
            aliases: ["vs"],
            permissions: ["EMBED_LINKS"],
            subArgs: {}
        });
    }

    async run(Bot, message, [user1str, user2str, ...character], options) { // eslint-disable-line no-unused-vars
        const statList = [
            {stat: "Health",                   short: "Health"},
            {stat: "Protection",               short: "Prot"  },
            {stat: "Speed",                    short: "Speed" },
            {stat: "Armor",                    short: "Armor" },
            {stat: "Physical Damage",          short: "P Dmg" },
            {stat: "Physical Critical Chance", short: "P Crit"},
            {stat: "Special Damage",           short: "S Dmg" },
            {stat: "Special Critical Chance",  short: "S Crit"},
            {stat: "Critical Damage",          short: "Crit D"},
            {stat: "Potency",                  short: "Pot"   },
            {stat: "Tenacity",                 short: "Ten"   }
        ];
        /*
         * If user1str AND user2str are both valid users, use both
         *
         * If only user2str is valid, spit out an error
         *
         * If only user1str is valid, set it up for user2 and grab the primary code if available
         *  -- If there is no valid primary/ linked allycode for author, spit out an error
         *  -- In this case, tack whatever user2str is onto the beginning of the character array
         *
         * Once both users are validated in some way, check against the character, get a valid baseId and go from there.
         *  -- If character is invalid, spit out an error
         */

        // If it can't find a valid character, but can find a ship, set this to true so it knows how to format the data later
        // let ship = false;

        const msg = await message.channel.send("Please wait while I process your data.");

        let user1 = await super.getUser(message, user1str, false);
        let user2 = await super.getUser(message, user2str, false);

        if (user1 && user2) {
            // Everyting is fine, they entered 2 valid users
            if (character.length) {
                character = character.join(" ");
            } else {
                // Spit out an error because of no character
                // TODO return error here
            }
        } else if (user1) {
            // Just user1 is valid, grab author's linked code and attach user2str to character
            user2 = user1;
            user1 = await super.getUser(message, message.author.id, false);
            if (!user1) {
                // Spit out an error because the message author is not registered
                // TODO return error here
            }
            character = [user2str].concat(character).join(" ");
        } else if (user2) {
            // Something went wrong with user1, let's spit out an error
            // TODO return error here
        } else {
            // Something really went wrong, and neither user is valid. Spit out a bigger error
            // TODO return error here
        }

        // If it got this far, it has 2 users and a character that needs checking.
        let char = Bot.findChar(character, Bot.characters);
        if (!char.length) {
            char = Bot.findChar(character, Bot.ships, true);
            // ship = true;
        }
        if (!char.length) {
            //TODO return super.error(message, message.language.get("COMMAND_GRANDARENA_INVALID_CHAR", character));
        } else if (char.length > 1) {
            // If found more than 1 match
            // TODO return error here about more than 1 match
        } else {
            // It only found one match
            if (Array.isArray(char)) char = char[0];
        }

        const cooldown = await Bot.getPlayerCooldown(message.author.id);
        try {
            user1 = await Bot.swgohAPI.unitStats(user1, cooldown);
            if (Array.isArray(user1)) user1 = user1[0];
        } catch (e) {
            return super.error(message, "Something broke when getting user 1");
        }
        try {
            user2 = await Bot.swgohAPI.unitStats(user2, cooldown);
            if (Array.isArray(user2)) user2 = user2[0];
        } catch (e) {
            return super.error(message, "Something broke when getting user 2");
        }
        const errArr = [];
        if (!user1?.roster?.length) {
            errArr.push("User 1 is missing pieces, please try again later.");
        }
        if (!user2?.roster?.length) {
            errArr.push("User 2 is missing pieces, please try again later.");
        }
        if (errArr.length) {
            return super.error(message, errArr.join("\n"));
        }

        // From here, we should have both user's rosters, so grab the characters and make the table
        const char1 = user1.roster.find(c => c.defId === char.uniqueName);
        const char2 = user2.roster.find(c => c.defId === char.uniqueName);

        if (!char1 && !char2) {
            return super.error(message, "Neither user seems to have that character unlocked!") ;
        }

        const isShip = (char1 ? char1.combatType : char2.combatType) === 1 ? false : true;

        const genOut = [];

        // Stick the level in
        genOut.push({
            stat: "Lvl",
            user1: char1?.level,
            user2: char2?.level
        });

        // Add in the Star level / rarity
        genOut.push({
            stat: "Rarity",
            user1: char1?.rarity,
            user2: char2?.rarity
        });

        if (!isShip) {
            // Add in the zeta count
            const user1Zetas = char1?.skills.filter(sk => sk.isZeta && sk.tiers === sk.tier).length;
            const user2Zetas = char2?.skills.filter(sk => sk.isZeta && sk.tiers === sk.tier).length;
            if (user1Zetas || user2Zetas) {
                genOut.push({
                    stat: "Zetas",
                    user1: user1Zetas,
                    user2: user2Zetas
                });
            }

            // Add in the gear level
            genOut.push({
                stat: "Gear",
                user1: char1?.gear,
                user2: char2?.gear
            });

            const user1Relic = char1?.relic?.currentTier - 2;
            const user2Relic = char2?.relic?.currentTier - 2;
            if (user1Relic || user2Relic) {
                genOut.push({
                    stat: "Relic",
                    user1: user1Relic,
                    user2: user2Relic
                });
            }
        }

        const generalTable = Bot.makeTable({
            stat:  {value: "Stat", align: "right", endWith: "::"},
            user1: {value: user1.name, align: "right", endWith: "vs"},
            user2: {value: user2.name, align: "left"}
        }, genOut, {boldHeader: false, useHeader: false});

        // For each stat in a list, add onto the statOut array
        const statOut = [];
        statList.forEach(stat => {
            const s1 = char1?.stats?.final[stat.stat];
            const s2 = char2?.stats?.final[stat.stat];
            statOut.push({
                stat: stat.short,
                user1: s1 ? (s1 % 1 === 0 ? s1.toLocaleString() : (s1 * 100).toFixed(2)+"%") : "N/A",
                user2: s2 ? (s2 % 1 === 0 ? s2.toLocaleString() : (s2 * 100).toFixed(2)+"%") : "N/A",
            });
        });

        const langChar = await Bot.swgohAPI.langChar({defId: char1.defId});
        const charName = langChar.nameKey;
        const statTable = Bot.makeTable({
            stat:  {value: "Stat", align: "right", endWith: "::"},
            user1: {value: user1.name, align: "right", endWith: "vs"},
            user2: {value: user2.name, align: "left"}
        }, statOut, {boldHeader: false, useHeader: false});

        const footer = Bot.updatedFooter(Math.min(user1.updated, user2.updated), message, "player", cooldown);
        return msg.edit("", {embed: {
            title: `${user1.name} vs. ${user2.name} (${charName})`,
            fields: [
                {
                    name: "General Info",
                    value: Bot.codeBlock(generalTable.join("\n"), "asciidoc")
                },
                {
                    name: "Stats",
                    value: Bot.codeBlock(statTable.join("\n"), "asciidoc")
                }
            ],
            footer: footer
        }});
    }
}

module.exports = Versus;

<commit_msg>Quick fix for vs<commit_after>const Command = require("../base/Command");

class Versus extends Command {
    constructor(Bot) {
        super(Bot, {
            name: "versus",
            category: "SWGoH",
            enabled: true,
            aliases: ["vs"],
            permissions: ["EMBED_LINKS"],
            subArgs: {}
        });
    }

    async run(Bot, message, [user1str, user2str, ...character], options) { // eslint-disable-line no-unused-vars
        const statList = [
            {stat: "Health",                   short: "Health"},
            {stat: "Protection",               short: "Prot"  },
            {stat: "Speed",                    short: "Speed" },
            {stat: "Armor",                    short: "Armor" },
            {stat: "Physical Damage",          short: "P Dmg" },
            {stat: "Physical Critical Chance", short: "P Crit"},
            {stat: "Special Damage",           short: "S Dmg" },
            {stat: "Special Critical Chance",  short: "S Crit"},
            {stat: "Critical Damage",          short: "Crit D"},
            {stat: "Potency",                  short: "Pot"   },
            {stat: "Tenacity",                 short: "Ten"   }
        ];
        /*
         * If user1str AND user2str are both valid users, use both
         *
         * If only user2str is valid, spit out an error
         *
         * If only user1str is valid, set it up for user2 and grab the primary code if available
         *  -- If there is no valid primary/ linked allycode for author, spit out an error
         *  -- In this case, tack whatever user2str is onto the beginning of the character array
         *
         * Once both users are validated in some way, check against the character, get a valid baseId and go from there.
         *  -- If character is invalid, spit out an error
         */

        // If it can't find a valid character, but can find a ship, set this to true so it knows how to format the data later
        // let ship = false;

        const msg = await message.channel.send("Please wait while I process your data.");

        let user1 = await super.getUser(message, user1str, false);
        let user2 = await super.getUser(message, user2str, false);

        if (user1 && user2) {
            // Everyting is fine, they entered 2 valid users
            if (character.length) {
                character = character.join(" ");
            } else {
                // Spit out an error because of no character
                // TODO return error here
            }
        } else if (user1) {
            // Just user1 is valid, grab author's linked code and attach user2str to character
            user2 = user1;
            user1 = await super.getUser(message, message.author.id, false);
            if (!user1) {
                // Spit out an error because the message author is not registered
                // TODO return error here
            }
            character = [user2str].concat(character).join(" ");
        } else if (user2) {
            // Something went wrong with user1, let's spit out an error
            // TODO return error here
        } else {
            // Something really went wrong, and neither user is valid. Spit out a bigger error
            // TODO return error here
        }

        // If it got this far, it has 2 users and a character that needs checking.
        let char = Bot.findChar(character, Bot.characters);
        if (!char.length) {
            char = Bot.findChar(character, Bot.ships, true);
            // ship = true;
        }
        if (!char.length) {
            //TODO return super.error(message, message.language.get("COMMAND_GRANDARENA_INVALID_CHAR", character));
        } else if (char.length > 1) {
            // If found more than 1 match
            // TODO return error here about more than 1 match
        } else {
            // It only found one match
            if (Array.isArray(char)) char = char[0];
        }

        const cooldown = await Bot.getPlayerCooldown(message.author.id);
        try {
            user1 = await Bot.swgohAPI.unitStats(user1, cooldown);
            if (Array.isArray(user1)) user1 = user1[0];
        } catch (e) {
            return super.error(message, "Something broke when getting user 1");
        }
        try {
            user2 = await Bot.swgohAPI.unitStats(user2, cooldown);
            if (Array.isArray(user2)) user2 = user2[0];
        } catch (e) {
            return super.error(message, "Something broke when getting user 2");
        }
        const errArr = [];
        if (!user1?.roster?.length) {
            errArr.push("User 1 is missing pieces, please try again later.");
        }
        if (!user2?.roster?.length) {
            errArr.push("User 2 is missing pieces, please try again later.");
        }
        if (errArr.length) {
            return super.error(message, errArr.join("\n"));
        }

        // From here, we should have both user's rosters, so grab the characters and make the table
        const char1 = user1.roster.find(c => c.defId === char.uniqueName);
        const char2 = user2.roster.find(c => c.defId === char.uniqueName);

        if (!char1 && !char2) {
            return super.error(message, "Neither user seems to have that character unlocked!") ;
        }

        const isShip = (char1 ? char1.combatType : char2.combatType) === 1 ? false : true;

        const genOut = [];

        // Stick the level in
        genOut.push({
            stat: "Lvl",
            user1: char1?.level,
            user2: char2?.level
        });

        // Add in the Star level / rarity
        genOut.push({
            stat: "Rarity",
            user1: char1?.rarity,
            user2: char2?.rarity
        });

        if (!isShip) {
            // Add in the zeta count
            const user1Zetas = char1?.skills.filter(sk => sk.isZeta && sk.tiers === sk.tier).length;
            const user2Zetas = char2?.skills.filter(sk => sk.isZeta && sk.tiers === sk.tier).length;
            if (user1Zetas || user2Zetas) {
                genOut.push({
                    stat: "Zetas",
                    user1: user1Zetas,
                    user2: user2Zetas
                });
            }

            // Add in the gear level
            genOut.push({
                stat: "Gear",
                user1: char1?.gear,
                user2: char2?.gear
            });

            const user1Relic = char1?.relic?.currentTier - 2;
            const user2Relic = char2?.relic?.currentTier - 2;
            if (user1Relic || user2Relic) {
                genOut.push({
                    stat: "Relic",
                    user1: user1Relic,
                    user2: user2Relic
                });
            }
        }

        const generalTable = Bot.makeTable({
            stat:  {value: "Stat", align: "right", endWith: "::"},
            user1: {value: user1.name, align: "right", endWith: "vs"},
            user2: {value: user2.name, align: "left"}
        }, genOut, {boldHeader: false, useHeader: false});

        // For each stat in a list, add onto the statOut array
        const statOut = [];
        statList.forEach(stat => {
            const s1 = char1?.stats?.final[stat.stat];
            const s2 = char2?.stats?.final[stat.stat];
            statOut.push({
                stat: stat.short,
                user1: s1 ? (s1 % 1 === 0 ? s1.toLocaleString() : (s1 * 100).toFixed(2)+"%") : "N/A",
                user2: s2 ? (s2 % 1 === 0 ? s2.toLocaleString() : (s2 * 100).toFixed(2)+"%") : "N/A",
            });
        });

        const langChar = await Bot.swgohAPI.langChar({defId: char1 ? char1.defId : char2.defId});
        const charName = langChar.nameKey;
        const statTable = Bot.makeTable({
            stat:  {value: "Stat", align: "right", endWith: "::"},
            user1: {value: user1.name, align: "right", endWith: "vs"},
            user2: {value: user2.name, align: "left"}
        }, statOut, {boldHeader: false, useHeader: false});

        const footer = Bot.updatedFooter(Math.min(user1.updated, user2.updated), message, "player", cooldown);
        return msg.edit("", {embed: {
            title: `${user1.name} vs. ${user2.name} (${charName})`,
            fields: [
                {
                    name: "General Info",
                    value: Bot.codeBlock(generalTable.join("\n"), "asciidoc")
                },
                {
                    name: "Stats",
                    value: Bot.codeBlock(statTable.join("\n"), "asciidoc")
                }
            ],
            footer: footer
        }});
    }
}

module.exports = Versus;

<|endoftext|>


<commit_before>'use strict';

var sammuiForm = angular.module('sammui.form', [
    'sammui.formServices',
    'sammui.formControllers',
    'sammui.protocolServices',
    'sammui.protocolControllers',
    'sammui.formDirectives'
]);

sammuiForm.config(function ($locationProvider, $routeProvider) {
    $routeProvider.when('/form', {
        templateUrl: '/bundles/form/angular/views/form/start.html',
        templatePreload: true,
        controller: 'formStart',
        reloadOnSearch: false
    });
    $routeProvider.when('/form/:protocolId', {
        templateUrl: '/bundles/form/angular/views/form/filling/home.html',
        templatePreload: false,
        controller: 'formFilling',
        reloadOnSearch: false
    });
    $routeProvider.when('/form/:protocolId/page/:pageId', {
        templateUrl: '/bundles/form/angular/views/form/filling/home.html',
        templatePreload: false,
        controller: 'formFilling',
        reloadOnSearch: false
    });
});<commit_msg>Angular: Simplifying form protocol routes<commit_after>'use strict';

var sammuiForm = angular.module('sammui.form', [
    'sammui.formServices',
    'sammui.formControllers',
    'sammui.formDirectives',
    'sammui.protocolServices',
    'sammui.protocolControllers'
]);

sammuiForm.config(function ($locationProvider, $routeProvider) {
    $routeProvider.when('/form', {
        templateUrl: '/bundles/form/angular/views/form/start.html',
        templatePreload: true,
        controller: 'formStart',
        reloadOnSearch: false
    });
    $routeProvider.when('/form/:protocolId/:page?/:pageId?', {
        templateUrl: '/bundles/form/angular/views/form/filling/home.html',
        templatePreload: false,
        controller: 'formFilling',
        reloadOnSearch: false
    });
});<|endoftext|>


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

/**
 * @fileoverview Dygraphs options palette text area.
 *
 * @author konigsberg@google.com (Robert Konigsberg)
 */
"use strict";

function TextArea(parent) {
  var body = document.getElementsByTagName("body")[0];
  if (!parent) {
    parent = body;
  }
  this.elem = TextArea.createChild("div", parent, "textarea");
  this.title = TextArea.createChild("div", this.elem, "title");
  this.textarea = TextArea.createChild("textarea", this.elem, "editor");
  this.buttons = TextArea.createChild("div", this.elem, "buttons");
  this.ok = TextArea.createChild("button", this.buttons);
  this.ok.textContent = "OK";
  this.cancel = TextArea.createChild("button", this.buttons);
  this.cancel.textContent = "Cancel";
  this.height = 315;
  this.width = 445;

  var textarea = this;
  this.ok.onclick = function() {
    textarea.hide();
    textarea.okCallback(textarea.textarea.value);
  };
  this.cancel.onclick = function() {
    textarea.hide();
    textarea.cancelCallback();
  };
  this.reposition = function() {
    var left = (document.documentElement.clientWidth - textarea.elem.offsetWidth) / 2;
    var top = (document.documentElement.clientHeight - textarea.elem.offsetHeight) / 2;
    textarea.elem.style.left = Math.max(left, 0) + "px";
    textarea.elem.style.top = Math.max(top, 0) + "px";
  }

  this.background = TextArea.createChild("div", body, "background");
  this.background.id = "modalBackground";
  this.hide();
}

/* I think this is the third place I've copied this function */
TextArea.createChild = function(type, parent, className) {
  var elem = document.createElement(type);
  parent.appendChild(elem);
  if (className) {
    elem.className = className;
  }
  return elem;
};

TextArea.prototype.cancelCallback = function() {
};

TextArea.prototype.okCallback = function(content) {
};

TextArea.prototype.show = function(title, content) {
  this.title.textContent = title;
  this.textarea.value = content;

  var sums = function(adds, subtracts, field) {
    var total = 0;
    for (var idx in adds) {
      total += parseInt(adds[idx][field]);
    }
    for (var idx2 in subtracts) {
      total -= parseInt(subtracts[idx2][field]);
    }
    return total;
  }
  this.elem.style.display = "block";
  this.background.style.display = "block";

  this.elem.style.height = this.height + "px";
  this.elem.style.width = this.width + "px";

  this.textarea.style.height = (-18 + sums([this.elem], [this.title, this.buttons], "offsetHeight")) + "px";
  this.textarea.style.width = (-16 + sums([this.elem], [ ], "offsetWidth")) + "px";

  var textarea = this;

  this.keyDownListener_ = function(event) {
    // console.log(event);
    if(event.keyCode == 13) { // enter / return
      textarea.hide();
    }
    if(event.keyCode == 27) { // esc
      textarea.hide();
    }
  }

  Dygraph.addEvent(document, "keydown", this.keyDownListener_);
  this.reposition();
  window.addEventListener('resize', this.reposition, false);
  document.documentElement.addEventListener('onscroll', this.reposition);
}

TextArea.prototype.hide = function() {
  Dygraph.removeEvent(document, "keypress", this.keyDownListener_);
  this.keyDownListener_ = null;
  this.elem.style.display = "none";
  this.background.style.display = "none";
  window.removeEventListener("resize", this.reposition);
  document.documentElement.removeEventListener("onscroll", this.reposition);
}
<commit_msg>Remove commented-out console.log.<commit_after>// Copyright (c) 2012 Google, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

/**
 * @fileoverview Dygraphs options palette text area.
 *
 * @author konigsberg@google.com (Robert Konigsberg)
 */
"use strict";

function TextArea(parent) {
  var body = document.getElementsByTagName("body")[0];
  if (!parent) {
    parent = body;
  }
  this.elem = TextArea.createChild("div", parent, "textarea");
  this.title = TextArea.createChild("div", this.elem, "title");
  this.textarea = TextArea.createChild("textarea", this.elem, "editor");
  this.buttons = TextArea.createChild("div", this.elem, "buttons");
  this.ok = TextArea.createChild("button", this.buttons);
  this.ok.textContent = "OK";
  this.cancel = TextArea.createChild("button", this.buttons);
  this.cancel.textContent = "Cancel";
  this.height = 315;
  this.width = 445;

  var textarea = this;
  this.ok.onclick = function() {
    textarea.hide();
    textarea.okCallback(textarea.textarea.value);
  };
  this.cancel.onclick = function() {
    textarea.hide();
    textarea.cancelCallback();
  };
  this.reposition = function() {
    var left = (document.documentElement.clientWidth - textarea.elem.offsetWidth) / 2;
    var top = (document.documentElement.clientHeight - textarea.elem.offsetHeight) / 2;
    textarea.elem.style.left = Math.max(left, 0) + "px";
    textarea.elem.style.top = Math.max(top, 0) + "px";
  }

  this.background = TextArea.createChild("div", body, "background");
  this.background.id = "modalBackground";
  this.hide();
}

/* I think this is the third place I've copied this function */
TextArea.createChild = function(type, parent, className) {
  var elem = document.createElement(type);
  parent.appendChild(elem);
  if (className) {
    elem.className = className;
  }
  return elem;
};

TextArea.prototype.cancelCallback = function() {
};

TextArea.prototype.okCallback = function(content) {
};

TextArea.prototype.show = function(title, content) {
  this.title.textContent = title;
  this.textarea.value = content;

  var sums = function(adds, subtracts, field) {
    var total = 0;
    for (var idx in adds) {
      total += parseInt(adds[idx][field]);
    }
    for (var idx2 in subtracts) {
      total -= parseInt(subtracts[idx2][field]);
    }
    return total;
  }
  this.elem.style.display = "block";
  this.background.style.display = "block";

  this.elem.style.height = this.height + "px";
  this.elem.style.width = this.width + "px";

  this.textarea.style.height = (-18 + sums([this.elem], [this.title, this.buttons], "offsetHeight")) + "px";
  this.textarea.style.width = (-16 + sums([this.elem], [ ], "offsetWidth")) + "px";

  var textarea = this;

  this.keyDownListener_ = function(event) {
    if(event.keyCode == 13) { // enter / return
      textarea.hide();
    }
    if(event.keyCode == 27) { // esc
      textarea.hide();
    }
  }

  Dygraph.addEvent(document, "keydown", this.keyDownListener_);
  this.reposition();
  window.addEventListener('resize', this.reposition, false);
  document.documentElement.addEventListener('onscroll', this.reposition);
}

TextArea.prototype.hide = function() {
  Dygraph.removeEvent(document, "keypress", this.keyDownListener_);
  this.keyDownListener_ = null;
  this.elem.style.display = "none";
  this.background.style.display = "none";
  window.removeEventListener("resize", this.reposition);
  document.documentElement.removeEventListener("onscroll", this.reposition);
}
<|endoftext|>