<commit_before>import React from 'react';
import Markdown from './markdown';
import m from '../lib/markdown-insert';

var NOOP = Function.prototype;

export default class MarkdownEditor extends React.Component {
    get displayName() {
        return 'MarkdownEditor';
    }

    onInsertLinkClick() {
        this.wrapSelectionIn(m.hrefLink);
    }

    onInsertImageClick() {
        this.wrapSelectionIn(m.imageLink);
    }

    onBoldClick() {
        this.wrapSelectionIn(m.bold);
    }

    onItalicClick() {
        this.wrapSelectionIn(m.italic);
    }

    onHeadingClick() {
        this.wrapSelectionIn(m.heading, {ensureNewLine: true});
    }

    onQuoteClick() {
        this.wrapSelectionIn(m.quote, {ensureNewLine: true});
    }

    onHorizontalRuleClick() {
        this.wrapSelectionIn(m.horizontalRule, {ensureNewLine: true});
    }

    onStrikethroughClick() {
        this.wrapSelectionIn(m.strikethrough);
    }

    onBulletClick() {
        this.wrapLinesIn(m.bullet, {ensureNewLine: true});
    }

    onNumberClick() {
        this.wrapLinesIn(m.numberedList, {ensureNewLine: true, incrementLines: true});
    }

    componentWillMount() {
        this.setState({previewing: !!this.props.previewing});
    }

    render() {
        var previewIcon;
        if (this.state.previewing) {
            previewIcon = ;
        }
        else {
            previewIcon = ;
        }

        return (
                <div className={`markdown-editor ${this.props.className}`} data-previewing={this.state.previewing || null}>

                        <button type="button" title="link"className='talk-comment-insert-link-button' onClick={this.onInsertLinkClick.bind(this)}>

                        </button>
                        <button type="button" title="image" className='talk-comment-insert-image-button' onClick={this.onInsertImageClick.bind(this)}>

                        </button>
                        <button type="button" title="bold" className='talk-comment-bold-button' onClick={this.onBoldClick.bind(this)}>

                        </button>
                        <button type="button" title="italic" className='talk-comment-italic-button' onClick={this.onItalicClick.bind(this)}>

                        </button>
                        <button type="button" title="block quote" className='talk-comment-insert-quote-button' onClick={this.onQuoteClick.bind(this)}>

                        </button>
                        <button type="button" title="heading" className='talk-comment-heading-button' onClick={this.onHeadingClick.bind(this)}>

                        </button>
                        <button type="button" title="horizontal rule" className='talk-comment-hr-button' onClick={this.onHorizontalRuleClick.bind(this)}>

                        </button>
                        <button type="button" title="strikethrough" className='talk-comment-strikethrough-button' onClick={this.onStrikethroughClick.bind(this)}>

                        </button>
                        <button type="button" title="bulleted list" className='talk-comment-bullet-button' onClick={this.onBulletClick.bind(this)}>

                        </button>
                        <button type="button" title="numbered list" className='talk-comment-number-button' onClick={this.onNumberClick.bind(this)}>

                        </button>

                            <button title="preview" type="button" onClick={this.handlePreviewToggle.bind(this)}>
                                {previewIcon}
                            </button>

                            <button title="help" type="button" onClick={this.handleHelpRequest.bind(this)}>

                            </button>

                        <textarea ref="textarea" className="markdown-editor-input" name={this.props.name} placeholder={this.props.placeholder} value={this.props.value} rows={this.props.rows} cols={this.props.cols} onChange={this.onInputChange.bind(this)} />

                        <Markdown className="markdown-editor-preview" transform={this.props.transform}>{this.props.value}</Markdown>

        );
    }

    onInputChange(e) {
        if (this.props.onChange) {
            var value;
            if (e && e.target && e.target.value) {
                value = e.target.value;
            }
            else {
                value = this.refs.textarea.getDOMNode().value;
            }
            var event = {
                target: {
                    name: this.props.name,
                    value: value,
                    type: 'textarea',
                    dataset: {}
                }
            };
            this.props.onChange(event);
        }
    }

    handlePreviewToggle() {
        this.setState({previewing: !this.state.previewing});
    }

    handleHelpRequest(e) {
        this.props.onHelp(e);
    }

    wrapSelectionIn(wrapFn, opts = {}) {
        // helper to call markdown-insert functions on the textarea
        // wrapFn takes / returns a string (from ./lib/markdown-insert.cjsx)

        var textarea = this.refs.textarea.getDOMNode(),
            selection = m.getSelection(textarea),
            text,cursor;

        ({text, cursor} = wrapFn(selection));

        m.insertAtCursor(text, textarea, cursor, opts);
        this.onInputChange();
    }

    wrapLinesIn(wrapFn, opts = {}) {
        var textarea = this.refs.textarea.getDOMNode();
        var lines = m.getSelection(textarea).split("\n");

        var formattedText = lines
                .map((line) => wrapFn(line).text)
                .join("\n");

        // increment the line numbers in a list, if that option is specified
        if (opts.incrementLines && opts.ensureNewLine) {
            var begInputValue = textarea.value.substring(0, textarea.selectionStart) + "\n";
            formattedText = m.incrementedListItems(begInputValue, formattedText);
        }

        var cursor = {start: formattedText.length, end: formattedText.length};

        m.insertAtCursor(formattedText, textarea, cursor, opts);
        this.onInputChange();
    }
};

MarkdownEditor.defaultProps = {
    name: '',
    value: '',
    placeholder: '',
    rows: 5,
    transform: arg => arg,
    onChange: NOOP,
    previewing: null,
    onHelp: NOOP
};

MarkdownEditor.initialState = {
    previewing: false
};
<commit_msg>Use replaceSymbols as default transform of editor<commit_after>import React from 'react';
import Markdown from './markdown';
import m from '../lib/markdown-insert';
import replaceSymbols from '../lib/default-transformer';

var NOOP = Function.prototype;

export default class MarkdownEditor extends React.Component {
    get displayName() {
        return 'MarkdownEditor';
    }

    onInsertLinkClick() {
        this.wrapSelectionIn(m.hrefLink);
    }

    onInsertImageClick() {
        this.wrapSelectionIn(m.imageLink);
    }

    onBoldClick() {
        this.wrapSelectionIn(m.bold);
    }

    onItalicClick() {
        this.wrapSelectionIn(m.italic);
    }

    onHeadingClick() {
        this.wrapSelectionIn(m.heading, {ensureNewLine: true});
    }

    onQuoteClick() {
        this.wrapSelectionIn(m.quote, {ensureNewLine: true});
    }

    onHorizontalRuleClick() {
        this.wrapSelectionIn(m.horizontalRule, {ensureNewLine: true});
    }

    onStrikethroughClick() {
        this.wrapSelectionIn(m.strikethrough);
    }

    onBulletClick() {
        this.wrapLinesIn(m.bullet, {ensureNewLine: true});
    }

    onNumberClick() {
        this.wrapLinesIn(m.numberedList, {ensureNewLine: true, incrementLines: true});
    }

    componentWillMount() {
        this.setState({previewing: !!this.props.previewing});
    }

    render() {
        var previewIcon;
        if (this.state.previewing) {
            previewIcon = ;
        }
        else {
            previewIcon = ;
        }

        return (
                <div className={`markdown-editor ${this.props.className}`} data-previewing={this.state.previewing || null}>

                        <button type="button" title="link"className='talk-comment-insert-link-button' onClick={this.onInsertLinkClick.bind(this)}>

                        </button>
                        <button type="button" title="image" className='talk-comment-insert-image-button' onClick={this.onInsertImageClick.bind(this)}>

                        </button>
                        <button type="button" title="bold" className='talk-comment-bold-button' onClick={this.onBoldClick.bind(this)}>

                        </button>
                        <button type="button" title="italic" className='talk-comment-italic-button' onClick={this.onItalicClick.bind(this)}>

                        </button>
                        <button type="button" title="block quote" className='talk-comment-insert-quote-button' onClick={this.onQuoteClick.bind(this)}>

                        </button>
                        <button type="button" title="heading" className='talk-comment-heading-button' onClick={this.onHeadingClick.bind(this)}>

                        </button>
                        <button type="button" title="horizontal rule" className='talk-comment-hr-button' onClick={this.onHorizontalRuleClick.bind(this)}>

                        </button>
                        <button type="button" title="strikethrough" className='talk-comment-strikethrough-button' onClick={this.onStrikethroughClick.bind(this)}>

                        </button>
                        <button type="button" title="bulleted list" className='talk-comment-bullet-button' onClick={this.onBulletClick.bind(this)}>

                        </button>
                        <button type="button" title="numbered list" className='talk-comment-number-button' onClick={this.onNumberClick.bind(this)}>

                        </button>

                            <button title="preview" type="button" onClick={this.handlePreviewToggle.bind(this)}>
                                {previewIcon}
                            </button>

                            <button title="help" type="button" onClick={this.handleHelpRequest.bind(this)}>

                            </button>

                        <textarea ref="textarea" className="markdown-editor-input" name={this.props.name} placeholder={this.props.placeholder} value={this.props.value} rows={this.props.rows} cols={this.props.cols} onChange={this.onInputChange.bind(this)} />

                        <Markdown className="markdown-editor-preview" project={this.props.project} baseURI={this.props.baseURI} transform={this.props.transform}>{this.props.value}</Markdown>

        );
    }

    onInputChange(e) {
        if (this.props.onChange) {
            var value;
            if (e && e.target && e.target.value) {
                value = e.target.value;
            }
            else {
                value = this.refs.textarea.getDOMNode().value;
            }
            var event = {
                target: {
                    name: this.props.name,
                    value: value,
                    type: 'textarea',
                    dataset: {}
                }
            };
            this.props.onChange(event);
        }
    }

    handlePreviewToggle() {
        this.setState({previewing: !this.state.previewing});
    }

    handleHelpRequest(e) {
        this.props.onHelp(e);
    }

    wrapSelectionIn(wrapFn, opts = {}) {
        // helper to call markdown-insert functions on the textarea
        // wrapFn takes / returns a string (from ./lib/markdown-insert.cjsx)

        var textarea = this.refs.textarea.getDOMNode(),
            selection = m.getSelection(textarea),
            text,cursor;

        ({text, cursor} = wrapFn(selection));

        m.insertAtCursor(text, textarea, cursor, opts);
        this.onInputChange();
    }

    wrapLinesIn(wrapFn, opts = {}) {
        var textarea = this.refs.textarea.getDOMNode();
        var lines = m.getSelection(textarea).split("\n");

        var formattedText = lines
                .map((line) => wrapFn(line).text)
                .join("\n");

        // increment the line numbers in a list, if that option is specified
        if (opts.incrementLines && opts.ensureNewLine) {
            var begInputValue = textarea.value.substring(0, textarea.selectionStart) + "\n";
            formattedText = m.incrementedListItems(begInputValue, formattedText);
        }

        var cursor = {start: formattedText.length, end: formattedText.length};

        m.insertAtCursor(formattedText, textarea, cursor, opts);
        this.onInputChange();
    }
};

MarkdownEditor.defaultProps = {
    name: '',
    value: '',
    placeholder: '',
    rows: 5,
    transform: replaceSymbols,
    onChange: NOOP,
    previewing: null,
    onHelp: NOOP,
    project: null,
    baseURI: null
};

MarkdownEditor.initialState = {
    previewing: false
};
<|endoftext|>


<commit_before>import React from 'react';
import styled from 'styled-components';

import {sizes} from '../constants';

import logo from '../img/logo_white.svg';
import imec from '../img/logo_imec.svg';

const Wrapper = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5%;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: ${sizes.icons.height};
  box-sizing: border-box;
  transform: translateY(-0.5em);
`;

const Logo = styled.img`
  height: 100%;
  margin: 0.4em;
`;

// const Link = styled.a`
//   color: inherit;
//   text-decoration: none;
// `;

// const Text = styled.p`
//   margin: 0;
// `;

export default () => {
  return (
    <Wrapper>
      <Logo src={logo} alt="iRail" />
      <Logo src={imec} alt="IMEC" />
    </Wrapper>
  );
}
<commit_msg>removed commented code<commit_after>import React from 'react';
import styled from 'styled-components';

import {sizes} from '../constants';

import logo from '../img/logo_white.svg';
import imec from '../img/logo_imec.svg';

const Wrapper = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5%;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: ${sizes.icons.height};
  box-sizing: border-box;
  transform: translateY(-0.5em);
`;

const Logo = styled.img`
  height: 100%;
  margin: 0.4em;
`;

export default () => {
  return (
    <Wrapper>
      <Logo src={logo} alt="iRail" />
      <Logo src={imec} alt="IMEC" />
    </Wrapper>
  );
}
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { Modal } from 'react-overlays'

function Overlay ({ children, show, onLeave, className, ...props }) {
  const stopPropagation = (e) => {
    e.stopPropagation()
    e.nativeEvent.stopImmediatePropagation()

    if (e.key === 'Escape') {
      onLeave()
    }
  }

  return (
    <Modal
      {...props}
      show={show}
      className={`${className} fixed top-0 left-0 right-0 bottom-0 z-max flex items-center justify-around`}
      backdropClassName='fixed top-0 left-0 right-0 bottom-0 bg-black o-50'
      onKeyDown={stopPropagation}
      onBackdropClick={onLeave}>
      {children}
    </Modal>
  )
}

Overlay.propTypes = {
  show: PropTypes.bool.isRequired,
  onLeave: PropTypes.func.isRequired
}

Overlay.defaultProps = {
  className: ''
}

export default Overlay
<commit_msg>fix: modal backdrop (#1087)<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { Modal } from 'react-overlays'

function Overlay ({ children, show, onLeave, className, ...props }) {
  const stopPropagation = (e) => {
    e.stopPropagation()
    e.nativeEvent.stopImmediatePropagation()

    if (e.key === 'Escape') {
      onLeave()
    }
  }

  const renderBackdrop = (props) => (
    <div className='fixed top-0 left-0 right-0 bottom-0 bg-black o-50' {...props} />
  )

  return (
    <Modal
      {...props}
      show={show}
      className={`${className} fixed top-0 left-0 right-0 bottom-0 z-max flex items-center justify-around`}
      renderBackdrop={renderBackdrop}
      onKeyDown={stopPropagation}
      onBackdropClick={onLeave}>
      {children}
    </Modal>
  )
}

Overlay.propTypes = {
  show: PropTypes.bool.isRequired,
  onLeave: PropTypes.func.isRequired
}

Overlay.defaultProps = {
  className: ''
}

export default Overlay
<|endoftext|>


<commit_before>import React, { createRef, PureComponent } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from 'prop-types';
import cx from 'classnames';
import throttle from 'lodash.throttle';
import InjectOverlay from '../overlay';
import Transition from 'react-transition-group/Transition';
import ReactResizeDetector from 'react-resize-detector';
import { events } from '../utils';
import { calculatePositions } from './positionCalculation';
import { getMaxHeight } from './sizeCalculation';
import Box from '../box';
import theme from './theme.css';
import uiUtilities from '@teamleader/ui-utilities';

class Popover extends PureComponent {
  popoverNode = createRef();
  popoverRoot = document.createElement('div');

  state = { positioning: { left: 0, top: 0, maxHeight: 'initial' } };

  componentDidMount() {
    document.body.appendChild(this.popoverRoot);
    events.addEventsToWindow({ resize: this.setPlacementThrottled, scroll: this.setPlacementThrottled });
  }

  componentWillUnmount() {
    events.removeEventsFromWindow({ resize: this.setPlacementThrottled, scroll: this.setPlacementThrottled });
    document.body.removeChild(this.popoverRoot);
  }

  componentDidUpdate(prevProps) {
    if (this.props.active && prevProps !== this.props) {
      this.setPlacement();
    }
  }

  setPlacement = () => {
    const { anchorEl, direction, position, offsetCorrection } = this.props;

    if (this.popoverNode.current) {
      this.setState({
        positioning: calculatePositions(anchorEl, this.popoverNode.current, direction, position, offsetCorrection),
      });
    }
  };

  setPlacementThrottled = throttle(this.setPlacement, 250);

  render() {
    const { left, top, maxHeight } = this.state.positioning;

    const {
      active,
      backdrop,
      children,
      className,
      color,
      fullHeight,
      fullWidth,
      lockScroll,
      minWidth,
      onOverlayClick,
      onEscKeyDown,
      onOverlayMouseDown,
      onOverlayMouseMove,
      onOverlayMouseUp,
      tint,
      zIndex,
    } = this.props;

    if (!active) {
      return null;
    }

    const popover = (
      <Transition timeout={0} in={active} appear>
        {state => {
          return (
            <div
              className={cx(theme['wrapper'], theme[color], theme[tint], {
                [theme['is-entering']]: state === 'entering',
                [theme['is-entered']]: state === 'entered',
              })}
              style={{ zIndex }}
            >
              <InjectOverlay
                active={active}
                backdrop={backdrop}
                className={theme['overlay']}
                lockScroll={lockScroll}
                onClick={onOverlayClick}
                onEscKeyDown={onEscKeyDown}
                onMouseDown={onOverlayMouseDown}
                onMouseMove={onOverlayMouseMove}
                onMouseUp={onOverlayMouseUp}
              />
              <div
                data-teamleader-ui={'popover'}
                className={cx(uiUtilities['box-shadow-200'], theme['popover'], className)}
                style={{ left: `${left}px`, top: `${top}px`, maxWidth: fullWidth ? '100vw' : '50vw', minWidth }}
                ref={this.popoverNode}
              >
                <Box
                  className={theme['inner']}
                  display="flex"
                  flex="1 1 auto"
                  flexDirection="column"
                  style={{ maxHeight: getMaxHeight(fullHeight, maxHeight) }}
                >
                  {children}
                </Box>
                <ReactResizeDetector
                  handleHeight
                  handleWidth
                  onResize={this.setPlacement}
                  refreshMode="throttle"
                  refreshRate={250}
                />
              </div>
            </div>
          );
        }}
      </Transition>
    );

    return createPortal(popover, this.popoverRoot);
  }
}

Popover.propTypes = {
  /** The state of the Popover, when true the Popover is rendered otherwise it is not. */
  active: PropTypes.bool,
  /** The Popovers anchor element. */
  anchorEl: PropTypes.object,
  /** The background colour of the Overlay. */
  backdrop: PropTypes.string,
  /** The component wrapped by the Popover. */
  children: PropTypes.node,
  /** The class names for the wrapper to apply custom styling. */
  className: PropTypes.string,
  /** The background colour of the Popover. */
  color: PropTypes.oneOf(['aqua', 'gold', 'mint', 'neutral', 'ruby', 'teal', 'violet']),
  /** The direction in which the Popover is rendered, is overridden with the opposite direction if the Popover cannot be entirely displayed in the current direction. */
  direction: PropTypes.oneOf(['north', 'south', 'east', 'west']),
  /** If true, the Popover stretches to fit its content vertically */
  fullHeight: PropTypes.bool,
  /** If true, the Popover stretches to fit its content horizontally */
  fullWidth: PropTypes.bool,
  /** The scroll state of the body, if true it will not be scrollable. */
  lockScroll: PropTypes.bool,
  /** The minimum width for the popover. */
  minWidth: PropTypes.string,
  /** The amount of extra translation on the Popover (has no effect if position is "middle" or "center"). */
  offsetCorrection: PropTypes.number,
  /** The function executed, when the "ESC" key is down. */
  onEscKeyDown: PropTypes.func,
  /** The function executed, when the Overlay is clicked. */
  onOverlayClick: PropTypes.func,
  /** The function executed, when the mouse is down on the Overlay. */
  onOverlayMouseDown: PropTypes.func,
  /** The function executed, when the mouse is being moved over the Overlay. */
  onOverlayMouseMove: PropTypes.func,
  /** The function executed, when the mouse is up on the Overlay. */
  onOverlayMouseUp: PropTypes.func,
  /** The position in which the Popover is rendered, is overridden with the another position if the Popover cannot be entirely displayed in the current position. */
  position: PropTypes.oneOf(['start', 'center', 'end']),
  /** The tint of the background colour of the Popover. */
  tint: PropTypes.oneOf(['lightest', 'light', 'normal', 'dark', 'darkest']),
  /** The z-index of the Popover */
  zIndex: PropTypes.number,
};

Popover.defaultProps = {
  active: true,
  backdrop: 'dark',
  zIndex: 300,
  direction: 'south',
  fullHeight: true,
  fullWidth: false,
  color: 'neutral',
  lockScroll: true,
  minWidth: 'auto',
  offsetCorrection: 0,
  position: 'center',
  tint: 'lightest',
};

export default Popover;
<commit_msg>Add & implement `maxWidth` prop with default value `50vw`<commit_after>import React, { createRef, PureComponent } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from 'prop-types';
import cx from 'classnames';
import throttle from 'lodash.throttle';
import InjectOverlay from '../overlay';
import Transition from 'react-transition-group/Transition';
import ReactResizeDetector from 'react-resize-detector';
import { events } from '../utils';
import { calculatePositions } from './positionCalculation';
import { getMaxHeight } from './sizeCalculation';
import Box from '../box';
import theme from './theme.css';
import uiUtilities from '@teamleader/ui-utilities';

class Popover extends PureComponent {
  popoverNode = createRef();
  popoverRoot = document.createElement('div');

  state = { positioning: { left: 0, top: 0, maxHeight: 'initial' } };

  componentDidMount() {
    document.body.appendChild(this.popoverRoot);
    events.addEventsToWindow({ resize: this.setPlacementThrottled, scroll: this.setPlacementThrottled });
  }

  componentWillUnmount() {
    events.removeEventsFromWindow({ resize: this.setPlacementThrottled, scroll: this.setPlacementThrottled });
    document.body.removeChild(this.popoverRoot);
  }

  componentDidUpdate(prevProps) {
    if (this.props.active && prevProps !== this.props) {
      this.setPlacement();
    }
  }

  setPlacement = () => {
    const { anchorEl, direction, position, offsetCorrection } = this.props;

    if (this.popoverNode.current) {
      this.setState({
        positioning: calculatePositions(anchorEl, this.popoverNode.current, direction, position, offsetCorrection),
      });
    }
  };

  setPlacementThrottled = throttle(this.setPlacement, 250);

  render() {
    const { left, top, maxHeight } = this.state.positioning;

    const {
      active,
      backdrop,
      children,
      className,
      color,
      fullHeight,
      fullWidth,
      lockScroll,
      maxWidth,
      minWidth,
      onOverlayClick,
      onEscKeyDown,
      onOverlayMouseDown,
      onOverlayMouseMove,
      onOverlayMouseUp,
      tint,
      zIndex,
    } = this.props;

    if (!active) {
      return null;
    }

    const popover = (
      <Transition timeout={0} in={active} appear>
        {state => {
          return (
            <div
              className={cx(theme['wrapper'], theme[color], theme[tint], {
                [theme['is-entering']]: state === 'entering',
                [theme['is-entered']]: state === 'entered',
              })}
              style={{ zIndex }}
            >
              <InjectOverlay
                active={active}
                backdrop={backdrop}
                className={theme['overlay']}
                lockScroll={lockScroll}
                onClick={onOverlayClick}
                onEscKeyDown={onEscKeyDown}
                onMouseDown={onOverlayMouseDown}
                onMouseMove={onOverlayMouseMove}
                onMouseUp={onOverlayMouseUp}
              />
              <div
                data-teamleader-ui={'popover'}
                className={cx(uiUtilities['box-shadow-200'], theme['popover'], className)}
                style={{ left: `${left}px`, top: `${top}px`, maxWidth: fullWidth ? '100vw' : maxWidth, minWidth }}
                ref={this.popoverNode}
              >
                <Box
                  className={theme['inner']}
                  display="flex"
                  flex="1 1 auto"
                  flexDirection="column"
                  style={{ maxHeight: getMaxHeight(fullHeight, maxHeight) }}
                >
                  {children}
                </Box>
                <ReactResizeDetector
                  handleHeight
                  handleWidth
                  onResize={this.setPlacement}
                  refreshMode="throttle"
                  refreshRate={250}
                />
              </div>
            </div>
          );
        }}
      </Transition>
    );

    return createPortal(popover, this.popoverRoot);
  }
}

Popover.propTypes = {
  /** The state of the Popover, when true the Popover is rendered otherwise it is not. */
  active: PropTypes.bool,
  /** The Popovers anchor element. */
  anchorEl: PropTypes.object,
  /** The background colour of the Overlay. */
  backdrop: PropTypes.string,
  /** The component wrapped by the Popover. */
  children: PropTypes.node,
  /** The class names for the wrapper to apply custom styling. */
  className: PropTypes.string,
  /** The background colour of the Popover. */
  color: PropTypes.oneOf(['aqua', 'gold', 'mint', 'neutral', 'ruby', 'teal', 'violet']),
  /** The direction in which the Popover is rendered, is overridden with the opposite direction if the Popover cannot be entirely displayed in the current direction. */
  direction: PropTypes.oneOf(['north', 'south', 'east', 'west']),
  /** If true, the Popover stretches to fit its content vertically */
  fullHeight: PropTypes.bool,
  /** If true, the Popover stretches to fit its content horizontally */
  fullWidth: PropTypes.bool,
  /** The scroll state of the body, if true it will not be scrollable. */
  lockScroll: PropTypes.bool,
  /** The maximum width for the popover. */
  maxWidth: PropTypes.string,
  /** The minimum width for the popover. */
  minWidth: PropTypes.string,
  /** The amount of extra translation on the Popover (has no effect if position is "middle" or "center"). */
  offsetCorrection: PropTypes.number,
  /** The function executed, when the "ESC" key is down. */
  onEscKeyDown: PropTypes.func,
  /** The function executed, when the Overlay is clicked. */
  onOverlayClick: PropTypes.func,
  /** The function executed, when the mouse is down on the Overlay. */
  onOverlayMouseDown: PropTypes.func,
  /** The function executed, when the mouse is being moved over the Overlay. */
  onOverlayMouseMove: PropTypes.func,
  /** The function executed, when the mouse is up on the Overlay. */
  onOverlayMouseUp: PropTypes.func,
  /** The position in which the Popover is rendered, is overridden with the another position if the Popover cannot be entirely displayed in the current position. */
  position: PropTypes.oneOf(['start', 'center', 'end']),
  /** The tint of the background colour of the Popover. */
  tint: PropTypes.oneOf(['lightest', 'light', 'normal', 'dark', 'darkest']),
  /** The z-index of the Popover */
  zIndex: PropTypes.number,
};

Popover.defaultProps = {
  active: true,
  backdrop: 'dark',
  zIndex: 300,
  direction: 'south',
  fullHeight: true,
  fullWidth: false,
  color: 'neutral',
  lockScroll: true,
  maxWidth: '50vw',
  minWidth: 'auto',
  offsetCorrection: 0,
  position: 'center',
  tint: 'lightest',
};

export default Popover;
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { merge } from 'lodash';
import tagComponent from '../../utils/helpers/tags';

/**
 * A rainbow chart using the Highcharts API.
 *
 * == How to use a Rainbow in a component:
 *
 * In your file:
 *
 *   import Rainbow from 'carbon/lib/components/rainbow';
 *
 * Note that the Rainbow component expects that you already have the Highcharts
 * library loaded. This may be true in case of some projects, which already have
 * that library available for their legacy code.
 * In other cases, you would need to import Highcharts before importing Rainbow:
 *
 *   import 'react-highcharts/dist/bundle/highcharts';
 *
 * To render the Rainbow:
 *
 *   let myImmutableData = Immutable.fromJS([
 *     {
 *       y: 30,
 *       name: 'First Bit',
 *       label: 'label for first bit',
 *       tooltip: 'more info about this bit',
 *       color: '#000' # we supply color by default, but you can supply your own like this
 *     }, {
 *       y: 70,
 *       name: 'Second Bit',
 *       label: 'label for second bit',
 *       tooltip: 'more info about this bit'
 *     }
 *   ]);
 *
 *   <Rainbow title="My Chart" data={ myImmutableData } />
 *
 * @class Rainbow
 * @constructor
 */
class Rainbow extends React.Component {

  static propTypes = {
    /**
     * A title for the component.
     *
     * @property title
     * @type {String}
     */
    title: PropTypes.string,

    /**
     * The data set for the component.
     *
     * @property data
     * @type {Object}
     */
    data: PropTypes.object.isRequired,

    /**
     * Custom chart config for the component.
     *
     * @property config
     * @type {Object}
     */
    config: PropTypes.object,

    /**
     * Custom className
     *
     * @property className
     * @type {String}
     */
    className: PropTypes.string
  }

  static defaultProps = {
    className: '',
    config: {},
    title: ''
  }

  /**
   * Renders the initial chart, and stores it on the ref so it can be updated later
   */
  componentDidMount() {
    const config = generateConfig(this.props.data, this.props.title);
    merge(config, this.props.config);
    this._chart = global.Highcharts.chart(this._chart, config);
  }

  /**
   * Always returns false, but uses the Highcharts API to update the charts
   * data or title if they have been updated.
   *
   * @method shouldComponentUpdate
   * @param {Object} nextProps new props passed to the component
   * @return {void}
   */
  shouldComponentUpdate(nextProps) {
    // use the highchart api to update its title
    if (this.props.title !== nextProps.title) {
      this._chart.setTitle({ text: nextProps.title });
    }

    // use the highchart api to update its data
    if (this.props.data !== nextProps.data) {
      this._chart.series[0].setData(nextProps.data.toJS());
    }

    // never re-render the component
    return false;
  }

  /**
   * Main Class getter
   *
   * @method mainClasses
   * @return {String} Main className
   */
  get mainClasses() {
    return classNames(
      'carbon-rainbow',
      this.props.className
    );
  }

  /**
   * Renders the component.
   *
   * @method render
   * @return {Object} JSX
   */
  render() {
    return (

 { this._chart = chart; } } />

    );
  }

}

/* istanbul ignore next */
/**
 * Generates the config for the Highchart.
 *
 * @method generateConfig
 * @param {Object} immutableData data for highchart
 * @param {String} title title for highchart
 * @private
 * @return {Object} config for highchart
 */
function generateConfig(immutableData, title) {
  const data = immutableData.toJS();

  return {
    credits: {
      enabled: false
    },
    chart: {
      height: 250,
      margin: 0,
      backgroundColor: null,
      spacing: 0,
      plotShadow: false
    },
    title: {
      style: {
        color: '',
        fontFamily: '',
        fontSize: ''
      },
      text: title,
      useHTML: true,
      verticalAlign: 'top',
      y: 35
    },
    tooltip: {
      borderRadius: 100,
      borderWidth: 0,
      followPointer: true,
      headerFormat: '',
      pointFormatter() {
        return `<span style="color: ${this.color}">${this.tooltip}</span>`;
      },
      positioner: (tooltipWidth, tooltipHeight, point) => {
        return () => {
          const x = point.plotX - (tooltipWidth / 2);
          const y = point.plotY - (tooltipHeight - 5);

          return { x, y };
        };
      },
      shadow: false
    },
    plotOptions: {
      pie: {
        animation: {
          duration: 400
        },
        colors: ['#01A4CF', '#FFAB02', '#EA433F', '#FFDD4F', '#FF448F'],
        startAngle: -90,
        endAngle: 90,
        center: ['50%', '100%'],
        dataLabels: {
          connectorWidth: 0,
          defer: false,
          distance: 18,
          enabled: true,
          formatter() {
            let display = 'display: ';
            display += this.point.visible ? 'block' : 'none';

            return `

                ${this.point.name}
${this.point.label}

            `;
          },
          padding: 0,
          style: {
            fontSize: '',
            fontWeight: '',
            fontFamily: ''
          },
          useHTML: true
        },
        point: {
          events: {
            mouseOver: () => { this.graphic.zIndexSetter(1); },
            mouseOut: () => { this.graphic.zIndexSetter(0); }
          }
        },
        states: {
          hover: {
            halo: false
          }
        }
      }
    },
    series: [{
      data,
      innerSize: '65%',
      type: 'pie'
    }]
  };
}

export default Rainbow;
<commit_msg>add event argument to mouseOver and mouseOut<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { merge } from 'lodash';
import tagComponent from '../../utils/helpers/tags';

/**
 * A rainbow chart using the Highcharts API.
 *
 * == How to use a Rainbow in a component:
 *
 * In your file:
 *
 *   import Rainbow from 'carbon/lib/components/rainbow';
 *
 * Note that the Rainbow component expects that you already have the Highcharts
 * library loaded. This may be true in case of some projects, which already have
 * that library available for their legacy code.
 * In other cases, you would need to import Highcharts before importing Rainbow:
 *
 *   import 'react-highcharts/dist/bundle/highcharts';
 *
 * To render the Rainbow:
 *
 *   let myImmutableData = Immutable.fromJS([
 *     {
 *       y: 30,
 *       name: 'First Bit',
 *       label: 'label for first bit',
 *       tooltip: 'more info about this bit',
 *       color: '#000' # we supply color by default, but you can supply your own like this
 *     }, {
 *       y: 70,
 *       name: 'Second Bit',
 *       label: 'label for second bit',
 *       tooltip: 'more info about this bit'
 *     }
 *   ]);
 *
 *   <Rainbow title="My Chart" data={ myImmutableData } />
 *
 * @class Rainbow
 * @constructor
 */
class Rainbow extends React.Component {

  static propTypes = {
    /**
     * A title for the component.
     *
     * @property title
     * @type {String}
     */
    title: PropTypes.string,

    /**
     * The data set for the component.
     *
     * @property data
     * @type {Object}
     */
    data: PropTypes.object.isRequired,

    /**
     * Custom chart config for the component.
     *
     * @property config
     * @type {Object}
     */
    config: PropTypes.object,

    /**
     * Custom className
     *
     * @property className
     * @type {String}
     */
    className: PropTypes.string
  }

  static defaultProps = {
    className: '',
    config: {},
    title: ''
  }

  /**
   * Renders the initial chart, and stores it on the ref so it can be updated later
   */
  componentDidMount() {
    const config = generateConfig(this.props.data, this.props.title);
    merge(config, this.props.config);
    this._chart = global.Highcharts.chart(this._chart, config);
  }

  /**
   * Always returns false, but uses the Highcharts API to update the charts
   * data or title if they have been updated.
   *
   * @method shouldComponentUpdate
   * @param {Object} nextProps new props passed to the component
   * @return {void}
   */
  shouldComponentUpdate(nextProps) {
    // use the highchart api to update its title
    if (this.props.title !== nextProps.title) {
      this._chart.setTitle({ text: nextProps.title });
    }

    // use the highchart api to update its data
    if (this.props.data !== nextProps.data) {
      this._chart.series[0].setData(nextProps.data.toJS());
    }

    // never re-render the component
    return false;
  }

  /**
   * Main Class getter
   *
   * @method mainClasses
   * @return {String} Main className
   */
  get mainClasses() {
    return classNames(
      'carbon-rainbow',
      this.props.className
    );
  }

  /**
   * Renders the component.
   *
   * @method render
   * @return {Object} JSX
   */
  render() {
    return (

 { this._chart = chart; } } />

    );
  }

}

/* istanbul ignore next */
/**
 * Generates the config for the Highchart.
 *
 * @method generateConfig
 * @param {Object} immutableData data for highchart
 * @param {String} title title for highchart
 * @private
 * @return {Object} config for highchart
 */
function generateConfig(immutableData, title) {
  const data = immutableData.toJS();

  return {
    credits: {
      enabled: false
    },
    chart: {
      height: 250,
      margin: 0,
      backgroundColor: null,
      spacing: 0,
      plotShadow: false
    },
    title: {
      style: {
        color: '',
        fontFamily: '',
        fontSize: ''
      },
      text: title,
      useHTML: true,
      verticalAlign: 'top',
      y: 35
    },
    tooltip: {
      borderRadius: 100,
      borderWidth: 0,
      followPointer: true,
      headerFormat: '',
      pointFormatter() {
        return `<span style="color: ${this.color}">${this.tooltip}</span>`;
      },
      positioner: (tooltipWidth, tooltipHeight, point) => {
        return () => {
          const x = point.plotX - (tooltipWidth / 2);
          const y = point.plotY - (tooltipHeight - 5);

          return { x, y };
        };
      },
      shadow: false
    },
    plotOptions: {
      pie: {
        animation: {
          duration: 400
        },
        colors: ['#01A4CF', '#FFAB02', '#EA433F', '#FFDD4F', '#FF448F'],
        startAngle: -90,
        endAngle: 90,
        center: ['50%', '100%'],
        dataLabels: {
          connectorWidth: 0,
          defer: false,
          distance: 18,
          enabled: true,
          formatter() {
            let display = 'display: ';
            display += this.point.visible ? 'block' : 'none';

            return `

                ${this.point.name}
${this.point.label}

            `;
          },
          padding: 0,
          style: {
            fontSize: '',
            fontWeight: '',
            fontFamily: ''
          },
          useHTML: true
        },
        point: {
          events: {
            mouseOver: (ev) => { ev.target.graphic.zIndexSetter(1); },
            mouseOut: (ev) => { ev.target.graphic.zIndexSetter(0); }
          }
        },
        states: {
          hover: {
            halo: false
          }
        }
      }
    },
    series: [{
      data,
      innerSize: '65%',
      type: 'pie'
    }]
  };
}

export default Rainbow;
<|endoftext|>


<commit_before>// go.components.views
// ===================
// Generic, re-usable views for Go

(function(exports) {
  var utils = go.utils,
      functor = utils.functor;

  // View for a label which can be attached to an element.
  //
  // Options:
  //   - text: A string or a function returning a string containing the text to
  //   be displayed by the label
  //   - of: The element this label should be attached to
  //   - my: The my on the label to align with the of
  //   - at: The my on the of to align the label against
  var LabelView = Backbone.View.extend({
    tagName: 'span',
    className: 'label',

    initialize: function(options) {
      this.$of = $(options.of);
      this.text = functor(options.text);
      this.my = options.my;
      this.at = options.at;
    },

    render: function() {
      // Append the label to the of element so it can follow the of
      // around (in the case of moving or draggable ofs)
      this.$of.append(this.$el);

      this.$el
        .text(this.text())
        .position({
          of: this.$of,
          my: this.my,
          at: this.at
        })
        .css('position', 'absolute')
        .css('pointer-events', 'none');
    }
  });

  _.extend(exports, {
    LabelView: LabelView
  });
})(go.components.views = {});
<commit_msg>Fix bad comments for LabelView<commit_after>// go.components.views
// ===================
// Generic, re-usable views for Go

(function(exports) {
  var utils = go.utils,
      functor = utils.functor;

  // View for a label which can be attached to an element.
  //
  // Options:
  //   - text: A string or a function returning a string containing the text to
  //   be displayed by the label
  //   - of: The target element this label should be attached to
  //   - my: The point on the label to align with the of
  //   - at: The point on the target element to align the label against
  var LabelView = Backbone.View.extend({
    tagName: 'span',
    className: 'label',

    initialize: function(options) {
      this.$of = $(options.of);
      this.text = functor(options.text);
      this.my = options.my;
      this.at = options.at;
    },

    render: function() {
      // Append the label to the of element so it can follow the of
      // around (in the case of moving or draggable ofs)
      this.$of.append(this.$el);

      this.$el
        .text(this.text())
        .position({
          of: this.$of,
          my: this.my,
          at: this.at
        })
        .css('position', 'absolute')
        .css('pointer-events', 'none');
    }
  });

  _.extend(exports, {
    LabelView: LabelView
  });
})(go.components.views = {});
<|endoftext|>


<commit_before>import React from 'react';

import Container from './../shared/container';
import Directions from './directions';
import Image from './../shared/image';
import Section from './../shared/section';
import constants from './../../constants/constants';

const {images, links} = constants;

const Wedding = () => {
  return (
    <Container
      id="wedding"
      title="The Wedding">

Friday, September 30, 2016

The Rengstorff House

3070 N Shoreline Blvd, Mountain View, CA 94043

        <Image
          src={images.rengstorffHouse}
          href={links.directions}
        />

          Wedding Ceremony & Reception:
          5:00pm

          Buffet Dinner:
          7:00pm

          Cake (is not a lie!):
          7:30pm

          More Partying & Fun until 10:00pm!

The Rengstorff House

3070 N Shoreline Blvd, Mountain View, CA 94043

        <Directions />

        <Image
          src={images.rengstorffHouse2}
          href={links.rengstorffHouse}
        />

            The Rengstorff House

          {' '} is one of Mountain View’s oldest house and finest examples of
          Victorian Italianate architecture on the West Coast.

          We really liked the house and its vicinity to Shoreline Park.  We
          recommend our family and friends to enjoy a nice Californian sunset
          walk before and after the wedding!

        <Image
          src={images.shorelinePark}
          href={links.shorelinePark}
        />

          Shoreline Park

          {' '} is a 750-acre wildlife and recreation area with a beautiful
          view of the mountains to the west and east across the Bay.

          We look forward to seeing all of you at the wedding and hopefully
          spending time walking under the sunset by the house and lake!

    </Container>
  );
};

export default Wedding;
<commit_msg>fixed apostrophe<commit_after>import React from 'react';

import Container from './../shared/container';
import Directions from './directions';
import Image from './../shared/image';
import Section from './../shared/section';
import constants from './../../constants/constants';

const {images, links} = constants;

const Wedding = () => {
  return (
    <Container
      id="wedding"
      title="The Wedding">

Friday, September 30, 2016

The Rengstorff House

3070 N Shoreline Blvd, Mountain View, CA 94043

        <Image
          src={images.rengstorffHouse}
          href={links.directions}
        />

          Wedding Ceremony & Reception:
          5:00pm

          Buffet Dinner:
          7:00pm

          Cake (is not a lie!):
          7:30pm

          More Partying & Fun until 10:00pm!

The Rengstorff House

3070 N Shoreline Blvd, Mountain View, CA 94043

        <Directions />

        <Image
          src={images.rengstorffHouse2}
          href={links.rengstorffHouse}
        />

            The Rengstorff House

          {' '} is one of Mountain View's oldest house and finest examples of
          Victorian Italianate architecture on the West Coast.

          We really liked the house and its vicinity to Shoreline Park.  We
          recommend our family and friends to enjoy a nice Californian sunset
          walk before and after the wedding!

        <Image
          src={images.shorelinePark}
          href={links.shorelinePark}
        />

          Shoreline Park

          {' '} is a 750-acre wildlife and recreation area with a beautiful
          view of the mountains to the west and east across the Bay.

          We look forward to seeing all of you at the wedding and hopefully
          spending time walking under the sunset by the house and lake!

    </Container>
  );
};

export default Wedding;
<|endoftext|>


<commit_before>// ─────────────────────────────────────────────────────────────────────────────
// import
// ─────────────────────────────────────────────────────────────────────────────

import React from 'react';

import { Toast, Link, Button } from '~components';
import { useLocalStorage } from '~utils/';

// ─────────────────────────────────────────────────────────────────────────────
// component
// ─────────────────────────────────────────────────────────────────────────────

export default function CookieContainer() {
  const [isVisible, setIsVisible] = useLocalStorage('isShowCookies', true);

  return (
    <Toast
      css={`
        background-color: var(--color-bg);
        color: var(--color-text);
        font-size: 1.25rem;
        bottom: auto;
        top: 0;

        @media screen and (min-width: 300px) {
          bottom: 0;
          top: auto;
        }
      `}
      isVisible={isVisible}
    >
      Yeah, we use cookies, we even have a{' '}
      <Link to="/legal/privacy/" look="secondary">
        cookie policy
      </Link>
      <Button
        look="secondary"
        css={`
          margin: 0 0 0 1rem;
        `}
        onClick={() => setIsVisible(!isVisible)}
      >
        Accept{' '}

          🍪

      </Button>
    </Toast>
  );
}
<commit_msg>fix cookies container update logic<commit_after>// ─────────────────────────────────────────────────────────────────────────────
// import
// ─────────────────────────────────────────────────────────────────────────────

import React from 'react';

import { Toast, Link, Button } from '~components';
import { useLocalStorage } from '~utils/';

// ─────────────────────────────────────────────────────────────────────────────
// component
// ─────────────────────────────────────────────────────────────────────────────

export default function CookieContainer() {
  const [isVisible, setIsVisible] = useLocalStorage('isShowCookies', true);

  if (!isVisible) return null;

  return (
    <Toast
      css={`
        background-color: var(--color-bg);
        color: var(--color-text);
        font-size: 1.25rem;
        bottom: auto;
        top: 0;

        @media screen and (min-width: 300px) {
          bottom: 0;
          top: auto;
        }
      `}
      isVisible
    >
      Yeah, we use cookies, we even have a{' '}
      <Link to="/legal/privacy/" look="secondary">
        cookie policy
      </Link>
      <Button
        look="secondary"
        css={`
          margin: 0 0 0 1rem;
        `}
        onClick={() => setIsVisible(!isVisible)}
      >
        Accept{' '}

          🍪

      </Button>
    </Toast>
  );
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { Media } from 'components';
import { connect } from 'react-redux';
import { asyncConnect } from 'redux-connect';
import { loadObjects } from '../../redux/modules/objects';
import Helmet from 'react-helmet';

@connect(
  state => ({
    nsrResults: state.objects.soortenregister.results,
    nsrLoading: state.objects.soortenregister.loading,
    nsrLoaded: state.objects.soortenregister.loaded
  }),
  {}
)
@asyncConnect([{
  promise: ({store: {dispatch}}) => {
    return dispatch(loadObjects('soortenregister'));
  }
}])
export default class Species extends Component {
  static propTypes = {
    nsrResults: PropTypes.object,
    nsrLoaded: PropTypes.bool,
    nsrLoading: PropTypes.bool
  }
  render() {
    const styles = require('./Species.scss');
    const { nsrResults, nsrLoaded } = this.props;
    let nsrNodes;

    if (nsrLoaded) {
      const object = nsrResults['@graph'][0]['edm:aggregatedCHO'];
      const resource = nsrResults['@graph'][0]['edm:isShownBy'];

      nsrNodes = (
        <Media
          url={resource['@id']}
          type={resource['dcterms:type']}
          title={object['@id']}
          color="red"
        />
      );
    }

    return (

        <Helmet title="Species"/>

Very fancy species page

          {nsrNodes}

    );
  }
}
<commit_msg>Loading objects from three platforms, resolves #107.<commit_after>import React, { Component, PropTypes } from 'react';
import { Media } from 'components';
import { connect } from 'react-redux';
import { asyncConnect } from 'redux-connect';
import { loadObjects } from '../../redux/modules/objects';
import Helmet from 'react-helmet';

@connect(
  state => ({
    nsrResults: state.objects.soortenregister.results,
    nsrLoading: state.objects.soortenregister.loading,
    nsrLoaded: state.objects.soortenregister.loaded
  }),
  {}
)
@asyncConnect([{
  promise: ({store: {dispatch}}) => {
    return dispatch(loadObjects('soortenregister'));
  },
}, {
  promise: ({store: {dispatch}}) => {
    return dispatch(loadObjects('xeno-canto'));
  },
}, {
  promise: ({store: {dispatch}}) => {
    return dispatch(loadObjects('rijksmuseum'));
  },
}])
export default class Species extends Component {
  static propTypes = {
    nsrResults: PropTypes.object,
    nsrLoaded: PropTypes.bool,
    nsrLoading: PropTypes.bool
  }
  render() {
    const styles = require('./Species.scss');
    const { nsrResults, nsrLoaded } = this.props;
    let nsrNodes;

    if (nsrLoaded) {
      const object = nsrResults['@graph'][0]['edm:aggregatedCHO'];
      const resource = nsrResults['@graph'][0]['edm:isShownBy'];

      nsrNodes = (
        <Media
          url={resource['@id']}
          type={resource['dcterms:type']}
          title={object['@id']}
          color="red"
        />
      );
    }

    return (

        <Helmet title="Species"/>

Very fancy species page

          {nsrNodes}

    );
  }
}
<|endoftext|>


<commit_before>

~ function () {
    var musicList = [
    {
        'Artist': 'Suara',
        'Album': '「Pure -AQUAPLUS LEGEND OF ACOUSTICS-」',
        'Source': 'https://dn-wind-moe.qbox.me/static/music/Suara - 梦想歌.mp3?ver=1.0',
        'Title': '梦想歌',
        'Duration': '247'
		}, {
        'Artist': 'Suara',
        'Title': '不安定な神様',
        'Album': '「不安定な神様」',
        'Source': 'https://dn-wind-moe.qbox.me/static/music/Suara - 不安定な神様.mp3',
        'Duration': '244'
		}
	];

    var se = sessionStorage;
    var audio = $('#audio');

    if(se.getItem('mode')){
        var musicMode = se.getItem('mode')
    }else {
        var musicMode = 'list'
    }

    function change() {
        if(se.getItem('index') && se.getItem('current')) {
            audio.currentTime = parseFloat(se.getItem('current'));
        }
    }

    var bufferTimer = null;
    var volumeTimer = null;

    $('.play').onclick = function () {
        toPlay('play');
    }
    $('.pause').onclick = function () {
        toPlay('pause');
    }
    $('.prev').onclick = function () {
        toPlay('prev');
    }
    $('.next').onclick = function () {
        toPlay('next');
    }
    $('.progress_bar').onclick = function (ev) {
            adjustPorgress(this, ev);
        }

    $('.volume').onmouseover = $('.volume_wrap').onmouseover = function () {
        clearTimeout(volumeTimer);
        removeClass($('.volume_wrap'), 'hidden')
    };
    $('.volume').onmouseout = $('.volume_wrap').onmouseout = function () {
        volumeTimer = setTimeout(function () {
            addClass($('.volume_wrap'), 'hidden');
        }, 300);
    };
    $('.volume_bar').onclick = function (ev) {
        adjustVolume(this, ev);
    };

    $('.volume').onclick = function () {
        if (audio.muted == false) {
            this.style.color = '#A1A1A1';
            audio.muted = true;
            se.setItem('muted', 1);
        } else if (audio.muted == true) {
            this.style.color = '#8BC34A';
            audio.muted = false;
            se.setItem('muted', 0);
        };
    };

    $('.shuffle').onclick = function () {
        if(musicMode=='list'){
            changeMusicMode(this, 'shuffle')
        }else{
            changeMusicMode(this, 'list')
        }
    };

    audio.addEventListener('canplay', bufferBar, false);

    function initPlayer(index) {
        audio.setAttribute('src', musicList[index].Source);
        $('.song').innerHTML = musicList[index].Title;
        $('.album').innerHTML = musicList[index].Album;
        $('.progress').style.width = 0 + 'px';
        audio.removeEventListener('canplay', bufferBar, false);
        clearInterval(bufferTimer);
        $('.buffer').style.width = 0 + 'px';
    }

    function toPlay(action) {
        if (action == 'play') {
            audio.play();
            removeClass($('.pause'), 'hidden');
            addClass($('.play'), 'hidden');
            se.setItem('pause', 0)
        } else if (action == 'pause') {
            audio.pause();
            removeClass($('.play'), 'hidden');
            addClass($('.pause'), 'hidden');
            se.setItem('pause', 1)
        } else if (action == 'prev') {
            playMusicMode(action);
        } else if (action == 'next') {
            playMusicMode(action);
        }
    }

    audio.addEventListener('ended', function () {
        playMusicMode('ended');
    }, false);

    function playMusicMode(action) {
        var MusicNum = musicList.length;
        var index = musicIndex;

        //list loop
        if (musicMode == 'list') {
            if (action == 'prev') {
                if (index == 1) {
                    index = MusicNum; //第一首歌则返回最后一首
                } else {
                    index -= 1;
                }
            } else if (action == 'next' || action == 'ended') {
                if (index == MusicNum) {
                    index = 1;
                } else {
                    index += 1;
                }
            }
        }

        if (musicMode == 'shuffle') {
            var randomIndex = parseInt(MusicNum * Math.random());
            index = randomIndex + 1;
        }

        musicIndex = index;
        playIndex(index - 1);
    }

    function playIndex(index) {
        initPlayer(index);
        audio.load();
        audio.addEventListener('canplay', bufferBar, false);
        toPlay('play');
        se.setItem('index', index + 1)
    }

    function changeMusicMode(dom, mode) {
        musicMode = mode;
        if(musicMode=='shuffle'){
            dom.style.color = '#8BC34A';
        }else{
            dom.style.color = '#A1A1A1';
        }
        se.setItem('mode', mode);
    }

    audio.addEventListener('timeupdate', function () {
        if (!isNaN(audio.duration)) {
			sessionStorage.setItem('current',audio.currentTime);

            var curMin = parseInt(audio.currentTime / 60);
            var curSec = parseInt(audio.currentTime % 60);
            if(curSec < 10){curSec = '0'+curSec;}
            var totalMin = parseInt(audio.duration / 60);
            var totalSec = parseInt(audio.duration % 60);
            if(totalSec < 10){totalSec = '0'+totalSec;}

            $('.time').innerHTML = curMin + ":" + curSec + "/" + totalMin + ":" + totalSec;

            var progressValue = audio.currentTime / audio.duration * 324;
            $('.progress').style.width = parseInt(progressValue) + 'px';
        };
    }, false);

    function bufferBar() {
        bufferTimer = setInterval(function () {
            var bufferIndex = audio.buffered.length;
            if (bufferIndex > 0 && audio.buffered != undefined) {
                var bufferValue = audio.buffered.end(bufferIndex - 1) / audio.duration * 324;
                $('.buffer').style.width = parseInt(bufferValue) + 'px';

                if (Math.abs(audio.duration - audio.buffered.end(bufferIndex - 1)) < 1) {
                    $('.buffer').style.width = 324 + 'px';
                    clearInterval(bufferTimer);
                };
            };
        }, 1000);
    }

    function adjustPorgress(dom, ev) {
        var event = window.event || ev;
        var progressX = event.clientX - dom.getBoundingClientRect().left;
        audio.currentTime = parseInt(progressX / 324 * audio.duration);
        audio.removeEventListener('canplay', bufferBar, false);
    }

    function adjustVolume(dom, ev) {
        var event = window.event || ev;
        var volumeY = dom.getBoundingClientRect().bottom - event.clientY;
        audio.volume = (volumeY / 80).toFixed(2);
        $('.volume_now').style.height = volumeY + 'px';
        se.setItem('volume', (volumeY / 80).toFixed(2));
    };

	function adjustplay(time) {
		audio.currentTime = parseFloat(time);
		audio.removeEventListener('canplay', bufferBar, false);
	}

    function hasClass(dom, className) {
        var classNum = dom.className.split(" "),
            hasClass;
        for (var i = 0; i < classNum.length; i++) {
            if (classNum[i] == className) {
                hasClass = true;
                break;
            } else {
                hasClass = false;
            };
        };
        return hasClass;
    }

    function addClass(dom, className) {
        if (!hasClass(dom, className)) {
            dom.className += " " + className;
        };
    }

    function removeClass(dom, className) {
        if (hasClass(dom, className)) {
            var classNum = dom.className.split(" ");
            for (var i = 0; i < classNum.length; i++) {
                if (classNum[i] == className) {
                    classNum.splice(i, 1);
                    dom.className = classNum.join(" ");
                    break;
                };
            };
        };
    }

    function replaceClass(dom, className, replaceClass) {
        if (hasClass(dom, className)) {
            var classNum = dom.className.split(" ");
            for (var i = 0; i < classNum.length; i++) {
                if (classNum[i] == className) {
                    classNum.splice(i, 1, replaceClass);
                    dom.className = className.join(" ");
                    break;
                };
            };
        };
    }

    $('.dialog-close-button').onclick = function(){
        addClass($('#music'), 'hidden')
    }

    $('#mbtn').onclick = function(){
        if(hasClass($('#music'), 'hidden')){
            removeClass($('#music'), 'hidden')
        }else{
            addClass($('#music'), 'hidden')
        }
    }

	if(se.getItem('index')){
        var musicIndex = se.getItem('index')
    }else {
        var musicIndex = 1;
        se.setItem('index', musicIndex)
    }
    initPlayer(musicIndex - 1);

     if (se.getItem('volume')) {
		audio.volume = se.getItem('volume');
		$('#volume_now').style.height = se.getItem('volume') * 80 + "px";
	} else {
		audio.volume = .5
	};

	if(se.getItem('pause') && se.getItem('pause') == 0){
	    setTimeout(function () {
            audio.play();
            change();
        }, 150);
        addClass($('.play'), 'hidden');
        removeClass($('.pause'), 'hidden');
	}

	if (se.getItem("muted") == 1) {
		$(".volume").style.color = '#A1A1A1';
		audio.muted = !0;
	};
}();

var oDiv=$("#music_drap"),
    oTag=$('#music');
fnDrafting(oDiv, oTag);
function fnDrafting(obj, tag){
    obj.onmousedown=function(ev){
        var oEvent=ev||event,
			disX=oEvent.clientX-tag.offsetLeft,
			disY=oEvent.clientY-tag.offsetTop;
        document.onmousemove=function(ev){
            var oEvent=ev||event,
                left=oEvent.clientX-disX,
				top=oEvent.clientY-disY;
            if(left<0){
                left=0;
            }else if(left>document.documentElement.clientWidth-tag.offsetWidth){
                left=document.documentElement.clientWidth-tag.offsetWidth;
            }
            if(top<0){
                top=0;
            }else if(top>document.documentElement.clientHeight-tag.offsetHeight){
                top=document.documentElement.clientHeight-tag.offsetHeight;
            }
            tag.style.left=left+'px';
            tag.style.top=top+'px';
        }
        document.onmouseup=function(){
            document.onmousemove=null;
            document.onmouseup=null;
        }
    }

}
<commit_msg>Fix music player work bug<commit_after>~ function () {
    var musicList = [
    {
        'Artist': 'Suara',
        'Album': '「Pure -AQUAPLUS LEGEND OF ACOUSTICS-」',
        'Source': 'https://dn-wind-moe.qbox.me/static/music/Suara - 梦想歌.mp3?ver=1.0',
        'Title': '梦想歌',
        'Duration': '247'
		}, {
        'Artist': 'Suara',
        'Title': '不安定な神様',
        'Album': '「不安定な神様」',
        'Source': 'https://dn-wind-moe.qbox.me/static/music/Suara - 不安定な神様.mp3',
        'Duration': '244'
		}
	];

    var se = sessionStorage;
    var audio = $('#audio');

    if(se.getItem('mode')){
        var musicMode = se.getItem('mode')
    }else {
        var musicMode = 'list'
    }

    function change() {
        if(se.getItem('index') && se.getItem('current')) {
            audio.currentTime = parseFloat(se.getItem('current'));
        }
    }

    var bufferTimer = null;
    var volumeTimer = null;

    $('.play').onclick = function () {
        toPlay('play');
    }
    $('.pause').onclick = function () {
        toPlay('pause');
    }
    $('.prev').onclick = function () {
        toPlay('prev');
    }
    $('.next').onclick = function () {
        toPlay('next');
    }
    $('.progress_bar').onclick = function (ev) {
            adjustPorgress(this, ev);
        }

    $('.volume').onmouseover = $('.volume_wrap').onmouseover = function () {
        clearTimeout(volumeTimer);
        removeClass($('.volume_wrap'), 'hidden')
    };
    $('.volume').onmouseout = $('.volume_wrap').onmouseout = function () {
        volumeTimer = setTimeout(function () {
            addClass($('.volume_wrap'), 'hidden');
        }, 300);
    };
    $('.volume_bar').onclick = function (ev) {
        adjustVolume(this, ev);
    };

    $('.volume').onclick = function () {
        if (audio.muted == false) {
            this.style.color = '#A1A1A1';
            audio.muted = true;
            se.setItem('muted', 1);
        } else if (audio.muted == true) {
            this.style.color = '#8BC34A';
            audio.muted = false;
            se.setItem('muted', 0);
        };
    };

    $('.shuffle').onclick = function () {
        if(musicMode=='list'){
            changeMusicMode(this, 'shuffle')
        }else{
            changeMusicMode(this, 'list')
        }
    };

    audio.addEventListener('canplay', bufferBar, false);

    function initPlayer(index) {
        audio.setAttribute('src', musicList[index].Source);
        $('.song').innerHTML = musicList[index].Title;
        $('.album').innerHTML = musicList[index].Album;
        $('.progress').style.width = 0 + 'px';
        audio.removeEventListener('canplay', bufferBar, false);
        clearInterval(bufferTimer);
        $('.buffer').style.width = 0 + 'px';
    }

    function toPlay(action) {
        if (action == 'play') {
            audio.play();
            removeClass($('.pause'), 'hidden');
            addClass($('.play'), 'hidden');
            se.setItem('pause', 0)
        } else if (action == 'pause') {
            audio.pause();
            removeClass($('.play'), 'hidden');
            addClass($('.pause'), 'hidden');
            se.setItem('pause', 1)
        } else if (action == 'prev') {
            playMusicMode(action);
        } else if (action == 'next') {
            playMusicMode(action);
        }
    }

    audio.addEventListener('ended', function () {
        playMusicMode('ended');
    }, false);

    function playMusicMode(action) {
        var MusicNum = musicList.length;
        var index = musicIndex;

        //list loop
        if (musicMode == 'list') {
            if (action == 'prev') {
                if (index == 1) {
                    index = MusicNum; //第一首歌则返回最后一首
                } else {
                    index -= 1;
                }
            } else if (action == 'next' || action == 'ended') {
                if (index == MusicNum) {
                    index = 1;
                } else {
                    index += 1;
                }
            }
        }

        if (musicMode == 'shuffle') {
            var randomIndex = parseInt(MusicNum * Math.random());
            index = randomIndex + 1;
        }

        musicIndex = index;
        playIndex(index - 1);
    }

    function playIndex(index) {
        initPlayer(index);
        audio.load();
        audio.addEventListener('canplay', bufferBar, false);
        toPlay('play');
        se.setItem('index', index + 1)
    }

    function changeMusicMode(dom, mode) {
        musicMode = mode;
        if(musicMode=='shuffle'){
            dom.style.color = '#8BC34A';
        }else{
            dom.style.color = '#A1A1A1';
        }
        se.setItem('mode', mode);
    }

    audio.addEventListener('timeupdate', function () {
        if (!isNaN(audio.duration)) {
			sessionStorage.setItem('current',audio.currentTime);

            var curMin = parseInt(audio.currentTime / 60);
            var curSec = parseInt(audio.currentTime % 60);
            if(curSec < 10){curSec = '0'+curSec;}
            var totalMin = parseInt(audio.duration / 60);
            var totalSec = parseInt(audio.duration % 60);
            if(totalSec < 10){totalSec = '0'+totalSec;}

            $('.time').innerHTML = curMin + ":" + curSec + "/" + totalMin + ":" + totalSec;

            var progressValue = audio.currentTime / audio.duration * 324;
            $('.progress').style.width = parseInt(progressValue) + 'px';
        };
    }, false);

    function bufferBar() {
        bufferTimer = setInterval(function () {
            var bufferIndex = audio.buffered.length;
            if (bufferIndex > 0 && audio.buffered != undefined) {
                var bufferValue = audio.buffered.end(bufferIndex - 1) / audio.duration * 324;
                $('.buffer').style.width = parseInt(bufferValue) + 'px';

                if (Math.abs(audio.duration - audio.buffered.end(bufferIndex - 1)) < 1) {
                    $('.buffer').style.width = 324 + 'px';
                    clearInterval(bufferTimer);
                };
            };
        }, 1000);
    }

    function adjustPorgress(dom, ev) {
        var event = window.event || ev;
        var progressX = event.clientX - dom.getBoundingClientRect().left;
        audio.currentTime = parseInt(progressX / 324 * audio.duration);
        audio.removeEventListener('canplay', bufferBar, false);
    }

    function adjustVolume(dom, ev) {
        var event = window.event || ev;
        var volumeY = dom.getBoundingClientRect().bottom - event.clientY;
        audio.volume = (volumeY / 80).toFixed(2);
        $('.volume_now').style.height = volumeY + 'px';
        se.setItem('volume', (volumeY / 80).toFixed(2));
    };

	function adjustplay(time) {
		audio.currentTime = parseFloat(time);
		audio.removeEventListener('canplay', bufferBar, false);
	}

    function hasClass(dom, className) {
        var classNum = dom.className.split(" "),
            hasClass;
        for (var i = 0; i < classNum.length; i++) {
            if (classNum[i] == className) {
                hasClass = true;
                break;
            } else {
                hasClass = false;
            };
        };
        return hasClass;
    }

    function addClass(dom, className) {
        if (!hasClass(dom, className)) {
            dom.className += " " + className;
        };
    }

    function removeClass(dom, className) {
        if (hasClass(dom, className)) {
            var classNum = dom.className.split(" ");
            for (var i = 0; i < classNum.length; i++) {
                if (classNum[i] == className) {
                    classNum.splice(i, 1);
                    dom.className = classNum.join(" ");
                    break;
                };
            };
        };
    }

    function replaceClass(dom, className, replaceClass) {
        if (hasClass(dom, className)) {
            var classNum = dom.className.split(" ");
            for (var i = 0; i < classNum.length; i++) {
                if (classNum[i] == className) {
                    classNum.splice(i, 1, replaceClass);
                    dom.className = className.join(" ");
                    break;
                };
            };
        };
    }

    $('.dialog-close-button').onclick = function(){
        addClass($('#music'), 'hidden')
    }

    $('#mbtn').onclick = function(){
        if(hasClass($('#music'), 'hidden')){
            removeClass($('#music'), 'hidden')
        }else{
            addClass($('#music'), 'hidden')
        }
    }
    se.setItem('mode', 'list')
	if(se.getItem('index')){
        var musicIndex = se.getItem('index')
    }else {
        var musicIndex = 1;
        se.setItem('index', musicIndex)
    }
    initPlayer(musicIndex - 1);

     if (se.getItem('volume')) {
		audio.volume = se.getItem('volume');
		$('.volume_now').style.height = se.getItem('volume') * 80 + "px";
	} else {
		audio.volume = .5
	};

	if(se.getItem('pause') && se.getItem('pause') == 0){
	    setTimeout(function () {
            audio.play();
            change();
        }, 150);
        addClass($('.play'), 'hidden');
        removeClass($('.pause'), 'hidden');
	}

	if (se.getItem("muted") == 1) {
		$(".volume").style.color = '#A1A1A1';
		audio.muted = !0;
	};
}();

var oDiv=$("#music_drap"),
    oTag=$('#music');
fnDrafting(oDiv, oTag);
function fnDrafting(obj, tag){
    obj.onmousedown=function(ev){
        var oEvent=ev||event,
			disX=oEvent.clientX-tag.offsetLeft,
			disY=oEvent.clientY-tag.offsetTop;
        document.onmousemove=function(ev){
            var oEvent=ev||event,
                left=oEvent.clientX-disX,
				top=oEvent.clientY-disY;
            if(left<0){
                left=0;
            }else if(left>document.documentElement.clientWidth-tag.offsetWidth){
                left=document.documentElement.clientWidth-tag.offsetWidth;
            }
            if(top<0){
                top=0;
            }else if(top>document.documentElement.clientHeight-tag.offsetHeight){
                top=document.documentElement.clientHeight-tag.offsetHeight;
            }
            tag.style.left=left+'px';
            tag.style.top=top+'px';
        }
        document.onmouseup=function(){
            document.onmousemove=null;
            document.onmouseup=null;
        }
    }

}
<|endoftext|>


<commit_before>
"use strict";

let loc;
let auth;
let nav;
let route;
let modal;
let langs;

class RootController {

    constructor($location, $rootScope, $route, $translate, Authentication, Navigation, $modal, title, languages, theme) {
        loc = $location;
        auth = Authentication;
        nav = Navigation;
        modal = $modal;
        this.title = title;
        let reload = $route.reload;
        $route.reload = () => {
            this.modal = false;
            reload();
        };
        this.loginRequired = this.loginRequired || true;
        this.language = undefined;
        langs = languages;
        this.theme = theme;
        $rootScope.$on('$routeChangeStart', () => this.Authentication.read().success(result => {
            if (!this.Authentication.isAuthenticated() && this.loginRequired) {
                loc.path('/' + (this.language || languages[0]) + '/login/');
            }
        }));
        $rootScope.$on('$routeChangeSuccess', (event, target) => {
            if (target.params.language && target.params.language != this.language) {
                this.language = target.params.language;
                $translate.refresh();
            }
            if (!this.language) {
                loc.path('/' + languages[0] + '/');
            }
            $translate.use(this.language);
        });
        route = $route;
    }

    get Authentication() {
        return auth;
    }

    get Navigation() {
        return nav;
    }

    get languages() {
        return langs;
    }

    logout() {
        this.Authentication.logout().success(() => loc.path('/' + this.language + '/login/'));
    }

    url() {
        return loc.path();
    }

    reload() {
        route.reload();
    }

    license() {
        let m = modal.open({
            template: `

{{'monad.license' | translate}}

    <button class="btn btn-primary" ng-click="ok()">OK</button>

`,
            controller: ['$scope', '$modalInstance', ($scope, $modalInstance) => {
                $scope.ok = $modalInstance.close;
            }]
        });
    }

};

RootController.$inject = ['$location', '$rootScope', '$route', '$translate', 'moAuthentication', 'moNavigation', '$modal', 'title', 'languages', 'theme'];

export {RootController};

<commit_msg>set current route<commit_after>
"use strict";

let loc;
let auth;
let nav;
let route;
let modal;
let langs;

class RootController {

    constructor($location, $rootScope, $route, $translate, Authentication, Navigation, $modal, title, languages, theme) {
        loc = $location;
        auth = Authentication;
        nav = Navigation;
        modal = $modal;
        this.title = title;
        let reload = $route.reload;
        $route.reload = () => {
            this.modal = false;
            reload();
        };
        this.loginRequired = this.loginRequired || true;
        this.language = undefined;
        langs = languages;
        this.theme = theme;
        Navigation.current();
        $rootScope.$on('$routeChangeStart', () => this.Authentication.read().success(result => {
            if (!this.Authentication.isAuthenticated() && this.loginRequired) {
                loc.path('/' + (this.language || languages[0]) + '/login/');
            }
        }));
        $rootScope.$on('$routeChangeSuccess', (event, target) => {
            if (target.params.language && target.params.language != this.language) {
                this.language = target.params.language;
                $translate.refresh();
            }
            if (!this.language) {
                loc.path('/' + languages[0] + '/');
            }
            $translate.use(this.language);
        });
        route = $route;
    }

    get Authentication() {
        return auth;
    }

    get Navigation() {
        return nav;
    }

    get languages() {
        return langs;
    }

    logout() {
        this.Authentication.logout().success(() => loc.path('/' + this.language + '/login/'));
    }

    url() {
        return loc.path();
    }

    reload() {
        route.reload();
    }

    license() {
        let m = modal.open({
            template: `

{{'monad.license' | translate}}

    <button class="btn btn-primary" ng-click="ok()">OK</button>

`,
            controller: ['$scope', '$modalInstance', ($scope, $modalInstance) => {
                $scope.ok = $modalInstance.close;
            }]
        });
    }

};

RootController.$inject = ['$location', '$rootScope', '$route', '$translate', 'moAuthentication', 'moNavigation', '$modal', 'title', 'languages', 'theme'];

export {RootController};

<|endoftext|>


<commit_before>/**
 * Movement Controls
 *
 * @author Don McCurdy <dm@donmccurdy.com>
 */

const COMPONENT_SUFFIX = '-controls',
    MAX_DELTA = 0.2, // ms
    EPS = 10e-6;

module.exports = AFRAME.registerComponent('movement-controls', {

  /*******************************************************************
   * Schema
   */

  dependencies: ['rotation'],

  schema: {
    enabled:            { default: true },
    controls:           { default: ['gamepad', 'trackpad', 'keyboard', 'touch'] },
    speed:              { default: 0.3, min: 0 },
    fly:                { default: false },
    constrainToNavMesh: { default: false },
    camera:             { default: '[movement-controls] [camera]', type: 'selector' }
  },

  /*******************************************************************
   * Lifecycle
   */

  init: function () {
    const el = this.el;

    this.velocityCtrl = null;

    this.velocity = new THREE.Vector3();
    this.heading = new THREE.Quaternion();

    // Navigation
    this.navGroup = null;
    this.navNode = null;

    if (el.sceneEl.hasLoaded) {
      this.injectControls();
    } else {
      el.sceneEl.addEventListener('loaded', this.injectControls.bind(this));
    }
  },

  update: function (prevData) {
    const el = this.el;
    const data = this.data;
    const nav = el.sceneEl.systems.nav;
    if (el.sceneEl.hasLoaded) {
      this.injectControls();
    }
    if (nav && data.constrainToNavMesh !== prevData.constrainToNavMesh) {
      data.constrainToNavMesh
        ? nav.addAgent(this)
        : nav.removeAgent(this);
    }
  },

  injectControls: function () {
    const data = this.data;
    var name;

    for (let i = 0; i < data.controls.length; i++) {
      name = data.controls[i] + COMPONENT_SUFFIX;
      if (!this.el.components[name]) {
        this.el.setAttribute(name, '');
      }
    }
  },

  updateNavLocation: function () {
    this.navGroup = null;
    this.navNode = null;
  },

  /*******************************************************************
   * Tick
   */

  tick: (function () {
    const start = new THREE.Vector3();
    const end = new THREE.Vector3();
    const clampedEnd = new THREE.Vector3();

    return function (t, dt) {
      if (!dt) return;

      const el = this.el;
      const data = this.data;

      if (!data.enabled) return;

      this.updateVelocityCtrl();
      const velocityCtrl = this.velocityCtrl;
      const velocity = this.velocity;

      if (!velocityCtrl) return;

      // Update velocity. If FPS is too low, reset.
      if (dt / 1000 > MAX_DELTA) {
        velocity.set(0, 0, 0);
      } else {
        this.updateVelocity(dt);
      }

      if (data.constrainToNavMesh
          && velocityCtrl.isNavMeshConstrained !== false) {

        if (velocity.lengthSq() < EPS) return;

        start.copy(el.object3D.position);
        end
          .copy(velocity)
          .multiplyScalar(dt / 1000)
          .add(start);

        const nav = el.sceneEl.systems.nav;
        this.navGroup = this.navGroup === null ? nav.getGroup(start) : this.navGroup;
        this.navNode = this.navNode || nav.getNode(start, this.navGroup);
        this.navNode = nav.clampStep(start, end, this.navGroup, this.navNode, clampedEnd);
        el.object3D.position.copy(clampedEnd);
      } else if (el.hasAttribute('velocity')) {
        el.setAttribute('velocity', velocity);
      } else {
        el.object3D.position.x += velocity.x * dt / 1000;
        el.object3D.position.y += velocity.y * dt / 1000;
        el.object3D.position.z += velocity.z * dt / 1000;
      }

    };
  }()),

  /*******************************************************************
   * Movement
   */

  updateVelocityCtrl: function () {
    const data = this.data;
    if (data.enabled) {
      for (let i = 0, l = data.controls.length; i < l; i++) {
        const control = this.el.components[data.controls[i] + COMPONENT_SUFFIX];
        if (control && control.isVelocityActive()) {
          this.velocityCtrl = control;
          return;
        }
      }
      this.velocityCtrl = null;
    }
  },

  updateVelocity: (function () {
    const vector2 = new THREE.Vector2();
    const quaternion = new THREE.Quaternion();

    return function (dt) {
      let dVelocity;
      const el = this.el;
      const control = this.velocityCtrl;
      const velocity = this.velocity;
      const data = this.data;

      if (control) {
        if (control.getVelocityDelta) {
          dVelocity = control.getVelocityDelta(dt);
        } else if (control.getVelocity) {
          velocity.copy(control.getVelocity());
          return;
        } else if (control.getPositionDelta) {
          velocity.copy(control.getPositionDelta(dt).multiplyScalar(1000 / dt));
          return;
        } else {
          throw new Error('Incompatible movement controls: ', control);
        }
      }

      if (el.hasAttribute('velocity') && !data.constrainToNavMesh) {
        velocity.copy(this.el.getAttribute('velocity'));
      }

      if (dVelocity && data.enabled) {
        const cameraEl = data.camera;

        // Rotate to heading
        quaternion.copy(cameraEl.object3D.quaternion);
        quaternion.premultiply(el.object3D.quaternion);
        dVelocity.applyQuaternion(quaternion);

        const factor = dVelocity.length();
        if (data.fly) {
          velocity.copy(dVelocity);
          velocity.multiplyScalar(this.data.speed * 16.66667);
        } else {
          vector2.set(dVelocity.x, dVelocity.z);
          vector2.setLength(factor * this.data.speed * 16.66667);
          velocity.x = vector2.x;
          velocity.z = vector2.y;
        }
      }
    };

  }())
});
<commit_msg>fixing issue #340<commit_after>/**
 * Movement Controls
 *
 * @author Don McCurdy <dm@donmccurdy.com>
 */

const COMPONENT_SUFFIX = '-controls',
    MAX_DELTA = 0.2, // ms
    EPS = 10e-6;

module.exports = AFRAME.registerComponent('movement-controls', {

  /*******************************************************************
   * Schema
   */

  dependencies: ['rotation'],

  schema: {
    enabled:            { default: true },
    controls:           { default: ['gamepad', 'trackpad', 'keyboard', 'touch'] },
    speed:              { default: 0.3, min: 0 },
    fly:                { default: false },
    constrainToNavMesh: { default: false },
    camera:             { default: '[movement-controls] [camera]', type: 'selector' }
  },

  /*******************************************************************
   * Lifecycle
   */

  init: function () {
    const el = this.el;
    if (!this.data.camera) {
      this.data.camera = el.querySelector('[camera]')
    }
    this.velocityCtrl = null;

    this.velocity = new THREE.Vector3();
    this.heading = new THREE.Quaternion();

    // Navigation
    this.navGroup = null;
    this.navNode = null;

    if (el.sceneEl.hasLoaded) {
      this.injectControls();
    } else {
      el.sceneEl.addEventListener('loaded', this.injectControls.bind(this));
    }
  },

  update: function (prevData) {
    const el = this.el;
    const data = this.data;
    const nav = el.sceneEl.systems.nav;
    if (el.sceneEl.hasLoaded) {
      this.injectControls();
    }
    if (nav && data.constrainToNavMesh !== prevData.constrainToNavMesh) {
      data.constrainToNavMesh
        ? nav.addAgent(this)
        : nav.removeAgent(this);
    }
  },

  injectControls: function () {
    const data = this.data;
    var name;

    for (let i = 0; i < data.controls.length; i++) {
      name = data.controls[i] + COMPONENT_SUFFIX;
      if (!this.el.components[name]) {
        this.el.setAttribute(name, '');
      }
    }
  },

  updateNavLocation: function () {
    this.navGroup = null;
    this.navNode = null;
  },

  /*******************************************************************
   * Tick
   */

  tick: (function () {
    const start = new THREE.Vector3();
    const end = new THREE.Vector3();
    const clampedEnd = new THREE.Vector3();

    return function (t, dt) {
      if (!dt) return;

      const el = this.el;
      const data = this.data;

      if (!data.enabled) return;

      this.updateVelocityCtrl();
      const velocityCtrl = this.velocityCtrl;
      const velocity = this.velocity;

      if (!velocityCtrl) return;

      // Update velocity. If FPS is too low, reset.
      if (dt / 1000 > MAX_DELTA) {
        velocity.set(0, 0, 0);
      } else {
        this.updateVelocity(dt);
      }

      if (data.constrainToNavMesh
          && velocityCtrl.isNavMeshConstrained !== false) {

        if (velocity.lengthSq() < EPS) return;

        start.copy(el.object3D.position);
        end
          .copy(velocity)
          .multiplyScalar(dt / 1000)
          .add(start);

        const nav = el.sceneEl.systems.nav;
        this.navGroup = this.navGroup === null ? nav.getGroup(start) : this.navGroup;
        this.navNode = this.navNode || nav.getNode(start, this.navGroup);
        this.navNode = nav.clampStep(start, end, this.navGroup, this.navNode, clampedEnd);
        el.object3D.position.copy(clampedEnd);
      } else if (el.hasAttribute('velocity')) {
        el.setAttribute('velocity', velocity);
      } else {
        el.object3D.position.x += velocity.x * dt / 1000;
        el.object3D.position.y += velocity.y * dt / 1000;
        el.object3D.position.z += velocity.z * dt / 1000;
      }

    };
  }()),

  /*******************************************************************
   * Movement
   */

  updateVelocityCtrl: function () {
    const data = this.data;
    if (data.enabled) {
      for (let i = 0, l = data.controls.length; i < l; i++) {
        const control = this.el.components[data.controls[i] + COMPONENT_SUFFIX];
        if (control && control.isVelocityActive()) {
          this.velocityCtrl = control;
          return;
        }
      }
      this.velocityCtrl = null;
    }
  },

  updateVelocity: (function () {
    const vector2 = new THREE.Vector2();
    const quaternion = new THREE.Quaternion();

    return function (dt) {
      let dVelocity;
      const el = this.el;
      const control = this.velocityCtrl;
      const velocity = this.velocity;
      const data = this.data;

      if (control) {
        if (control.getVelocityDelta) {
          dVelocity = control.getVelocityDelta(dt);
        } else if (control.getVelocity) {
          velocity.copy(control.getVelocity());
          return;
        } else if (control.getPositionDelta) {
          velocity.copy(control.getPositionDelta(dt).multiplyScalar(1000 / dt));
          return;
        } else {
          throw new Error('Incompatible movement controls: ', control);
        }
      }

      if (el.hasAttribute('velocity') && !data.constrainToNavMesh) {
        velocity.copy(this.el.getAttribute('velocity'));
      }

      if (dVelocity && data.enabled) {
        const cameraEl = data.camera;

        // Rotate to heading
        quaternion.copy(cameraEl.object3D.quaternion);
        quaternion.premultiply(el.object3D.quaternion);
        dVelocity.applyQuaternion(quaternion);

        const factor = dVelocity.length();
        if (data.fly) {
          velocity.copy(dVelocity);
          velocity.multiplyScalar(this.data.speed * 16.66667);
        } else {
          vector2.set(dVelocity.x, dVelocity.z);
          vector2.setLength(factor * this.data.speed * 16.66667);
          velocity.x = vector2.x;
          velocity.z = vector2.y;
        }
      }
    };

  }())
});
<|endoftext|>


<commit_before>/**
 * @module Core
 */
define([
    'require.text!modules/dialogs/dialogs-template.html',
    'core/modules/GelatoView'
], function(
    Template,
    GelatoView
) {

    /**
     * @class GelatoDialogs
     * @extends GelatoView
     */
    var GelatoDialogs = GelatoView.extend({
        /**
         * @method initialize
         * @constructor
         */
        initialize: function() {
            this.dialog = null;
            this.element = null;
            this.state = 'hidden';
            this.render();
        },
        /**
         * @property el
         * @type String
         */
        el: 'body',
        /**
         * @method render
         * @returns {GelatoDialogs}
         */
        render: function() {
            this.renderTemplate(Template, 'gelato-dialogs');
            return this;
        },
        /**
         * @property events
         * @type Object
         */
        events: {
            'vclick button': 'handleClickButton',
            'vclick .button': 'handleClickButton'
        },
        /**
         * @method hide
         * @returns {GelatoDialogs}
         */
        close: function() {
            this.dialog.modal('hide');
            return this;
        },
        /**
         * @method getName
         * @returns {String}
         */
        getName: function() {
            return this.element ? this.element.data('name') : null;
        },
        /**
         * @method handleClickButton
         * @param event
         */
        handleClickButton: function(event) {
            var buttonAction = $(event.currentTarget).data('action');
            var dialogName = this.getName();
            if (buttonAction) {
                this.trigger(dialogName + ':' + buttonAction, event);
                this.trigger(dialogName + ':click', buttonAction, event);
                this.trigger('button:click', dialogName + ':' + buttonAction, event);
            } else {
                this.trigger('button:click', dialogName, event);
            }
        },
        /**
         * @method handleModalHide
         * @param {Event} event
         */
        handleModalHide: function(event) {
            this.state = 'hide';
            this.trigger('hide', event);
        },
        /**
         * @method handleModalHidden
         * @param {Event} event
         */
        handleModalHidden: function(event) {
            $(event.target).find('*').off();
            this.state = 'hidden';
            this.dialog = null;
            this.element = null;
            this.trigger('hidden', event);
        },
        /**
         * @method handleModalShow
         * @param {Event} event
         */
        handleModalShow: function(event) {
            this.state = 'show';
            this.trigger('show', event);
        },
        /**
         * @method handleModalShown
         * @param {Event} event
         */
        handleModalShown: function(event) {
            this.state = 'shown';
            this.trigger('shown', event);
        },
        /**
         * @method open
         * @param {String} name
         * @param {Object} [options]
         * @returns {GelatoDialogs}
         */
        open: function(name, options) {
            options = options || {};
            options.backdrop = options.backdrop || 'static';
            options.keyboard = options.keyboard || false;
            options.show = options.show || true;
            options.remote = options.remote || false;
            if (this.state === 'hidden') {
                this.element = this.$('gelato-dialog[data-name="' + name + '"]');
                if (this.element.length) {
                    this.dialog = this.element.find('[role="dialog"]');
                    this.dialog.one('show.bs.modal', $.proxy(this.handleModalShow, this));
                    this.dialog.one('shown.bs.modal', $.proxy(this.handleModalShown, this));
                    this.dialog.one('hide.bs.modal', $.proxy(this.handleModalHide, this));
                    this.dialog.one('hidden.bs.modal', $.proxy(this.handleModalHidden, this));
                    this.dialog.modal(options);
                } else {
                    console.error(new Error('Dialog "' + name +  '" does not exist.'));
                }
            }
            return this;
        }
    });

    return GelatoDialogs;

});
<commit_msg>Pass the jquery dialog element rather than click event.<commit_after>/**
 * @module Core
 */
define([
    'require.text!modules/dialogs/dialogs-template.html',
    'core/modules/GelatoView'
], function(
    Template,
    GelatoView
) {

    /**
     * @class GelatoDialogs
     * @extends GelatoView
     */
    var GelatoDialogs = GelatoView.extend({
        /**
         * @method initialize
         * @constructor
         */
        initialize: function() {
            this.dialog = null;
            this.element = null;
            this.state = 'hidden';
            this.render();
        },
        /**
         * @property el
         * @type String
         */
        el: 'body',
        /**
         * @method render
         * @returns {GelatoDialogs}
         */
        render: function() {
            this.renderTemplate(Template, 'gelato-dialogs');
            return this;
        },
        /**
         * @property events
         * @type Object
         */
        events: {
            'vclick button': 'handleClickButton',
            'vclick .button': 'handleClickButton'
        },
        /**
         * @method hide
         * @returns {GelatoDialogs}
         */
        close: function() {
            this.dialog.modal('hide');
            return this;
        },
        /**
         * @method getName
         * @returns {String}
         */
        getName: function() {
            return this.element ? this.element.data('name') : null;
        },
        /**
         * @method handleClickButton
         * @param event
         */
        handleClickButton: function(event) {
            var buttonAction = $(event.currentTarget).data('action');
            var dialogName = this.getName();
            if (buttonAction) {
                this.trigger(dialogName + ':' + buttonAction, this.dialog);
                this.trigger(dialogName + ':click', buttonAction, this.dialog);
                this.trigger('button:click', dialogName + ':' + buttonAction, this.dialog);
            } else {
                this.trigger('button:click', dialogName, this.dialog);
            }
        },
        /**
         * @method handleModalHide
         * @param {Event} event
         */
        handleModalHide: function(event) {
            this.state = 'hide';
            this.trigger('hide', event);
        },
        /**
         * @method handleModalHidden
         * @param {Event} event
         */
        handleModalHidden: function(event) {
            $(event.target).find('*').off();
            this.state = 'hidden';
            this.dialog = null;
            this.element = null;
            this.trigger('hidden', event);
        },
        /**
         * @method handleModalShow
         * @param {Event} event
         */
        handleModalShow: function(event) {
            this.state = 'show';
            this.trigger('show', event);
        },
        /**
         * @method handleModalShown
         * @param {Event} event
         */
        handleModalShown: function(event) {
            this.state = 'shown';
            this.trigger('shown', event);
        },
        /**
         * @method open
         * @param {String} name
         * @param {Object} [options]
         * @returns {GelatoDialogs}
         */
        open: function(name, options) {
            options = options || {};
            options.backdrop = options.backdrop || 'static';
            options.keyboard = options.keyboard || false;
            options.show = options.show || true;
            options.remote = options.remote || false;
            if (this.state === 'hidden') {
                this.element = this.$('gelato-dialog[data-name="' + name + '"]');
                if (this.element.length) {
                    this.dialog = this.element.find('[role="dialog"]');
                    this.dialog.one('show.bs.modal', $.proxy(this.handleModalShow, this));
                    this.dialog.one('shown.bs.modal', $.proxy(this.handleModalShown, this));
                    this.dialog.one('hide.bs.modal', $.proxy(this.handleModalHide, this));
                    this.dialog.one('hidden.bs.modal', $.proxy(this.handleModalHidden, this));
                    this.dialog.modal(options);
                } else {
                    console.error(new Error('Dialog "' + name +  '" does not exist.'));
                }
            }
            return this;
        }
    });

    return GelatoDialogs;

});
<|endoftext|>