<commit_before>"use strict";
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import ReactDOM from 'react-dom';
import DocumentTitle from 'react-document-title';
import { Authenticated } from 'react-stormpath';
import { Col, Image, Panel, Grid, Row, Button, Form, Schema, Property, Component } from 'react-bootstrap';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';

//import { images } from 'js/img';

var EvtTier1
var EvtTier2
var EvtTier3
var EvtTeam
var dbuser

var getTier1 = fetch(`/eventers/` + 1)
  .then(function (response) {
    return response.json();
  }).then(function (json) {
    EvtTier1 = json;
    return { options: json };
  }).catch(function (ex) {

  })

var getTier2 = fetch(`/eventers/` + 2)
  .then(function (response) {
    return response.json();
  }).then(function (json) {
    EvtTier2 = json;
    return { options: json };
  }).catch(function (ex) {
  })

var getTier3 = fetch(`/eventers/` + 3)
  .then(function (response) {
    return response.json();
  }).then(function (json) {
    EvtTier3 = json;
    return { options: json };
  }).catch(function (ex) {
  })

//Table stuff

function asMyQuote(input) {
  return '\'' + input + '\'';
}

function imageFormatter(cell, row) {
  var celly = asMyQuote(cell);
  //console.log("IMAGEFORMATTER CELLy::",celly);
  return ;
}

export default class EventerPage extends React.Component {
  static contextTypes = {
    user: React.PropTypes.object
  };
  constructor(props) {
    super(props);
    console.log("REACT::EVENTERPAGE::PROPS::",this.props);
    this.state = { selected: [], value: '', dbuser: {} };
    // this.state = { value: '' };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);

    this.options = {
      defaultSortName: 'ridername',  // default sort column name
      defaultSortOrder: 'desc'  // default sort order
    };
  }

      // componentWillMount() { }

   componentDidMount() {

  }

  handleChange(event) {
    this.setState({ value: event.target.value });
  }

  handleSubmit(event, propid) {
    //alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
    console.log('REACT::EVENTERTEAM::HANDLESUBMIT::SELECTEDTEAM', JSON.stringify(this.state.selected));
    console.log('REACT::EVENTERTEAM::HANDLESUBMIT::PROPID', JSON.stringify(propid));

    fetch(`/eventerteam/`,{
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        id: propid,
        teamName: this.state.value,
        team: this.state.selected,
      })
    })
  }

    handleRowSelect = (row, isSelected, e) => {
      if (isSelected) {
        console.log("MYROW::", row);
        console.log("MYSTATEROW1::", this.state.selected)
        this.setState({ selected: this.state.selected.concat([row]) }, () => {
          console.log("MYSTATEROW2::", this.state.selected[0].ridername);
        });
      } else {
        this.setState({ selected: this.state.selected.filter(it => it !== row) });
      }
    }

    render() {

      var selectRowProp = {
        mode: 'checkbox',
        bgColor: '#dcf442', // you should give a bgcolor, otherwise, you can't regonize which row has been selected
        hideSelectColumn: true,  // enable hide selection column.
        clickToSelect: true,  // you should enable clickToSelect, otherwise, you can't select column.
        onSelect: this.handleRowSelect.bind(this)
      };

      return (

Welcome Fantasy Eventers

Here's the basics:

Riders are posted as final 48 hrs before the start of the next great event.

You will able to select one scratch replacement in case you select a horse and rider pair that scratch before the event.

Select a total of 8 riders from the list below plus one scratch replacement.

All teams lock once the first rider enters the dressage arena.

Once you've picked you team, go create your own league, invite your friends or join and existing league.

User Prop ID:: {this.props.id}

          <Grid>
            <Row>

{this.state.selected.map((selected, index) => (
                <Col sm={2} md={2} key={index}>{selected.ridername}
{selected.horsename}
</Col>
              ))}

            </Row>

            <Row>

{this.state.value}

              <form onSubmit={() => this.handleSubmit(this.props.id)}>

                  Enter Team Name
                <input type="text" value={this.state.value} onChange={this.handleChange} />

                   <input type="submit" value="Submit" className="btn btn-warning" />
              </form>
            </Row>
          </Grid>

Tier 1 Eventers

Pick 2

          <BootstrapTable data={EvtTier1} hover selectRow={selectRowProp} bodyStyle={{ background: '#f4a442' }} ref='table1'>
            <TableHeaderColumn isKey dataField='pk_id_competitor' hidden>compId</TableHeaderColumn>
            <TableHeaderColumn dataField='pic' dataFormat={imageFormatter}>pic</TableHeaderColumn>
            <TableHeaderColumn dataField='ridername' dataSort>Ridername</TableHeaderColumn>
            <TableHeaderColumn dataField='horsename' dataSort>Horsename</TableHeaderColumn>
            <TableHeaderColumn dataField='eventtier'>EventTier</TableHeaderColumn>
          </BootstrapTable>

Tier 2 Eventers

Pick 4

          <BootstrapTable data={EvtTier2} hover selectRow={selectRowProp} bodyStyle={{ background: '#f4a442' }} ref='table2'>
            <TableHeaderColumn isKey dataField='pk_id_competitor' hidden>compId</TableHeaderColumn>
            <TableHeaderColumn dataField='pic' dataFormat={imageFormatter}>pic</TableHeaderColumn>
            <TableHeaderColumn dataField='ridername' dataSort>Ridername</TableHeaderColumn>
            <TableHeaderColumn dataField='horsename' dataSort>Horsename</TableHeaderColumn>
            <TableHeaderColumn dataField='eventtier'>EventTier</TableHeaderColumn>
          </BootstrapTable>

Tier 3 Eventers

Pick 2

          <BootstrapTable data={EvtTier3} hover selectRow={selectRowProp} bodyStyle={{ background: '#f4a442' }} ref='table3'>
            <TableHeaderColumn isKey dataField='pk_id_competitor' hidden>compId</TableHeaderColumn>
            <TableHeaderColumn dataField='pic' dataFormat={imageFormatter}>pic</TableHeaderColumn>
            <TableHeaderColumn dataField='ridername' dataSort>Ridername</TableHeaderColumn>
            <TableHeaderColumn dataField='horsename' dataSort>Horsename</TableHeaderColumn>
            <TableHeaderColumn dataField='eventtier'>EventTier</TableHeaderColumn>
          </BootstrapTable>

      );

    }

  }

<commit_msg>cleanup<commit_after>"use strict";
import React, { PropTypes } from 'react';
import { Link } from 'react-router';
import ReactDOM from 'react-dom';
import DocumentTitle from 'react-document-title';
import { Authenticated } from 'react-stormpath';
import { Col, Image, Panel, Grid, Row, Button, Form, Schema, Property, Component } from 'react-bootstrap';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';

//import { images } from 'js/img';

var EvtTier1
var EvtTier2
var EvtTier3
var EvtTeam
var dbuser

var getTier1 = fetch(`/eventers/` + 1)
  .then(function (response) {
    return response.json();
  }).then(function (json) {
    EvtTier1 = json;
    return { options: json };
  }).catch(function (ex) {

  })

var getTier2 = fetch(`/eventers/` + 2)
  .then(function (response) {
    return response.json();
  }).then(function (json) {
    EvtTier2 = json;
    return { options: json };
  }).catch(function (ex) {
  })

var getTier3 = fetch(`/eventers/` + 3)
  .then(function (response) {
    return response.json();
  }).then(function (json) {
    EvtTier3 = json;
    return { options: json };
  }).catch(function (ex) {
  })

//Table stuff

function asMyQuote(input) {
  return '\'' + input + '\'';
}

function imageFormatter(cell, row) {
  var celly = asMyQuote(cell);
  //console.log("IMAGEFORMATTER CELLy::",celly);
  return ;
}

export default class EventerPage extends React.Component {
  static contextTypes = {
    user: React.PropTypes.object
  };
  constructor(props) {
    super(props);
    console.log("REACT::EVENTERPAGE::PROPS::",this.props);
    this.state = { selected: [], value: '', dbuser: {} };
    // this.state = { value: '' };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);

    this.options = {
      defaultSortName: 'ridername',  // default sort column name
      defaultSortOrder: 'desc'  // default sort order
    };
  }

      // componentWillMount() { }

   componentDidMount() {

  }

  handleChange(event) {
    this.setState({ value: event.target.value });
  }

  handleSubmit(event, propid) {
    //alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
    console.log('REACT::EVENTERTEAM::HANDLESUBMIT::SELECTEDTEAM', JSON.stringify(this.state.selected));
    console.log('REACT::EVENTERTEAM::HANDLESUBMIT::PROPID', JSON.stringify(propid));

    fetch(`/eventerteam/`,{
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        id: propid,
        teamName: this.state.value,
        team: this.state.selected,
      })
    })
  }

    handleRowSelect = (row, isSelected, e) => {
      if (isSelected) {
        console.log("MYROW::", row);
        console.log("MYSTATEROW1::", this.state.selected)
        this.setState({ selected: this.state.selected.concat([row]) }, () => {
          console.log("MYSTATEROW2::", this.state.selected[0].ridername);
        });
      } else {
        this.setState({ selected: this.state.selected.filter(it => it !== row) });
      }
    }

    render() {

      var selectRowProp = {
        mode: 'checkbox',
        bgColor: '#dcf442', // you should give a bgcolor, otherwise, you can't regonize which row has been selected
        hideSelectColumn: true,  // enable hide selection column.
        clickToSelect: true,  // you should enable clickToSelect, otherwise, you can't select column.
        onSelect: this.handleRowSelect.bind(this)
      };

      return (

Welcome Fantasy Eventers

Here's the basics:

User Prop ID:: {this.props.id}

          <Grid>
            <Row>

{this.state.selected.map((selected, index) => (
                <Col sm={2} md={2} key={index}>{selected.ridername}
{selected.horsename}
</Col>
              ))}

            </Row>

            <Row>

{this.state.value}

              <form onSubmit={() => this.handleSubmit(this.props.id)}>

                  Enter Team Name
                <input type="text" value={this.state.value} onChange={this.handleChange} />

                   <input type="submit" value="Submit" className="btn btn-warning" />
              </form>
            </Row>
          </Grid>

Tier 1 Eventers

Pick 2

          <BootstrapTable data={EvtTier1} hover selectRow={selectRowProp} bodyStyle={{ background: '#f4a442' }} ref='table1'>
            <TableHeaderColumn isKey dataField='pk_id_competitor' hidden>compId</TableHeaderColumn>
            <TableHeaderColumn dataField='pic' dataFormat={imageFormatter}>pic</TableHeaderColumn>
            <TableHeaderColumn dataField='ridername' dataSort>Ridername</TableHeaderColumn>
            <TableHeaderColumn dataField='horsename' dataSort>Horsename</TableHeaderColumn>
            <TableHeaderColumn dataField='eventtier'>EventTier</TableHeaderColumn>
          </BootstrapTable>

Tier 2 Eventers

Pick 4

          <BootstrapTable data={EvtTier2} hover selectRow={selectRowProp} bodyStyle={{ background: '#f4a442' }} ref='table2'>
            <TableHeaderColumn isKey dataField='pk_id_competitor' hidden>compId</TableHeaderColumn>
            <TableHeaderColumn dataField='pic' dataFormat={imageFormatter}>pic</TableHeaderColumn>
            <TableHeaderColumn dataField='ridername' dataSort>Ridername</TableHeaderColumn>
            <TableHeaderColumn dataField='horsename' dataSort>Horsename</TableHeaderColumn>
            <TableHeaderColumn dataField='eventtier'>EventTier</TableHeaderColumn>
          </BootstrapTable>

Tier 3 Eventers

Pick 2

          <BootstrapTable data={EvtTier3} hover selectRow={selectRowProp} bodyStyle={{ background: '#f4a442' }} ref='table3'>
            <TableHeaderColumn isKey dataField='pk_id_competitor' hidden>compId</TableHeaderColumn>
            <TableHeaderColumn dataField='pic' dataFormat={imageFormatter}>pic</TableHeaderColumn>
            <TableHeaderColumn dataField='ridername' dataSort>Ridername</TableHeaderColumn>
            <TableHeaderColumn dataField='horsename' dataSort>Horsename</TableHeaderColumn>
            <TableHeaderColumn dataField='eventtier'>EventTier</TableHeaderColumn>
          </BootstrapTable>

      );

    }

  }

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import classNames from 'classnames';
// import Input from 'input';
import Popover from 'popover';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';

import DatePanel from './date/DatePanel';
import PanelFooter from './common/PanelFooter';
import { goMonths, isArray, isSameMonth } from './utils';
import { formatDate, parseDate, maybeFormatDate } from './utils/date';
import { timeFnMap, noop } from './constants/';

let retType = 'string';

const isValidValue = val => {
  if (!isArray(val)) return false;
  const ret = val.filter(item => !!item);
  return ret.length === 2;
};

const getDateTime = (date, time) => {
  return new Date(
    date.getFullYear(),
    date.getMonth(),
    date.getDate(),
    time.getHours(),
    time.getMinutes(),
    time.getSeconds()
  );
};

const extractStateFromProps = props => {
  const { format, min, max, defaultValue } = props;
  let showPlaceholder;
  let selected = [];
  let actived = [];
  let range = [];
  let value = [];
  console.log(props.value);
  if (isValidValue(props.value)) {
    showPlaceholder = false;
    const tmp = [
      maybeFormatDate(props.value[0], format),
      maybeFormatDate(props.value[1], format)
    ];
    selected = tmp.slice();
    range = tmp.slice();
    actived = tmp.slice();
    value = [formatDate(selected[0], format), formatDate(selected[1], format)];

    // 特殊处理：如果两个时间在同一个月，右边的面板月份加一
    if (isSameMonth(actived[0], actived[1])) {
      actived[1] = goMonths(actived[0], 1);
    }
  } else {
    showPlaceholder = true;
    value = [];
    let start;
    if (defaultValue && isValidValue(defaultValue)) {
      start = maybeFormatDate(defaultValue[0], format);
    } else if (min) {
      start = maybeFormatDate(min, format);
    } else if (max) {
      let maxDate = maybeFormatDate(max, format);
      let timestamp = maxDate && maxDate.getTime();
      if (timestamp < Date.now()) {
        start = goMonths(maxDate, -1);
      }
    } else {
      start = new Date();
    }
    actived = [start, goMonths(start, 1)];
  }

  return {
    value,
    range,
    selected,
    actived,
    activedTime: actived.slice(),
    openPanel: false,
    showError: false,
    openStartTimePanel: false,
    openEndTimePanel: false,
    showPlaceholder
  };
};

class DateRangePicker extends Component {
  static PropTypes = {
    className: PropTypes.string,
    prefix: PropTypes.string,
    placeholder: PropTypes.arrayOf(PropTypes.string),
    confirmText: PropTypes.string,
    valueType: PropTypes.oneOf(['date', 'number', 'string']),
    format: PropTypes.string,
    showTime: PropTypes.bool,
    disabledDate: PropTypes.func,
    onChange: PropTypes.func,
    onClick: PropTypes.func,
    onOpen: PropTypes.func,
    onClose: PropTypes.func
  };

  static defaultProps = {
    className: '',
    prefix: 'zent',
    placeholder: ['开始日期', '结束日期'],
    confirmText: '确认',
    errorText: '请选择起止时间',
    format: 'YYYY-MM-DD',
    showTime: false,
    disabledDate: noop,
    onChange: noop
  };

  constructor(props) {
    super(props);

    const { value, valueType } = props;

    if (valueType) {
      retType = valueType;
    } else if (isValidValue(value)) {
      if (typeof value[0] === 'number') retType = 'number';
      if (value[0] instanceof Date) retType = 'date';
    }

    this.state = extractStateFromProps(props);
  }

  componentWillReceiveProps(next) {
    const { value } = this.props;
    if (!isEqual(value, next.value)) {
      const state = extractStateFromProps(next);
      this.setState(state);
    }
  }

  onHover = val => {
    const { selected, range } = this.state;
    const scp = selected.slice();
    const rcp = range.slice();

    if (scp.length !== 1) {
      rcp.splice(0, 2);
      return;
    }

    if (rcp[0] && rcp[0] < val) {
      rcp.splice(1, 1, val);
      this.setState({
        range: rcp
      });
    }
  };

  onSelectDate = val => {
    const { selected, actived, range } = this.state;
    const { onClick } = this.props;
    const scp = selected.slice();
    const acp = actived.slice();
    const rcp = range.slice();
    let type;

    /**
     * 选择日期时，可能如下出现四种情况
     * 1. 还没有选择过，这次选择的日期作为开始日期
     * 2. 选择过一次，并且第二次选择日期大于第一次，这次选择的日期作为结束日期
     * 3. 有效选择过两次，清空之前的选择，重新设置这次选择的日期作为开始日期
     * 4. 选择过一次，并且这次选择的日期小于第一次，替换这次选择的日期为开始日期
     */
    if (scp.length === 2) {
      scp.splice(0, 2, val);
      rcp.splice(0, 2, val);
      acp.splice(0, 2, val, goMonths(val, 1));
      type = 'start';
      // 支持选择同一天
    } else if (
      scp[0] &&
      (scp[0] < val || formatDate(scp[0]) === formatDate(val))
    ) {
      scp.splice(1, 1, val);
      if (scp[0].getMonth() < val.getMonth()) {
        acp.splice(1, 1, val);
      }
      type = 'end';
    } else {
      acp.splice(0, 2, val, goMonths(val, 1));
      scp.splice(0, 1, val);
      rcp.splice(0, 1, val);
      type = 'start';
    }

    this.setState({
      selected: scp,
      actived: acp,
      range: rcp
    });

    onClick && onClick(val, type);
  };

  isDisabled = val => {
    const { disabledDate, format, min, max } = this.props;

    if (disabledDate && disabledDate(val)) return true;
    if (min && val < parseDate(min, format)) return true;
    if (max && val > parseDate(max, format)) return true;

    return false;
  };

  onChangeDate = (val, i) => {
    const { actived } = this.state;
    const acp = actived.slice();
    acp.splice(i, 1, val);

    this.setState({
      actived: acp
    });
  };

  onChangeStart = val => {
    this.onChangeDate(val, 0);
  };

  onChangeEnd = val => {
    this.onChangeDate(val, 1);
  };

  onChangeTime = (val, i, type) => {
    const { activedTime } = this.state;
    const tcp = activedTime.slice();
    const fn = timeFnMap[type];

    tcp[i][fn](val);
    this.setState({
      activedTime: tcp
    });
  };

  onChangeStartTime = (val, type) => {
    this.onChangeTime(val, 0, type);
  };

  onChangeEndTime = (val, type) => {
    this.onChangeTime(val, 1, type);
  };

  // next&prev month 翻页效果联动
  onChangeMonth = type => {
    const baseMap = {
      prev: 0,
      next: 1
    };
    const typeMap = {
      prev: -1,
      next: 1
    };

    return () => {
      const { actived } = this.state;
      const base = actived[baseMap[type]];
      let acp = [base, base];
      acp.splice(baseMap[type], 1, goMonths(base, typeMap[type]));
      // acp = acp.map((item, i) => {
      //   return i === baseMap[type] ? goMonths(item, typeMap[type]) : item;
      // });

      this.setState({
        actived: acp
      });
    };
  };

  onOpenStartTime = () => {
    this.setState({
      openStartTimePanel: true,
      openEndTimePanel: false
    });
  };

  onOpenEndTime = () => {
    this.setState({
      openStartTimePanel: false,
      openEndTimePanel: true
    });
  };

  onClearInput = evt => {
    evt.stopPropagation();
    this.props.onChange([]);
  };

  /**
   * 如果传入为数字，返回值也为数字
   * 如果传入为 Date 的实例，返回值也为 Date 的实例
   * 默认返回 format 格式的字符串
   */

  getReturnValue(date, format) {
    if (retType === 'number') {
      return date.getTime();
    }

    if (retType === 'date') {
      return date;
    }

    return formatDate(date, format);
  }

  onConfirm = () => {
    const { selected, activedTime } = this.state;

    if (selected.length !== 2) {
      this.setState({
        showError: true
      });
      // eslint-disable-next-line
      let timer = setTimeout(() => {
        this.setState({
          showError: false
        });
        timer = null;
      }, 2000);

      return;
    }

    const { format, showTime } = this.props;

    let tmp = selected.slice();
    if (showTime) {
      tmp = [
        getDateTime(tmp[0], activedTime[0]),
        getDateTime(tmp[1], activedTime[1])
      ];
    }

    const vcp = [formatDate(tmp[0], format), formatDate(tmp[1], format)];
    this.setState({
      value: vcp,
      showPlaceholder: false,
      openPanel: false
    });

    const ret = [
      this.getReturnValue(tmp[0], format),
      this.getReturnValue(tmp[1], format)
    ];
    this.props.onChange(ret);
  };

  renderPicker() {
    const state = this.state;
    const props = this.props;
    let rangePicker;

    const getTimeConfig = type => {
      if (!props.showTime) return false;
      const handleMap = {
        start: this.onChangeStartTime,
        end: this.onChangeEndTime
      };
      const indexMap = {
        start: 0,
        end: 1
      };
      const timeStatusMap = {
        start: 'openEndTimePanel',
        end: 'openStartTimePanel'
      };
      const timeHandleMap = {
        start: this.onOpenStartTime,
        end: this.onOpenEndTime
      };

      return {
        hidePanel: state[timeStatusMap[type]],
        actived: state.activedTime[indexMap[type]],
        disabledTime: props.disabledTime && props.disabledTime(type),
        onChange: handleMap[type],
        onOpen: timeHandleMap[type]
      };
    };

    if (state.openPanel) {
      const pickerCls = classNames({
        'range-picker': true,
        'range-picker--showTime': props.showTime
      });
      rangePicker = (

 (this.picker = ref)}>

            <DatePanel
              range={state.range}
              showTime={getTimeConfig('start')}
              actived={state.actived[0]}
              selected={state.selected}
              disabledDate={this.isDisabled}
              onSelect={this.onSelectDate}
              onChange={this.onChangeStart}
              onHover={this.onHover}
              onPrev={this.onChangeMonth('prev')}
              onNext={noop}
              showPrev
              showNext={false}
            />

            <DatePanel
              range={state.range}
              showTime={getTimeConfig('end')}
              actived={state.actived[1]}
              selected={state.selected}
              disabledDate={this.isDisabled}
              onSelect={this.onSelectDate}
              onChange={this.onChangeEnd}
              onHover={this.onHover}
              onPrev={noop}
              onNext={this.onChangeMonth('next')}
              showPrev={false}
              showNext
            />

          <PanelFooter
            buttonText={props.confirmText}
            onClickButton={this.onConfirm}
            showError={state.showError}
            errorText={props.errorText}
          />

      );
    }

    return rangePicker;
  }

  togglePicker = () => {
    const { onOpen, onClose, disabled } = this.props;
    const openPanel = !this.state.openPanel;

    if (disabled) return;

    openPanel ? onOpen && onOpen() : onClose && onClose();
    this.setState({
      openPanel: !this.state.openPanel
    });
  };

  render() {
    const state = this.state;
    const props = this.props;
    const prefixCls = `${props.prefix}-datetime-picker ${props.className}`;
    const inputCls = classNames({
      'picker-input--range picker-input': true,
      'picker-input--filled': !state.showPlaceholder,
      'picker-input--showTime': props.showTime,
      'picker-input--disabled': props.disabled
    });

    return (

        <Popover
          cushion={5}
          visible={state.openPanel}
          onVisibleChange={this.togglePicker}
          className={`${props.prefix}-datetime-picker-popover ${props.className}-popover`}
          position={Popover.Position.AutoBottomLeft}
        >
          <Popover.Trigger.Click>

              {state.showPlaceholder
                ? props.placeholder.join(' 至 ')
                : state.value.join(' 至 ')}

          </Popover.Trigger.Click>
          <Popover.Content>
            {this.renderPicker()}
          </Popover.Content>
        </Popover>

    );
  }
}

export default DateRangePicker;
<commit_msg>remove unused console<commit_after>import React, { Component } from 'react';
import classNames from 'classnames';
// import Input from 'input';
import Popover from 'popover';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';

import DatePanel from './date/DatePanel';
import PanelFooter from './common/PanelFooter';
import { goMonths, isArray, isSameMonth } from './utils';
import { formatDate, parseDate, maybeFormatDate } from './utils/date';
import { timeFnMap, noop } from './constants/';

let retType = 'string';

const isValidValue = val => {
  if (!isArray(val)) return false;
  const ret = val.filter(item => !!item);
  return ret.length === 2;
};

const getDateTime = (date, time) => {
  return new Date(
    date.getFullYear(),
    date.getMonth(),
    date.getDate(),
    time.getHours(),
    time.getMinutes(),
    time.getSeconds()
  );
};

const extractStateFromProps = props => {
  const { format, min, max, defaultValue } = props;
  let showPlaceholder;
  let selected = [];
  let actived = [];
  let range = [];
  let value = [];

  if (isValidValue(props.value)) {
    showPlaceholder = false;
    const tmp = [
      maybeFormatDate(props.value[0], format),
      maybeFormatDate(props.value[1], format)
    ];
    selected = tmp.slice();
    range = tmp.slice();
    actived = tmp.slice();
    value = [formatDate(selected[0], format), formatDate(selected[1], format)];

    // 特殊处理：如果两个时间在同一个月，右边的面板月份加一
    if (isSameMonth(actived[0], actived[1])) {
      actived[1] = goMonths(actived[0], 1);
    }
  } else {
    showPlaceholder = true;
    value = [];
    let start;
    if (defaultValue && isValidValue(defaultValue)) {
      start = maybeFormatDate(defaultValue[0], format);
    } else if (min) {
      start = maybeFormatDate(min, format);
    } else if (max) {
      let maxDate = maybeFormatDate(max, format);
      let timestamp = maxDate && maxDate.getTime();
      if (timestamp < Date.now()) {
        start = goMonths(maxDate, -1);
      }
    } else {
      start = new Date();
    }
    actived = [start, goMonths(start, 1)];
  }

  return {
    value,
    range,
    selected,
    actived,
    activedTime: actived.slice(),
    openPanel: false,
    showError: false,
    openStartTimePanel: false,
    openEndTimePanel: false,
    showPlaceholder
  };
};

class DateRangePicker extends Component {
  static PropTypes = {
    className: PropTypes.string,
    prefix: PropTypes.string,
    placeholder: PropTypes.arrayOf(PropTypes.string),
    confirmText: PropTypes.string,
    valueType: PropTypes.oneOf(['date', 'number', 'string']),
    format: PropTypes.string,
    showTime: PropTypes.bool,
    disabledDate: PropTypes.func,
    onChange: PropTypes.func,
    onClick: PropTypes.func,
    onOpen: PropTypes.func,
    onClose: PropTypes.func
  };

  static defaultProps = {
    className: '',
    prefix: 'zent',
    placeholder: ['开始日期', '结束日期'],
    confirmText: '确认',
    errorText: '请选择起止时间',
    format: 'YYYY-MM-DD',
    showTime: false,
    disabledDate: noop,
    onChange: noop
  };

  constructor(props) {
    super(props);

    const { value, valueType } = props;

    if (valueType) {
      retType = valueType;
    } else if (isValidValue(value)) {
      if (typeof value[0] === 'number') retType = 'number';
      if (value[0] instanceof Date) retType = 'date';
    }

    this.state = extractStateFromProps(props);
  }

  componentWillReceiveProps(next) {
    const { value } = this.props;
    if (!isEqual(value, next.value)) {
      const state = extractStateFromProps(next);
      this.setState(state);
    }
  }

  onHover = val => {
    const { selected, range } = this.state;
    const scp = selected.slice();
    const rcp = range.slice();

    if (scp.length !== 1) {
      rcp.splice(0, 2);
      return;
    }

    if (rcp[0] && rcp[0] < val) {
      rcp.splice(1, 1, val);
      this.setState({
        range: rcp
      });
    }
  };

  onSelectDate = val => {
    const { selected, actived, range } = this.state;
    const { onClick } = this.props;
    const scp = selected.slice();
    const acp = actived.slice();
    const rcp = range.slice();
    let type;

    /**
     * 选择日期时，可能如下出现四种情况
     * 1. 还没有选择过，这次选择的日期作为开始日期
     * 2. 选择过一次，并且第二次选择日期大于第一次，这次选择的日期作为结束日期
     * 3. 有效选择过两次，清空之前的选择，重新设置这次选择的日期作为开始日期
     * 4. 选择过一次，并且这次选择的日期小于第一次，替换这次选择的日期为开始日期
     */
    if (scp.length === 2) {
      scp.splice(0, 2, val);
      rcp.splice(0, 2, val);
      acp.splice(0, 2, val, goMonths(val, 1));
      type = 'start';
      // 支持选择同一天
    } else if (
      scp[0] &&
      (scp[0] < val || formatDate(scp[0]) === formatDate(val))
    ) {
      scp.splice(1, 1, val);
      if (scp[0].getMonth() < val.getMonth()) {
        acp.splice(1, 1, val);
      }
      type = 'end';
    } else {
      acp.splice(0, 2, val, goMonths(val, 1));
      scp.splice(0, 1, val);
      rcp.splice(0, 1, val);
      type = 'start';
    }

    this.setState({
      selected: scp,
      actived: acp,
      range: rcp
    });

    onClick && onClick(val, type);
  };

  isDisabled = val => {
    const { disabledDate, format, min, max } = this.props;

    if (disabledDate && disabledDate(val)) return true;
    if (min && val < parseDate(min, format)) return true;
    if (max && val > parseDate(max, format)) return true;

    return false;
  };

  onChangeDate = (val, i) => {
    const { actived } = this.state;
    const acp = actived.slice();
    acp.splice(i, 1, val);

    this.setState({
      actived: acp
    });
  };

  onChangeStart = val => {
    this.onChangeDate(val, 0);
  };

  onChangeEnd = val => {
    this.onChangeDate(val, 1);
  };

  onChangeTime = (val, i, type) => {
    const { activedTime } = this.state;
    const tcp = activedTime.slice();
    const fn = timeFnMap[type];

    tcp[i][fn](val);
    this.setState({
      activedTime: tcp
    });
  };

  onChangeStartTime = (val, type) => {
    this.onChangeTime(val, 0, type);
  };

  onChangeEndTime = (val, type) => {
    this.onChangeTime(val, 1, type);
  };

  // next&prev month 翻页效果联动
  onChangeMonth = type => {
    const baseMap = {
      prev: 0,
      next: 1
    };
    const typeMap = {
      prev: -1,
      next: 1
    };

    return () => {
      const { actived } = this.state;
      const base = actived[baseMap[type]];
      let acp = [base, base];
      acp.splice(baseMap[type], 1, goMonths(base, typeMap[type]));
      // acp = acp.map((item, i) => {
      //   return i === baseMap[type] ? goMonths(item, typeMap[type]) : item;
      // });

      this.setState({
        actived: acp
      });
    };
  };

  onOpenStartTime = () => {
    this.setState({
      openStartTimePanel: true,
      openEndTimePanel: false
    });
  };

  onOpenEndTime = () => {
    this.setState({
      openStartTimePanel: false,
      openEndTimePanel: true
    });
  };

  onClearInput = evt => {
    evt.stopPropagation();
    this.props.onChange([]);
  };

  /**
   * 如果传入为数字，返回值也为数字
   * 如果传入为 Date 的实例，返回值也为 Date 的实例
   * 默认返回 format 格式的字符串
   */

  getReturnValue(date, format) {
    if (retType === 'number') {
      return date.getTime();
    }

    if (retType === 'date') {
      return date;
    }

    return formatDate(date, format);
  }

  onConfirm = () => {
    const { selected, activedTime } = this.state;

    if (selected.length !== 2) {
      this.setState({
        showError: true
      });
      // eslint-disable-next-line
      let timer = setTimeout(() => {
        this.setState({
          showError: false
        });
        timer = null;
      }, 2000);

      return;
    }

    const { format, showTime } = this.props;

    let tmp = selected.slice();
    if (showTime) {
      tmp = [
        getDateTime(tmp[0], activedTime[0]),
        getDateTime(tmp[1], activedTime[1])
      ];
    }

    const vcp = [formatDate(tmp[0], format), formatDate(tmp[1], format)];
    this.setState({
      value: vcp,
      showPlaceholder: false,
      openPanel: false
    });

    const ret = [
      this.getReturnValue(tmp[0], format),
      this.getReturnValue(tmp[1], format)
    ];
    this.props.onChange(ret);
  };

  renderPicker() {
    const state = this.state;
    const props = this.props;
    let rangePicker;

    const getTimeConfig = type => {
      if (!props.showTime) return false;
      const handleMap = {
        start: this.onChangeStartTime,
        end: this.onChangeEndTime
      };
      const indexMap = {
        start: 0,
        end: 1
      };
      const timeStatusMap = {
        start: 'openEndTimePanel',
        end: 'openStartTimePanel'
      };
      const timeHandleMap = {
        start: this.onOpenStartTime,
        end: this.onOpenEndTime
      };

      return {
        hidePanel: state[timeStatusMap[type]],
        actived: state.activedTime[indexMap[type]],
        disabledTime: props.disabledTime && props.disabledTime(type),
        onChange: handleMap[type],
        onOpen: timeHandleMap[type]
      };
    };

    if (state.openPanel) {
      const pickerCls = classNames({
        'range-picker': true,
        'range-picker--showTime': props.showTime
      });
      rangePicker = (

 (this.picker = ref)}>

            <DatePanel
              range={state.range}
              showTime={getTimeConfig('start')}
              actived={state.actived[0]}
              selected={state.selected}
              disabledDate={this.isDisabled}
              onSelect={this.onSelectDate}
              onChange={this.onChangeStart}
              onHover={this.onHover}
              onPrev={this.onChangeMonth('prev')}
              onNext={noop}
              showPrev
              showNext={false}
            />

            <DatePanel
              range={state.range}
              showTime={getTimeConfig('end')}
              actived={state.actived[1]}
              selected={state.selected}
              disabledDate={this.isDisabled}
              onSelect={this.onSelectDate}
              onChange={this.onChangeEnd}
              onHover={this.onHover}
              onPrev={noop}
              onNext={this.onChangeMonth('next')}
              showPrev={false}
              showNext
            />

          <PanelFooter
            buttonText={props.confirmText}
            onClickButton={this.onConfirm}
            showError={state.showError}
            errorText={props.errorText}
          />

      );
    }

    return rangePicker;
  }

  togglePicker = () => {
    const { onOpen, onClose, disabled } = this.props;
    const openPanel = !this.state.openPanel;

    if (disabled) return;

    openPanel ? onOpen && onOpen() : onClose && onClose();
    this.setState({
      openPanel: !this.state.openPanel
    });
  };

  render() {
    const state = this.state;
    const props = this.props;
    const prefixCls = `${props.prefix}-datetime-picker ${props.className}`;
    const inputCls = classNames({
      'picker-input--range picker-input': true,
      'picker-input--filled': !state.showPlaceholder,
      'picker-input--showTime': props.showTime,
      'picker-input--disabled': props.disabled
    });

    return (

        <Popover
          cushion={5}
          visible={state.openPanel}
          onVisibleChange={this.togglePicker}
          className={`${props.prefix}-datetime-picker-popover ${props.className}-popover`}
          position={Popover.Position.AutoBottomLeft}
        >
          <Popover.Trigger.Click>

              {state.showPlaceholder
                ? props.placeholder.join(' 至 ')
                : state.value.join(' 至 ')}

          </Popover.Trigger.Click>
          <Popover.Content>
            {this.renderPicker()}
          </Popover.Content>
        </Popover>

    );
  }
}

export default DateRangePicker;
<|endoftext|>


<commit_before>// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', 'angular-cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-remap-istanbul'),
      require('angular-cli/plugins/karma')
    ],
    files: [
      { pattern: './src/test.ts', watched: false }
    ],
    preprocessors: {
      './src/test.ts': ['angular-cli']
    },
    mime: {
      'text/x-typescript': ['ts','tsx']
    },
    remapIstanbulReporter: {
      reports: {
        html: 'coverage',
        lcovonly: './coverage/coverage.lcov'
      }
    },
    angularCli: {
      config: './angular-cli.json',
      environment: 'dev'
    },
    reporters: config.angularCli && config.angularCli.codeCoverage
              ? ['progress', 'karma-remap-istanbul']
              : ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<commit_msg>Delete karma.conf.js<commit_after><|endoftext|>


<commit_before>// tests/e2e/pattern-lab-compiling.js

// const url = require('url');
// const querystring = require('querystring');
// const fetch = require('node-fetch');
const sauce = require('../../scripts/nightwatch-sauce');
// // const { spawnSync } = require('child_process');

// const { NOW_TOKEN } = process.env;

// if (!NOW_TOKEN) {
//   console.error('Need to have env var of NOW_TOKEN set');
//   process.exit(1);
// }

// const getDeployUrl = async () => {
//   // @todo determine if this is even needed since we have `deployedUrl` from deploy command
//   const nowEndpoint = url.resolve(
//     'https://api.zeit.co/v2/now/deployments',
//     `?${querystring.stringify({
//       teamId: 'boltdesignsystem',
//     })}`,
//   );

//   const nowDeploys = await fetch(nowEndpoint, {
//     headers: {
//       Authorization: `Bearer ${NOW_TOKEN}`,
//       'Content-Type': 'application/json',
//     },
//   }).then(res => res.json());

//   if (!nowDeploys) {
//     console.error('Did not get any info on latest now deploys...');
//     process.exit(1);
//   }

//   nowDeploys.deployments
//     .sort((a, b) => {
//       return a.created - b.created;
//     })
//     .reverse();

//   const latestDeploy = nowDeploys.deployments[0];
//   console.log('Latest now.sh Deploy:');
//   console.log(latestDeploy);
//   return 'https://' + latestDeploy.url;
// };

// function getUrl() {
//   const server = process.env.NOW_URL
//   ? process.env.NOW_URL
//   : 'http://localhost:3000';

//   return server;
// }

var testingUrl = process.env.NOW_URL = 'https://boltdesignsystem.com';

// let testingUrl = ''; // cached deploy url we grab from the now.sh API

module.exports = {
  // async beforeEach(browser, done) {
  //   testingUrl = await getDeployUrl();
  //   done();
  //   // // log the url being tested against to make it easier to debug failed deploys
  //   // function logTestingUrl() {
  //   //   console.log(`Running tests against the ${testingUrl} deploy url.`);
  //   // }

  //   // // grab the latest testing URL from now.sh if we haven't grabbed it yet.
  //   // if (testingUrl === '') {
  //   //   getUrl().then(deployUrl => {
  //   //     testingUrl = deployUrl; //
  //   //     logTestingUrl();
  //   //     done();
  //   //   });

  //   //   // otherwise let's be efficient and use the deploy url we already got
  //   // } else {
  //   //   logTestingUrl();
  //   //   done();
  //   // }
  // },

  'Bolt Docs: Verify Docs Site Compiled + Deployed': function(browser) {
    browser
      .url(`${testingUrl}`)
      .waitForElementVisible('.c-bolt-site', 1000)
      .assert.containsText('.c-bolt-navbar__title-text', 'Bolt Design System')
      .end();
  },

  'Pattern Lab: Confirm Successful Now.sh Deploy + Pattern Lab Compiled': function(
    browser,
  ) {
    browser
      .url(`${testingUrl}/pattern-lab/index.html`)
      .waitForElementVisible('.pl-c-body', 1000)
      .verify.title('Pattern Lab - components-overview')
      .end();
  },
  tearDown: sauce,
};
<commit_msg>fix: removing old code<commit_after>// tests/e2e/pattern-lab-compiling.js

// const url = require('url');
// const querystring = require('querystring');
// const fetch = require('node-fetch');
const sauce = require('../../scripts/nightwatch-sauce');
// // const { spawnSync } = require('child_process');

// const { NOW_TOKEN } = process.env;

// if (!NOW_TOKEN) {
//   console.error('Need to have env var of NOW_TOKEN set');
//   process.exit(1);
// }

// const getDeployUrl = async () => {
//   // @todo determine if this is even needed since we have `deployedUrl` from deploy command
//   const nowEndpoint = url.resolve(
//     'https://api.zeit.co/v2/now/deployments',
//     `?${querystring.stringify({
//       teamId: 'boltdesignsystem',
//     })}`,
//   );

//   const nowDeploys = await fetch(nowEndpoint, {
//     headers: {
//       Authorization: `Bearer ${NOW_TOKEN}`,
//       'Content-Type': 'application/json',
//     },
//   }).then(res => res.json());

//   if (!nowDeploys) {
//     console.error('Did not get any info on latest now deploys...');
//     process.exit(1);
//   }

//   nowDeploys.deployments
//     .sort((a, b) => {
//       return a.created - b.created;
//     })
//     .reverse();

//   const latestDeploy = nowDeploys.deployments[0];
//   console.log('Latest now.sh Deploy:');
//   console.log(latestDeploy);
//   return 'https://' + latestDeploy.url;
// };

// function getUrl() {
//   const server = process.env.NOW_URL
//   ? process.env.NOW_URL
//   : 'http://localhost:3000';

//   return server;
// }

var testingUrl = process.env.NOW_URL = 'https://boltdesignsystem.com';

// let testingUrl = ''; // cached deploy url we grab from the now.sh API

module.exports = {
  // async beforeEach(browser, done) {
  //   testingUrl = await getDeployUrl();
  //   done();
  //   // // log the url being tested against to make it easier to debug failed deploys
  //   // function logTestingUrl() {
  //   //   console.log(`Running tests against the ${testingUrl} deploy url.`);
  //   // }

  //   // // grab the latest testing URL from now.sh if we haven't grabbed it yet.
  //   // if (testingUrl === '') {
  //   //   getUrl().then(deployUrl => {
  //   //     testingUrl = deployUrl; //
  //   //     logTestingUrl();
  //   //     done();
  //   //   });

  //   //   // otherwise let's be efficient and use the deploy url we already got
  //   // } else {
  //   //   logTestingUrl();
  //   //   done();
  //   // }
  // },

  'Pattern Lab: Confirm Successful Now.sh Deploy + Pattern Lab Compiled': function(
    browser,
  ) {
    browser
      .url(`${testingUrl}/pattern-lab/index.html`)
      .waitForElementVisible('.pl-c-body', 1000)
      .verify.title('Pattern Lab - components-overview')
      .end();
  },
  tearDown: sauce,
};
<|endoftext|>


<commit_before>/**
 * plupload.html4.js
 *
 * Copyright 2010, Ryan Demmer
 * Copyright 2009, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

// JSLint defined globals
/*global plupload:false, window:false */

(function(window, document, plupload, undef) {
	function getById(id) {
		return document.getElementById(id);
	}

	/**
	 * HTML4 implementation. This runtime has no special features it uses an form that posts files into an hidden iframe.
	 *
	 * @static
	 * @class plupload.runtimes.Html4
	 * @extends plupload.Runtime
	 */
	plupload.runtimes.Html4 = plupload.addRuntime("html4", {
		/**
		 * Returns a list of supported features for the runtime.
		 *
		 * @return {Object} Name/value object with supported features.
		 */
		getFeatures : function() {
			// Only multipart feature
			return {
				multipart: true,

				// WebKit and Gecko 2+ can trigger file dialog progrmmatically
				triggerDialog: (plupload.ua.gecko && window.FormData || plupload.ua.webkit)
			};
		},

		/**
		 * Initializes the upload runtime.
		 *
		 * @method init
		 * @param {plupload.Uploader} uploader Uploader instance that needs to be initialized.
		 * @param {function} callback Callback to execute when the runtime initializes or fails to initialize. If it succeeds an object with a parameter name success will be set to true.
		 */
		init : function(uploader, callback) {
			uploader.bind("Init", function(up) {
				var container = document.body, iframe, url = "javascript", currentFile,
					input, currentFileId, fileIds = [], IE = /MSIE/.test(navigator.userAgent), mimes = [],
					filters = up.settings.filters, i, ext, type, y;

				// Convert extensions to mime types list
				no_type_restriction:
				for (i = 0; i < filters.length; i++) {
					ext = filters[i].extensions.split(/,/);

					for (y = 0; y < ext.length; y++) {

						// If there's an asterisk in the list, then accept attribute is not required
						if (ext[y] === '*') {
							mimes = [];
							break no_type_restriction;
						}

						type = plupload.mimeTypes[ext[y]];

						if (type && plupload.inArray(type, mimes) === -1) {
							mimes.push(type);
						}
					}
				}

				mimes = mimes.join(',');

				function createForm() {
					var form, input, bgcolor, browseButton;

					// Setup unique id for form
					currentFileId = plupload.guid();

					// Save id for Destroy handler
					fileIds.push(currentFileId);

					// Create form
					form = document.createElement('form');
					form.setAttribute('id', 'form_' + currentFileId);
					form.setAttribute('method', 'post');
					form.setAttribute('enctype', 'multipart/form-data');
					form.setAttribute('encoding', 'multipart/form-data');
					form.setAttribute("target", up.id + '_iframe');
					form.style.position = 'absolute';

					// Create input and set attributes
					input = document.createElement('input');
					input.setAttribute('id', 'input_' + currentFileId);
					input.setAttribute('type', 'file');
					input.setAttribute('accept', mimes);
					input.setAttribute('size', 1);

					browseButton = getById(up.settings.browse_button);

					// Route click event to input element programmatically, if possible
					if (up.features.triggerDialog && browseButton) {
						plupload.addEvent(getById(up.settings.browse_button), 'click', function(e) {
							if (!input.disabled) {
								input.click();
							}
							e.preventDefault();
						}, up.id);
					}

					// Set input styles
					plupload.extend(input.style, {
						width : '100%',
						height : '100%',
						opacity : 0,
						fontSize: '99px' // force input element to be bigger then needed to occupy whole space
					});

					plupload.extend(form.style, {
						overflow: 'hidden'
					});

					// Show the container if shim_bgcolor is specified
					bgcolor = up.settings.shim_bgcolor;
					if (bgcolor) {
						form.style.background = bgcolor;
					}

					// no opacity in IE
					if (IE) {
						plupload.extend(input.style, {
							filter : "alpha(opacity=0)"
						});
					}

					// add change event
					plupload.addEvent(input, 'change', function(e) {
						var element = e.target, name, files = [], topElement;

						if (element.value) {
							getById('form_' + currentFileId).style.top = -0xFFFFF + "px";

							// Get file name
							name = element.value.replace(/\\/g, '/');
							name = name.substring(name.length, name.lastIndexOf('/') + 1);

							// Push files
							files.push(new plupload.File(currentFileId, name));

							// Clean-up events - they won't be needed anymore
							if (!up.features.triggerDialog) {
								plupload.removeAllEvents(form, up.id);
							} else {
								plupload.removeEvent(browseButton, 'click', up.id);
							}
							plupload.removeEvent(input, 'change', up.id);

							// Create and position next form
							createForm();

							// Fire FilesAdded event
							if (files.length) {
								uploader.trigger("FilesAdded", files);
							}
						}
					}, up.id);

					// append to container
					form.appendChild(input);
					container.appendChild(form);

					up.refresh();
				}

				function createIframe() {
					var temp = document.createElement('div');

					// Create iframe using a temp div since IE 6 won't be able to set the name using setAttribute or iframe.name
					temp.innerHTML = '';
					iframe = temp.firstChild;
					container.appendChild(iframe);

					// Add IFrame onload event
					plupload.addEvent(iframe, 'load', function(e) {
						var n = e.target, el, result;

						// Ignore load event if there is no file
						if (!currentFile) {
							return;
						}

						try {
							el = n.contentWindow.document || n.contentDocument || window.frames[n.id].document;
						} catch (ex) {
							// Probably a permission denied error
							up.trigger('Error', {
								code : plupload.SECURITY_ERROR,
								message : plupload.translate('Security error.'),
								file : currentFile
							});

							return;
						}

						// Get result
						result = el.body.innerHTML;

						// Assume no error
						if (result) {
							currentFile.status = plupload.DONE;
							currentFile.loaded = 1025;
							currentFile.percent = 100;

							up.trigger('UploadProgress', currentFile);
							up.trigger('FileUploaded', currentFile, {
								response : result
							});
						}
					}, up.id);
				} // end createIframe

				if (up.settings.container) {
					container = getById(up.settings.container);
					if (plupload.getStyle(container, 'position') === 'static') {
						container.style.position = 'relative';
					}
				}

				// Upload file
				up.bind("UploadFile", function(up, file) {
					var form, input;

					// File upload finished
					if (file.status == plupload.DONE || file.status == plupload.FAILED || up.state == plupload.STOPPED) {
						return;
					}

					// Get the form and input elements
					form = getById('form_' + file.id);
					input = getById('input_' + file.id);

					// Set input element name attribute which allows it to be submitted
					input.setAttribute('name', up.settings.file_data_name);

					// Store action
					form.setAttribute("action", up.settings.url);

					// Append multipart parameters
					plupload.each(plupload.extend({name : file.target_name || file.name}, up.settings.multipart_params), function(value, name) {
						var hidden = document.createElement('input');

						plupload.extend(hidden, {
							type : 'hidden',
							name : name,
							value : value
						});

						form.insertBefore(hidden, form.firstChild);
					});

					currentFile = file;

					// Hide the current form
					getById('form_' + currentFileId).style.top = -0xFFFFF + "px";

					form.submit();
					form.parentNode.removeChild(form);
				});

				up.bind('FileUploaded', function(up) {
					up.refresh(); // just to get the form back on top of browse_button
				});

				up.bind('StateChanged', function(up) {
					if (up.state == plupload.STARTED) {
						createIframe();
					}

					if (up.state == plupload.STOPPED) {
						window.setTimeout(function() {
							plupload.removeEvent(iframe, 'load', up.id);
							if (iframe.parentNode) { // #382
								iframe.parentNode.removeChild(iframe);
							}
						}, 0);
					}
				});

				// Refresh button, will reposition the input form
				up.bind("Refresh", function(up) {
					var browseButton, topElement, hoverClass, activeClass, browsePos, browseSize, inputContainer, inputFile, zIndex;

					browseButton = getById(up.settings.browse_button);
					if (browseButton) {
						browsePos = plupload.getPos(browseButton, getById(up.settings.container));
						browseSize = plupload.getSize(browseButton);
						inputContainer = getById('form_' + currentFileId);
						inputFile = getById('input_' + currentFileId);

						plupload.extend(inputContainer.style, {
							top : browsePos.y + 'px',
							left : browsePos.x + 'px',
							width : browseSize.w + 'px',
							height : browseSize.h + 'px'
						});

						// for IE and WebKit place input element underneath the browse button and route onclick event
						// TODO: revise when browser support for this feature will change
						if (up.features.triggerDialog) {
							if (plupload.getStyle(browseButton, 'position') === 'static') {
								plupload.extend(browseButton.style, {
									position : 'relative'
								});
							}

							zIndex = parseInt(browseButton.style.zIndex, 10);

							if (isNaN(zIndex)) {
								zIndex = 0;
							}

							plupload.extend(browseButton.style, {
								zIndex : zIndex
							});

							plupload.extend(inputContainer.style, {
								zIndex : zIndex - 1
							});
						}

						/* Since we have to place input[type=file] on top of the browse_button for some browsers (FF, Opera),
						browse_button loses interactivity, here we try to neutralize this issue highlighting browse_button
						with a special class
						TODO: needs to be revised as things will change */
						hoverClass = up.settings.browse_button_hover;
						activeClass = up.settings.browse_button_active;
						topElement = up.features.triggerDialog ? browseButton : inputContainer;

						if (hoverClass) {
							plupload.addEvent(topElement, 'mouseover', function() {
								plupload.addClass(browseButton, hoverClass);
							}, up.id);
							plupload.addEvent(topElement, 'mouseout', function() {
								plupload.removeClass(browseButton, hoverClass);
							}, up.id);
						}

						if (activeClass) {
							plupload.addEvent(topElement, 'mousedown', function() {
								plupload.addClass(browseButton, activeClass);
							}, up.id);
							plupload.addEvent(document.body, 'mouseup', function() {
								plupload.removeClass(browseButton, activeClass);
							}, up.id);
						}
					}
				});

				// Remove files
				uploader.bind("FilesRemoved", function(up, files) {
					var i, n;

					for (i = 0; i < files.length; i++) {
						n = getById('form_' + files[i].id);
						if (n) {
							n.parentNode.removeChild(n);
						}
					}
				});

				uploader.bind("DisableBrowse", function(up, disabled) {
					var input = document.getElementById('input_' + currentFileId);
					if (input) {
						input.disabled = disabled;
					}
				});

				// Completely destroy the runtime
				uploader.bind("Destroy", function(up) {
					var name, element, form,
						elements = {
							inputContainer: 'form_' + currentFileId,
							inputFile: 'input_' + currentFileId,
							browseButton: up.settings.browse_button
						};

					// Unbind event handlers
					for (name in elements) {
						element = getById(elements[name]);
						if (element) {
							plupload.removeAllEvents(element, up.id);
						}
					}
					plupload.removeAllEvents(document.body, up.id);

					// Remove mark-up
					plupload.each(fileIds, function(id, i) {
						form = getById('form_' + id);
						if (form) {
							container.removeChild(form);
						}
					});

				});

				// Create initial form
				createForm();
			});

			callback({success : true});
		}
	});
})(window, document, plupload);
<commit_msg>fixed issue #472: IE8, HTML4: mouse cursor type should be pointer<commit_after>/**
 * plupload.html4.js
 *
 * Copyright 2010, Ryan Demmer
 * Copyright 2009, Moxiecode Systems AB
 * Released under GPL License.
 *
 * License: http://www.plupload.com/license
 * Contributing: http://www.plupload.com/contributing
 */

// JSLint defined globals
/*global plupload:false, window:false */

(function(window, document, plupload, undef) {
	function getById(id) {
		return document.getElementById(id);
	}

	/**
	 * HTML4 implementation. This runtime has no special features it uses an form that posts files into an hidden iframe.
	 *
	 * @static
	 * @class plupload.runtimes.Html4
	 * @extends plupload.Runtime
	 */
	plupload.runtimes.Html4 = plupload.addRuntime("html4", {
		/**
		 * Returns a list of supported features for the runtime.
		 *
		 * @return {Object} Name/value object with supported features.
		 */
		getFeatures : function() {
			// Only multipart feature
			return {
				multipart: true,

				// WebKit and Gecko 2+ can trigger file dialog progrmmatically
				triggerDialog: (plupload.ua.gecko && window.FormData || plupload.ua.webkit)
			};
		},

		/**
		 * Initializes the upload runtime.
		 *
		 * @method init
		 * @param {plupload.Uploader} uploader Uploader instance that needs to be initialized.
		 * @param {function} callback Callback to execute when the runtime initializes or fails to initialize. If it succeeds an object with a parameter name success will be set to true.
		 */
		init : function(uploader, callback) {
			uploader.bind("Init", function(up) {
				var container = document.body, iframe, url = "javascript", currentFile,
					input, currentFileId, fileIds = [], IE = /MSIE/.test(navigator.userAgent), mimes = [],
					filters = up.settings.filters, i, ext, type, y;

				// Convert extensions to mime types list
				no_type_restriction:
				for (i = 0; i < filters.length; i++) {
					ext = filters[i].extensions.split(/,/);

					for (y = 0; y < ext.length; y++) {

						// If there's an asterisk in the list, then accept attribute is not required
						if (ext[y] === '*') {
							mimes = [];
							break no_type_restriction;
						}

						type = plupload.mimeTypes[ext[y]];

						if (type && plupload.inArray(type, mimes) === -1) {
							mimes.push(type);
						}
					}
				}

				mimes = mimes.join(',');

				function createForm() {
					var form, input, bgcolor, browseButton;

					// Setup unique id for form
					currentFileId = plupload.guid();

					// Save id for Destroy handler
					fileIds.push(currentFileId);

					// Create form
					form = document.createElement('form');
					form.setAttribute('id', 'form_' + currentFileId);
					form.setAttribute('method', 'post');
					form.setAttribute('enctype', 'multipart/form-data');
					form.setAttribute('encoding', 'multipart/form-data');
					form.setAttribute("target", up.id + '_iframe');
					form.style.position = 'absolute';

					// Create input and set attributes
					input = document.createElement('input');
					input.setAttribute('id', 'input_' + currentFileId);
					input.setAttribute('type', 'file');
					input.setAttribute('accept', mimes);
					input.setAttribute('size', 1);

					browseButton = getById(up.settings.browse_button);

					// Route click event to input element programmatically, if possible
					if (up.features.triggerDialog && browseButton) {
						plupload.addEvent(getById(up.settings.browse_button), 'click', function(e) {
							if (!input.disabled) {
								input.click();
							}
							e.preventDefault();
						}, up.id);
					}

					// Set input styles
					plupload.extend(input.style, {
						width : '100%',
						height : '100%',
						opacity : 0,
						fontSize: '99px', // force input element to be bigger then needed to occupy whole space
						cursor: 'pointer'
					});

					plupload.extend(form.style, {
						overflow: 'hidden'
					});

					// Show the container if shim_bgcolor is specified
					bgcolor = up.settings.shim_bgcolor;
					if (bgcolor) {
						form.style.background = bgcolor;
					}

					// no opacity in IE
					if (IE) {
						plupload.extend(input.style, {
							filter : "alpha(opacity=0)"
						});
					}

					// add change event
					plupload.addEvent(input, 'change', function(e) {
						var element = e.target, name, files = [], topElement;

						if (element.value) {
							getById('form_' + currentFileId).style.top = -0xFFFFF + "px";

							// Get file name
							name = element.value.replace(/\\/g, '/');
							name = name.substring(name.length, name.lastIndexOf('/') + 1);

							// Push files
							files.push(new plupload.File(currentFileId, name));

							// Clean-up events - they won't be needed anymore
							if (!up.features.triggerDialog) {
								plupload.removeAllEvents(form, up.id);
							} else {
								plupload.removeEvent(browseButton, 'click', up.id);
							}
							plupload.removeEvent(input, 'change', up.id);

							// Create and position next form
							createForm();

							// Fire FilesAdded event
							if (files.length) {
								uploader.trigger("FilesAdded", files);
							}
						}
					}, up.id);

					// append to container
					form.appendChild(input);
					container.appendChild(form);

					up.refresh();
				}

				function createIframe() {
					var temp = document.createElement('div');

					// Create iframe using a temp div since IE 6 won't be able to set the name using setAttribute or iframe.name
					temp.innerHTML = '';
					iframe = temp.firstChild;
					container.appendChild(iframe);

					// Add IFrame onload event
					plupload.addEvent(iframe, 'load', function(e) {
						var n = e.target, el, result;

						// Ignore load event if there is no file
						if (!currentFile) {
							return;
						}

						try {
							el = n.contentWindow.document || n.contentDocument || window.frames[n.id].document;
						} catch (ex) {
							// Probably a permission denied error
							up.trigger('Error', {
								code : plupload.SECURITY_ERROR,
								message : plupload.translate('Security error.'),
								file : currentFile
							});

							return;
						}

						// Get result
						result = el.body.innerHTML;

						// Assume no error
						if (result) {
							currentFile.status = plupload.DONE;
							currentFile.loaded = 1025;
							currentFile.percent = 100;

							up.trigger('UploadProgress', currentFile);
							up.trigger('FileUploaded', currentFile, {
								response : result
							});
						}
					}, up.id);
				} // end createIframe

				if (up.settings.container) {
					container = getById(up.settings.container);
					if (plupload.getStyle(container, 'position') === 'static') {
						container.style.position = 'relative';
					}
				}

				// Upload file
				up.bind("UploadFile", function(up, file) {
					var form, input;

					// File upload finished
					if (file.status == plupload.DONE || file.status == plupload.FAILED || up.state == plupload.STOPPED) {
						return;
					}

					// Get the form and input elements
					form = getById('form_' + file.id);
					input = getById('input_' + file.id);

					// Set input element name attribute which allows it to be submitted
					input.setAttribute('name', up.settings.file_data_name);

					// Store action
					form.setAttribute("action", up.settings.url);

					// Append multipart parameters
					plupload.each(plupload.extend({name : file.target_name || file.name}, up.settings.multipart_params), function(value, name) {
						var hidden = document.createElement('input');

						plupload.extend(hidden, {
							type : 'hidden',
							name : name,
							value : value
						});

						form.insertBefore(hidden, form.firstChild);
					});

					currentFile = file;

					// Hide the current form
					getById('form_' + currentFileId).style.top = -0xFFFFF + "px";

					form.submit();
					form.parentNode.removeChild(form);
				});

				up.bind('FileUploaded', function(up) {
					up.refresh(); // just to get the form back on top of browse_button
				});

				up.bind('StateChanged', function(up) {
					if (up.state == plupload.STARTED) {
						createIframe();
					}

					if (up.state == plupload.STOPPED) {
						window.setTimeout(function() {
							plupload.removeEvent(iframe, 'load', up.id);
							if (iframe.parentNode) { // #382
								iframe.parentNode.removeChild(iframe);
							}
						}, 0);
					}
				});

				// Refresh button, will reposition the input form
				up.bind("Refresh", function(up) {
					var browseButton, topElement, hoverClass, activeClass, browsePos, browseSize, inputContainer, inputFile, zIndex;

					browseButton = getById(up.settings.browse_button);
					if (browseButton) {
						browsePos = plupload.getPos(browseButton, getById(up.settings.container));
						browseSize = plupload.getSize(browseButton);
						inputContainer = getById('form_' + currentFileId);
						inputFile = getById('input_' + currentFileId);

						plupload.extend(inputContainer.style, {
							top : browsePos.y + 'px',
							left : browsePos.x + 'px',
							width : browseSize.w + 'px',
							height : browseSize.h + 'px'
						});

						// for IE and WebKit place input element underneath the browse button and route onclick event
						// TODO: revise when browser support for this feature will change
						if (up.features.triggerDialog) {
							if (plupload.getStyle(browseButton, 'position') === 'static') {
								plupload.extend(browseButton.style, {
									position : 'relative'
								});
							}

							zIndex = parseInt(browseButton.style.zIndex, 10);

							if (isNaN(zIndex)) {
								zIndex = 0;
							}

							plupload.extend(browseButton.style, {
								zIndex : zIndex
							});

							plupload.extend(inputContainer.style, {
								zIndex : zIndex - 1
							});
						}

						/* Since we have to place input[type=file] on top of the browse_button for some browsers (FF, Opera),
						browse_button loses interactivity, here we try to neutralize this issue highlighting browse_button
						with a special class
						TODO: needs to be revised as things will change */
						hoverClass = up.settings.browse_button_hover;
						activeClass = up.settings.browse_button_active;
						topElement = up.features.triggerDialog ? browseButton : inputContainer;

						if (hoverClass) {
							plupload.addEvent(topElement, 'mouseover', function() {
								plupload.addClass(browseButton, hoverClass);
							}, up.id);
							plupload.addEvent(topElement, 'mouseout', function() {
								plupload.removeClass(browseButton, hoverClass);
							}, up.id);
						}

						if (activeClass) {
							plupload.addEvent(topElement, 'mousedown', function() {
								plupload.addClass(browseButton, activeClass);
							}, up.id);
							plupload.addEvent(document.body, 'mouseup', function() {
								plupload.removeClass(browseButton, activeClass);
							}, up.id);
						}
					}
				});

				// Remove files
				uploader.bind("FilesRemoved", function(up, files) {
					var i, n;

					for (i = 0; i < files.length; i++) {
						n = getById('form_' + files[i].id);
						if (n) {
							n.parentNode.removeChild(n);
						}
					}
				});

				uploader.bind("DisableBrowse", function(up, disabled) {
					var input = document.getElementById('input_' + currentFileId);
					if (input) {
						input.disabled = disabled;
					}
				});

				// Completely destroy the runtime
				uploader.bind("Destroy", function(up) {
					var name, element, form,
						elements = {
							inputContainer: 'form_' + currentFileId,
							inputFile: 'input_' + currentFileId,
							browseButton: up.settings.browse_button
						};

					// Unbind event handlers
					for (name in elements) {
						element = getById(elements[name]);
						if (element) {
							plupload.removeAllEvents(element, up.id);
						}
					}
					plupload.removeAllEvents(document.body, up.id);

					// Remove mark-up
					plupload.each(fileIds, function(id, i) {
						form = getById('form_' + id);
						if (form) {
							container.removeChild(form);
						}
					});

				});

				// Create initial form
				createForm();
			});

			callback({success : true});
		}
	});
})(window, document, plupload);
<|endoftext|>


<commit_before>/**
 * SAHARA Web Interface
 *
 * User interface to Sahara Remote Laboratory system.
 *
 * @license See LICENSE in the top level directory for complete license terms.
 *
 * Copyright (c) 2010, University of Technology, Sydney
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of the University of Technology, Sydney nor the names
 *    of its contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author Michael Diponio (mdiponio)
 * @date 1st August 2010
 */

var io = new Array(8);
var ty = new Array(8);

function uploadBitStream()
{
	var width = $("body").width();
	var height = $("body").height();

	var file = $("#bitstreamuploadformfile").val();

	disableFPGAButtons();
	addFPGAMessage("Started bitstream of file " + file + ".");
	$("#bitstreamuploadform").submit();

	$("#bitstreamupload").dialog('close');

	$("body").append(
		'
' +
		'
' +
		'
' +
			'' +
			'
Programming FPGA...
' +
		'
'
	);

	setTimeout(checkBitstreamPost, 2000);
}

function checkBitstreamPost()
{
	var response = $("#uploadtarget").contents().text();

	if (response == undefined || response == "") // Still waiting for the post response
	{
		setTimeout(checkBitstreamPost, 2000);
		return;
	}
	else if (response == "true") // Correct response
	{
		setTimeout(checkUploadStatus, 2000);
	}
	else // Failed response
	{
		addFPGAMessage('Failed programming FPGA.');

		enableFPGAButtons();
		clearBitstreamUploadOverlay();

		$("#bitstreamuploaderrormessage").html(response.substr(response.indexOf(';') + 2));
		$("#bitstreamuploaderror").css('display', 'block');
		$("#bitstreamupload").dialog('open');
	}
}

function checkUploadStatus()
{
	/* Getting this far means the upload was successful. */
	$("#bitstreamuploaderrormessage").empty();
	$("#bitstreamuploaderror").css('display', 'none');

	$.get(
		'/batch/status',
		null,
		function (data) {
			if (typeof data != "object" || data.state == undefined)
			{
				addFPGAMessage('Failed programming FPGA.');
				enableFPGAButtons();
				clearBitstreamUploadOverlay();
			}

			if (data.state == 'IN_PROGRESS') // Still programming
			{
				setTimeout(checkUploadStatus, 2000);
			}
			else if (data.state == 'FAILED')
			{
				addFPGAMessage('Failed programming FPGA.');
				enableFPGAButtons();
				clearBitstreamUploadOverlay();
			}
			else if (data.state == 'CLEAR' || data.state == 'COMPLETE')
			{
				addFPGAMessage('Finished programming FPGA.');
				enableFPGAButtons();
				clearBitstreamUploadOverlay();
			}
		}
	);
}

function clearBitstreamUploadOverlay()
{
	$(".bitstreamuploadoverlaydialog").remove();
	$(".bitstreamuploadoverlay").remove();
}

function initIO(types)
{
	performPrimitiveJSON('FPGAController', 'getDataByte', null, restoreIO, null);

	for (var i = 0; i < 8; i++)
	{
		io[i] = 0;
		$("#io" + i).css('background-color', '#ED8686');
		ty[i] = types.charAt(i);
	}
}

function restoreIO(resp)
{
	if (typeof resp != "object") return;

	var val = resp.value;

	for (var i = 0; i < 8; i++)
	{
		if (val & Math.pow(2, i))
		{
			io[i] = 1;
			$("#io" + i).css('background-color', '#62E877');
			$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttondown.png' :'switchdown.png'));
		}
	}
}

function setIO(i)
{
	if (io[i] == 0)
	{
		if (ty[i] == 'S') addFPGAMessage("Switch " + (7 - i) + " turned on.");
		else addFPGAMessage("Push button " + (7 - i) + " pressed.");

		io[i] = 1;
		$("#io" + i).css('background-color', '#62E877');
		$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttondown.png' :'switchdown.png'));
	}
	else
	{
		if (ty[i] == 'S') addFPGAMessage("Switch " + (7 - i) + " turned off.");
		else addFPGAMessage("Push button " + (7 - i) + " released.");

		io[i] = 0;
		$("#io" + i).css('background-color', '#ED8686');
		$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttonup.png' :'switchup.png'));
	}

	var val = 0;
	for (var i = 0; i < 8; i++)
	{
		val += io[i] * Math.pow(2, i);
	}

	var params = new Object;
	params.value = val;
	performPrimitiveJSON('FPGAController', 'setDataByte', params);
}

function clearIO(i)
{
	if (io[i] == 0) return;

	io[i] = 0;
	$("#io" + i).css('background-color', '#ED8686');
	$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttonup.png' :'switchup.png'));

	if (ty[i] == 'S') addFPGAMessage("Switch " + (7 - i) + " turned off.");
	else addFPGAMessage("Push button " + (7 - i) + " released.");

	var val = 0;
	for (var i = 0; i < 8; i++)
	{
		val += io[i] * Math.pow(2, i);
	}

	var params = new Object;
	params.value = val;
	performPrimitiveJSON('FPGAController', 'setDataByte', params);
}

function checkDemoLoadedStart()
{
	setTimeout(checkDemoLoaded, 2000);
}

function checkDemoLoaded()
{
	performPrimitiveJSON('FPGAAuxController', 'isDemoUploaded', null, checkDemoLoadedCallback);
}

function checkDemoLoadedCallback(data)
{
	if (typeof data != "object")
	{
		performPrimitiveClearOverlay();
		enableFPGAButtons();
		addFPGAMessage("Loading demonstration program has failed.");
		return;
	}

	if (data.value == 'true')
	{
		performPrimitiveClearOverlay();
		enableFPGAButtons();
		addFPGAMessage("Finished loading demonstration program.");

	}
	else
	{
		setTimeout(checkDemoLoaded, 2000);
	}
}

function softResetCallback()
{
	addFPGAMessage("FPGA has been soft reset.");
	enableFPGAButtons();
}

function hardResetCallback()
{
	addFPGAMessage("FPGA has been power cycled.");
	resetIO();
	addFPGAMessage("Input has been reset.");
	enableFPGAButtons();
}

function resetIO()
{
	for (var i = 0; i < 8; i++)
	{
		io[i] = 0;
		$("#io" + i).css('background-color', '#ED8686');
		$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttonup.png' :'switchup.png'));
	}
}

function enableFPGAButtons()
{
	$(".ioclass").addClass('ui-state-enabled')
		.removeClass('ui-state-disabled');

	$(".resetclass").addClass('ui-state-enabled')
		.removeClass('ui-state-disabled');

	$(".codebuttonclass").addClass('ui-state-enabled')
		.removeClass('ui-state-disabled');

}

function disableFPGAButtons()
{
	$(".ioclass").addClass('ui-state-disabled')
		.removeClass('ui-state-enabled');

	$(".resetclass").addClass('ui-state-disabled')
		.removeClass('ui-state-enabled');

	$(".codebuttonclass").addClass('ui-state-disabled')
		.removeClass('ui-state-enabled');
}

function addFPGAMessage(m)
{
	$("#operationpanellist").prepend("
" + m + "
");
	$("#operationpanellist li:even").removeClass("oplistodd").addClass("oplisteven");
	$("#operationpanellist li:odd").removeClass("oplisteven").addClass("oplistodd");
}<commit_msg>Fixed operations list message.<commit_after>/**
 * SAHARA Web Interface
 *
 * User interface to Sahara Remote Laboratory system.
 *
 * @license See LICENSE in the top level directory for complete license terms.
 *
 * Copyright (c) 2010, University of Technology, Sydney
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of the University of Technology, Sydney nor the names
 *    of its contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author Michael Diponio (mdiponio)
 * @date 1st August 2010
 */

var io = new Array(8);
var ty = new Array(8);

function uploadBitStream()
{
	var width = $("body").width();
	var height = $("body").height();

	var file = $("#bitstreamuploadformfile").val();

	disableFPGAButtons();
	addFPGAMessage("Started programming FPGA with bitstream file " + file + ".");
	$("#bitstreamuploadform").submit();

	$("#bitstreamupload").dialog('close');

	$("body").append(
		'
' +
		'
' +
		'
' +
			'' +
			'
Programming FPGA...
' +
		'
'
	);

	setTimeout(checkBitstreamPost, 2000);
}

function checkBitstreamPost()
{
	var response = $("#uploadtarget").contents().text();

	if (response == undefined || response == "") // Still waiting for the post response
	{
		setTimeout(checkBitstreamPost, 2000);
		return;
	}
	else if (response == "true") // Correct response
	{
		setTimeout(checkUploadStatus, 2000);
	}
	else // Failed response
	{
		addFPGAMessage('Failed programming FPGA.');

		enableFPGAButtons();
		clearBitstreamUploadOverlay();

		$("#bitstreamuploaderrormessage").html(response.substr(response.indexOf(';') + 2));
		$("#bitstreamuploaderror").css('display', 'block');
		$("#bitstreamupload").dialog('open');
	}
}

function checkUploadStatus()
{
	/* Getting this far means the upload was successful. */
	$("#bitstreamuploaderrormessage").empty();
	$("#bitstreamuploaderror").css('display', 'none');

	$.get(
		'/batch/status',
		null,
		function (data) {
			if (typeof data != "object" || data.state == undefined)
			{
				addFPGAMessage('Failed programming FPGA.');
				enableFPGAButtons();
				clearBitstreamUploadOverlay();
			}

			if (data.state == 'IN_PROGRESS') // Still programming
			{
				setTimeout(checkUploadStatus, 2000);
			}
			else if (data.state == 'FAILED')
			{
				addFPGAMessage('Failed programming FPGA.');
				enableFPGAButtons();
				clearBitstreamUploadOverlay();
			}
			else if (data.state == 'CLEAR' || data.state == 'COMPLETE')
			{
				addFPGAMessage('Finished programming FPGA.');
				enableFPGAButtons();
				clearBitstreamUploadOverlay();
			}
		}
	);
}

function clearBitstreamUploadOverlay()
{
	$(".bitstreamuploadoverlaydialog").remove();
	$(".bitstreamuploadoverlay").remove();
}

function initIO(types)
{
	performPrimitiveJSON('FPGAController', 'getDataByte', null, restoreIO, null);

	for (var i = 0; i < 8; i++)
	{
		io[i] = 0;
		$("#io" + i).css('background-color', '#ED8686');
		ty[i] = types.charAt(i);
	}
}

function restoreIO(resp)
{
	if (typeof resp != "object") return;

	var val = resp.value;

	for (var i = 0; i < 8; i++)
	{
		if (val & Math.pow(2, i))
		{
			io[i] = 1;
			$("#io" + i).css('background-color', '#62E877');
			$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttondown.png' :'switchdown.png'));
		}
	}
}

function setIO(i)
{
	if (io[i] == 0)
	{
		if (ty[i] == 'S') addFPGAMessage("Switch " + (7 - i) + " turned on.");
		else addFPGAMessage("Push button " + (7 - i) + " pressed.");

		io[i] = 1;
		$("#io" + i).css('background-color', '#62E877');
		$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttondown.png' :'switchdown.png'));
	}
	else
	{
		if (ty[i] == 'S') addFPGAMessage("Switch " + (7 - i) + " turned off.");
		else addFPGAMessage("Push button " + (7 - i) + " released.");

		io[i] = 0;
		$("#io" + i).css('background-color', '#ED8686');
		$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttonup.png' :'switchup.png'));
	}

	var val = 0;
	for (var i = 0; i < 8; i++)
	{
		val += io[i] * Math.pow(2, i);
	}

	var params = new Object;
	params.value = val;
	performPrimitiveJSON('FPGAController', 'setDataByte', params);
}

function clearIO(i)
{
	if (io[i] == 0) return;

	io[i] = 0;
	$("#io" + i).css('background-color', '#ED8686');
	$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttonup.png' :'switchup.png'));

	if (ty[i] == 'S') addFPGAMessage("Switch " + (7 - i) + " turned off.");
	else addFPGAMessage("Push button " + (7 - i) + " released.");

	var val = 0;
	for (var i = 0; i < 8; i++)
	{
		val += io[i] * Math.pow(2, i);
	}

	var params = new Object;
	params.value = val;
	performPrimitiveJSON('FPGAController', 'setDataByte', params);
}

function checkDemoLoadedStart()
{
	setTimeout(checkDemoLoaded, 2000);
}

function checkDemoLoaded()
{
	performPrimitiveJSON('FPGAAuxController', 'isDemoUploaded', null, checkDemoLoadedCallback);
}

function checkDemoLoadedCallback(data)
{
	if (typeof data != "object")
	{
		performPrimitiveClearOverlay();
		enableFPGAButtons();
		addFPGAMessage("Loading demonstration program has failed.");
		return;
	}

	if (data.value == 'true')
	{
		performPrimitiveClearOverlay();
		enableFPGAButtons();
		addFPGAMessage("Finished loading demonstration program.");

	}
	else
	{
		setTimeout(checkDemoLoaded, 2000);
	}
}

function softResetCallback()
{
	addFPGAMessage("FPGA has been soft reset.");
	enableFPGAButtons();
}

function hardResetCallback()
{
	addFPGAMessage("FPGA has been power cycled.");
	resetIO();
	addFPGAMessage("Input has been reset.");
	enableFPGAButtons();
}

function resetIO()
{
	for (var i = 0; i < 8; i++)
	{
		io[i] = 0;
		$("#io" + i).css('background-color', '#ED8686');
		$("#io" + i + " img").attr('src', '/uts/fpga/images/' + (ty[i] == 'P' ? 'pushbuttonup.png' :'switchup.png'));
	}
}

function enableFPGAButtons()
{
	$(".ioclass").addClass('ui-state-enabled')
		.removeClass('ui-state-disabled');

	$(".resetclass").addClass('ui-state-enabled')
		.removeClass('ui-state-disabled');

	$(".codebuttonclass").addClass('ui-state-enabled')
		.removeClass('ui-state-disabled');

}

function disableFPGAButtons()
{
	$(".ioclass").addClass('ui-state-disabled')
		.removeClass('ui-state-enabled');

	$(".resetclass").addClass('ui-state-disabled')
		.removeClass('ui-state-enabled');

	$(".codebuttonclass").addClass('ui-state-disabled')
		.removeClass('ui-state-enabled');
}

function addFPGAMessage(m)
{
	$("#operationpanellist").prepend("
" + m + "
");
	$("#operationpanellist li:even").removeClass("oplistodd").addClass("oplisteven");
	$("#operationpanellist li:odd").removeClass("oplisteven").addClass("oplistodd");
}<|endoftext|>


<commit_before>/*
 * Copyrights phwang
 * Written by Paul Hwang
 * File name: fabric_cluster_mgr.js
 */

var the_fabric_cluster_mgr_object = null;

module.exports = {
    malloc: function (root_object_val) {
        the_fabric_cluster_mgr_object = new FabricClusterMgrClass(root_object_val);
        return the_fabric_cluster_mgr_object;
    },

    receive_data: function (cluster_object_val, data_val) {
        the_fabric_cluster_mgr_object.receiveData(cluster_object_val, data_val);
    },
};

function FabricClusterMgrClass(root_object_val) {
    "use strict";

    this.init__ = function (root_object_val) {
        this.theRootObject = root_object_val;
        this.debug(true, "init__", "");
    };

    this.objectName = function () {
        return "FabricClusterMgrClass";
    };

    this.rootObject = function () {
        return this.theRootObject;
    };

    this.utilObject = function () {
        return this.rootObject().utilObject();
    };

    this.clusterRootObject = function () {
        return this.rootObject().clusterRootObject();
    };

    this.mallocCluster = function (data_val, session_val) {
        var cluster = require("./fabric_cluster.js").malloc(this.rootObject(), data_val, session_val);
        cluster.setGroupObject(require("../matrix_modules/matrix_group_mgr.js").malloc_group(data_val, cluster));
        return cluster;
    };

    this.receiveData = function (cluster_object_val, data_val) {
        cluster_object_val.receiveData(data_val);
    };

    this.debug = function (debug_val, str1_val, str2_val) {
        if (debug_val) {
            this.logit(str1_val, str2_val);
        }
    };

    this.logit = function (str1_val, str2_val) {
        this.rootObject().LOG_IT(this.objectName() + "." + str1_val, str2_val);
    };

    this.abend = function (str1_val, str2_val) {
        this.rootObject().ABEND(this.objectName() + "." + str1_val, str2_val);
    };

    this.init__(root_object_val);
}

<commit_msg>cluster<commit_after>/*
 * Copyrights phwang
 * Written by Paul Hwang
 * File name: fabric_cluster_mgr.js
 */

var the_fabric_cluster_mgr_object = null;

module.exports = {
    malloc: function (root_object_val) {
        the_fabric_cluster_mgr_object = new FabricClusterMgrClass(root_object_val);
        return the_fabric_cluster_mgr_object;
    },

    receive_data: function (cluster_object_val, data_val) {
        the_fabric_cluster_mgr_object.receiveData(cluster_object_val, data_val);
    },
};

function FabricClusterMgrClass(root_object_val) {
    "use strict";

    this.init__ = function (root_object_val) {
        this.theRootObject = root_object_val;
        this.debug(true, "init__", "");
    };

    this.objectName = function () {
        return "FabricClusterMgrClass";
    };

    this.rootObject = function () {
        return this.theRootObject;
    };

    this.utilObject = function () {
        return this.rootObject().utilObject();
    };

    this.importObject = function () {
        return this.rootObject().importObject();
    };

    this.mallocCluster = function (data_val, session_val) {
        var cluster = require("./fabric_cluster.js").malloc(this.rootObject(), data_val, session_val);
        cluster.setGroupObject(require("../matrix_modules/matrix_group_mgr.js").malloc_group(data_val, cluster));
        return cluster;
    };

    this.receiveData = function (cluster_object_val, data_val) {
        cluster_object_val.receiveData(data_val);
    };

    this.debug = function (debug_val, str1_val, str2_val) {
        if (debug_val) {
            this.logit(str1_val, str2_val);
        }
    };

    this.logit = function (str1_val, str2_val) {
        this.rootObject().LOG_IT(this.objectName() + "." + str1_val, str2_val);
    };

    this.abend = function (str1_val, str2_val) {
        this.rootObject().ABEND(this.objectName() + "." + str1_val, str2_val);
    };

    this.init__(root_object_val);
}

<|endoftext|>


<commit_before>// Defines certificate documents on business process certificates map

'use strict';

var ensureArray        = require('es5-ext/array/valid-array')
  , uncapitalize       = require('es5-ext/string/#/uncapitalize')
  , ensureType         = require('dbjs/valid-dbjs-type')
  , defineDocument     = require('../../document')
  , defineCertificates = require('../certificates');

module.exports = function (BusinessProcess, documentClasses) {
	var db = ensureType(BusinessProcess).database, Document = defineDocument(db), definitions = {};
	defineCertificates(db);
	ensureArray(documentClasses).forEach(function (CertificateDocument) {
		if (!Document.isPrototypeOf(ensureType(CertificateDocument))) {
			throw new TypeError(CertificateDocument.__id__ + " must extend Document.");
		}
		definitions[uncapitalize.call(CertificateDocument.__id__)] = {
			nested: true,
			type: CertificateDocument
		};
	});
	BusinessProcess.prototype.certificates.map.defineProperties(definitions);
	return BusinessProcess;
};
<commit_msg>Issue #995. Made define-certificates util to set custom name.<commit_after>// Defines certificate documents on business process certificates map

'use strict';

var ensureArray         = require('es5-ext/array/valid-array')
  , ensureObject        = require('es5-ext/object/valid-object')
  , ensureStringifiable = require('es5-ext/object/validate-stringifiable-value')
  , ensureType          = require('dbjs/valid-dbjs-type')
  , isType              = require('dbjs/is-dbjs-type')
  , uncapitalize        = require('es5-ext/string/#/uncapitalize')
  , endsWith            = require('es5-ext/string/#/ends-with')
  , defineDocument      = require('../../document')
  , defineCertificates  = require('../certificates');

module.exports = function (BusinessProcess, data) {
	var db          = ensureType(BusinessProcess).database
	  , Document    = defineDocument(db)
	  , definitions = {};

	defineCertificates(db);

	ensureArray(data).forEach(function (conf) {
		var CertificateDocument, name;

		if (!isType(ensureObject(conf))) {
			CertificateDocument = ensureType(conf.class);

			if (conf.name) name = ensureStringifiable(conf.name);
		} else {
			CertificateDocument = conf;
		}

		if (!Document.isPrototypeOf(ensureType(CertificateDocument))) {
			throw new TypeError(CertificateDocument.__id__ + " must extend Document.");
		}

		if (!name) {
			name = uncapitalize.call(CertificateDocument.__id__);

			if (endsWith.call(name, 'Certificate')) {
				name = uncapitalize.call(CertificateDocument.__id__).slice(0, -'Certificate'.length);
			}
		}

		definitions[name] = {
			nested: true,
			type: CertificateDocument
		};
	});

	BusinessProcess.prototype.certificates.map.defineProperties(definitions);
	return BusinessProcess;
};
<|endoftext|>


<commit_before>/*
	客户访问网站 "visitTime" 秒后弹出邀请窗
	客户拒绝邀请后，间隔 "intervalTime" 秒再次弹出邀请窗, 不填则拒绝后不再邀请
	同一页面单日最大邀请次数 "maxInvitation"
*/

var utils = require("@/common/utils");
var eventListener = require("@/app/tools/eventListener");
var _const = require("@/common/const");
var moment = require("moment");
var cr = require("@/common/crypto");

module.exports = function(info, config){
	var timer;
	var dayTimer;
	var endDaySecond;
	var inviteBox = document.createElement("div");
	var secret = "AUTOINVITATION"; // 加密解密密钥
	var encryptMaxInvitation;
	if(info.style.icon === "auto_invite_logo.png"){
		info.style.icon = config.domain + "/webim/static/img/" + info.style.icon;
	}
	inviteBox.className = utils.isMobile
		? "easemob-invite-box easemob-mobile-invite-box"
		: "easemob-invite-box";
	inviteBox.innerHTML = "
" +
						"
" +
					"×" +
					"
" +
						info.style.guide +
					"
" +
					"
" +
						info.style.button;
	"
";
	document.body.appendChild(inviteBox);
	setLocalStorage("visitTime", info.rule.visitTime);
	encryptMaxInvitation = setLocalStorage("maxInvitation", info.rule.maxInvitation);

	utils.live(".invite-cancel", "click", onCancelClick, inviteBox);
	utils.live(".invite-accept", "click", onAcceptClick, inviteBox);

	function onCancelClick(){
		var maxInvitation = getLocalStorage(encryptMaxInvitation);
		hide();
		if(maxInvitation > 1){
			setLocalStorage("maxInvitation", maxInvitation - 1);
			// intervalTime 不填则拒绝后不再邀请
			info.rule.intervalTime >= 0 && startTimer(info.rule.intervalTime);
		}
		else{
			clearTimer();
		}
	}

	function startTimer(second){
		timer = setTimeout(function(){
			show();
			clearTimeout(timer);
		}, second * 1000);
	}

	function clearTimer(){
		clearTimeout(timer);
	}

	function beginStartTimer(){
		startTimer(info.rule.visitTime);
		startDayTimer();
	}

	// 开启单日最大邀请次数的计时
	function startDayTimer(){
		// moment().endOf('day') 当前日期的 23:59:59
		endDaySecond = moment().endOf("day") - moment();
		dayTimer = setTimeout(function(){
			clearTimeout(dayTimer);
			// 一天结束后重新将“单日最大邀请次数” 设置到 localStorage
			setLocalStorage("maxInvitation", info.rule.maxInvitation);
			startTimer(info.rule.visitTime);
			startDayTimer();
		}, endDaySecond);
	}

	function cleartDayTimer(){
		clearTimeout(dayTimer);
	}

	function onAcceptClick(){
		// 点击接受就清除单日最大邀请次数的计时
		cleartDayTimer();
		eventListener.trigger(_const.SYSTEM_EVENT.ACCEPT_INVITATION);
		hide();
	}

	function setLocalStorage(key, val){
		var encryptionKey = cr.encrypt(key, secret);
		var encryptionVal = cr.encrypt(val, secret);
		window.localStorage && localStorage.setItem(encryptionKey, encryptionVal);
		return encryptionKey;
	}

	function getLocalStorage(encrypVal){
		var decryptVal = localStorage.getItem(encrypVal)
			? cr.decrypt(localStorage.getItem(encrypVal), secret)
			: "";
		return decryptVal;
	}

	function show(){
		inviteBox.style.display = "block";
	}

	function hide(){
		inviteBox.style.display = "none";
	}

	return {
		beginStartTimer: beginStartTimer,
		clearInvitation: function(){
			hide();
			clearTimeout(timer);
			clearTimeout(dayTimer);
		},
	};
};
<commit_msg>intervalTime 不填则拒绝后不再邀请<commit_after>/*
	客户访问网站 "visitTime" 秒后弹出邀请窗
	客户拒绝邀请后，间隔 "intervalTime" 秒再次弹出邀请窗, 不填则拒绝后不再邀请
	同一页面单日最大邀请次数 "maxInvitation"
*/

var utils = require("@/common/utils");
var eventListener = require("@/app/tools/eventListener");
var _const = require("@/common/const");
var moment = require("moment");
var cr = require("@/common/crypto");

module.exports = function(info, config){
	var timer;
	var dayTimer;
	var endDaySecond;
	var inviteBox = document.createElement("div");
	var secret = "AUTOINVITATION"; // 加密解密密钥
	var encryptMaxInvitation;
	if(info.style.icon === "auto_invite_logo.png"){
		info.style.icon = config.domain + "/webim/static/img/" + info.style.icon;
	}
	inviteBox.className = utils.isMobile
		? "easemob-invite-box easemob-mobile-invite-box"
		: "easemob-invite-box";
	inviteBox.innerHTML = "
" +
						"
" +
					"×" +
					"
" +
						info.style.guide +
					"
" +
					"
" +
						info.style.button;
	"
";
	document.body.appendChild(inviteBox);
	setLocalStorage("visitTime", info.rule.visitTime);
	encryptMaxInvitation = setLocalStorage("maxInvitation", info.rule.maxInvitation);

	utils.live(".invite-cancel", "click", onCancelClick, inviteBox);
	utils.live(".invite-accept", "click", onAcceptClick, inviteBox);

	function onCancelClick(){
		var maxInvitation = getLocalStorage(encryptMaxInvitation);
		hide();
		if(maxInvitation > 1){
			setLocalStorage("maxInvitation", maxInvitation - 1);
			// intervalTime 不填则拒绝后不再邀请
			(info.rule.intervalTime != "" && info.rule.intervalTime >= 0) && startTimer(info.rule.intervalTime);
		}
		else{
			clearTimer();
		}
	}

	function startTimer(second){
		timer = setTimeout(function(){
			show();
			clearTimeout(timer);
		}, second * 1000);
	}

	function clearTimer(){
		clearTimeout(timer);
	}

	function beginStartTimer(){
		startTimer(info.rule.visitTime);
		startDayTimer();
	}

	// 开启单日最大邀请次数的计时
	function startDayTimer(){
		// moment().endOf('day') 当前日期的 23:59:59
		endDaySecond = moment().endOf("day") - moment();
		dayTimer = setTimeout(function(){
			clearTimeout(dayTimer);
			// 一天结束后重新将“单日最大邀请次数” 设置到 localStorage
			setLocalStorage("maxInvitation", info.rule.maxInvitation);
			startTimer(info.rule.visitTime);
			startDayTimer();
		}, endDaySecond);
	}

	function cleartDayTimer(){
		clearTimeout(dayTimer);
	}

	function onAcceptClick(){
		// 点击接受就清除单日最大邀请次数的计时
		cleartDayTimer();
		eventListener.trigger(_const.SYSTEM_EVENT.ACCEPT_INVITATION);
		hide();
	}

	function setLocalStorage(key, val){
		var encryptionKey = cr.encrypt(key, secret);
		var encryptionVal = cr.encrypt(val, secret);
		window.localStorage && localStorage.setItem(encryptionKey, encryptionVal);
		return encryptionKey;
	}

	function getLocalStorage(encrypVal){
		var decryptVal = localStorage.getItem(encrypVal)
			? cr.decrypt(localStorage.getItem(encrypVal), secret)
			: "";
		return decryptVal;
	}

	function show(){
		inviteBox.style.display = "block";
	}

	function hide(){
		inviteBox.style.display = "none";
	}

	return {
		beginStartTimer: beginStartTimer,
		clearInvitation: function(){
			hide();
			clearTimeout(timer);
			clearTimeout(dayTimer);
		},
	};
};
<|endoftext|>


<commit_before>var webpackConfig = require('./webpack.config.js');

// Add istanbul-instrumenter to webpack configuration
webpackConfig.module.loaders.push(
    {
        test: /\.js$/,
        exclude: /(node_modules|test)/,
        loader: 'babel-istanbul-loader'
    }
);

// The main configuration
var configuration = function(config) {
    config.set({
        frameworks: [
            'jasmine-jquery',
            'jasmine-ajax',
            'jasmine'
        ],

        files: [
            'test/*.spec.js',
        ],

        preprocessors: {
            'test/*.spec.js': [
                'webpack'
            ],
        },

        coverageReporter: {
            dir: 'build/reports/coverage',
        },

        webpack: webpackConfig,

        webpackMiddleware: {
            noInfo: true
        },

        reporters: ['spec', 'coverage'],

        browsers: ['Chrome'],

        customLaunchers: {
            Chrome_travis_ci: {
                base: 'Chrome',
                flags: ['--no-sandbox']
            }
        },
    });
}

if (process.env.TRAVIS) {
    configuration.browsers = ['Chrome_travis_ci'];

    console.log(configuration.browsers);
}

module.exports = configuration;
<commit_msg>Add firefox again<commit_after>var webpackConfig = require('./webpack.config.js');

// Add istanbul-instrumenter to webpack configuration
webpackConfig.module.loaders.push(
    {
        test: /\.js$/,
        exclude: /(node_modules|test)/,
        loader: 'babel-istanbul-loader'
    }
);

// The main configuration
var configuration = function(config) {
    config.set({
        frameworks: [
            'jasmine-jquery',
            'jasmine-ajax',
            'jasmine'
        ],

        files: [
            'test/*.spec.js',
        ],

        preprocessors: {
            'test/*.spec.js': [
                'webpack'
            ],
        },

        coverageReporter: {
            dir: 'build/reports/coverage',
        },

        webpack: webpackConfig,

        webpackMiddleware: {
            noInfo: true
        },

        reporters: ['spec', 'coverage'],

        browsers: ['Chrome', 'Firefox'],

        customLaunchers: {
            Chrome_travis_ci: {
                base: 'Chrome',
                flags: ['--no-sandbox']
            }
        },
    });
}

if (process.env.TRAVIS) {
    configuration.browsers = ['Chrome_travis_ci'];

    console.log(configuration.browsers);
}

module.exports = configuration;
<|endoftext|>