<commit_before>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import ConfiguredRadium from './ConfiguredRadium';
import baseStyles from './baseStyles';
import BurgerIcon from './BurgerIcon';
import CrossIcon from './CrossIcon';

export default (styles) => {

  return ConfiguredRadium(React.createClass({

    propTypes: {
      customBurgerIcon: React.PropTypes.element,
      customCrossIcon: React.PropTypes.element,
      id: React.PropTypes.string,
      isOpen: React.PropTypes.bool,
      noOverlay: React.PropTypes.bool,
      onStateChange: React.PropTypes.func,
      outerContainerId: React.PropTypes.string,
      pageWrapId: React.PropTypes.string,
      right: React.PropTypes.bool,
      styles: React.PropTypes.object,
      width: React.PropTypes.number
    },

    toggleMenu() {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      const newState = { isOpen: !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper(id, wrapperStyles, set) {
      const html = document.querySelector('html');
      const body = document.querySelector('body');
      const wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      const builtStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (const prop in builtStyles) {
        if (builtStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? builtStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach((element) => {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles(el, index) {
      const propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      let output = baseStyles[el] ? [baseStyles[el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: () => {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState() {
      return { isOpen: false };
    },

    componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Warn if the selected menu requires external wrapper elements
      // but none were supplied.
      if (styles.pageWrap && !this.props.pageWrapId) {
        console.warn('No pageWrapId supplied');
      }

      if (styles.outerContainer && !this.props.outerContainerId) {
        console.warn('No outerContainerId supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount() {
      window.onkeydown = this.listenForClose;
    },

    componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate() {
      if (styles.svg && this.isMounted()) {
        const morphShape = ReactDOM.findDOMNode(this, 'bm-morph-shape');
        let Snap, s, path;

        try {
          // This will throw with Webpack.
          Snap = require('snapsvg');
          s = Snap(morphShape);
          path = s.select('path');
        } catch (e) {
          console.warn('It looks like you might be using Webpack. Unfortunately, Elastic and Bubble are not currently supported with Webpack builds due to their Snap.svg dependency. See https://github.com/adobe-webplatform/Snap.svg/issues/341 for more info.');
          return;
        }

        if (this.state.isOpen) {
          // Animate SVG path.
          styles.svg.animate(path);
        } else {
          // Reset path (timeout ensures animation happens off screen).
          setTimeout(() => {
            path.attr('d', styles.svg.pathInitial);
          }, 300);
        }
      }
    },

    componentWillReceiveProps(nextProps) {
      const propDiff = nextProps.isOpen !== this.props.isOpen;
      const stateDiff = nextProps.isOpen !== this.state.isOpen;

      if (typeof nextProps.isOpen !== 'undefined' && (propDiff || stateDiff)) {
        this.toggleMenu();
      }
    },

    render() {
      let items, svg, overlay;

      // Add styles to user-defined menu items.
      if (this.props.children) {
        items = React.Children.map(this.props.children, (item, index) => {
          const extraProps = {
            key: index,
            style: this.getStyles('item', index)
          };
          return React.cloneElement(item, extraProps);
        });
      }

      // Add a morph shape for animations that use SVG.
      if (styles.svg) {
        svg = (

            <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 800" preserveAspectRatio="none">
              <path d={ styles.svg.pathInitial }/>
            </svg>

        );
      }

      if (!this.props.noOverlay) {
        overlay =

;
      }

      return (

          { overlay }

            { svg }

                { items }

              <CrossIcon onClick={ this.toggleMenu } styles={ this.props.styles } customIcon={ this.props.customCrossIcon } />

          <BurgerIcon onClick={ this.toggleMenu } styles={ this.props.styles } customIcon={ this.props.customBurgerIcon } />

      );
    }
  }));
};
<commit_msg>Fix condition<commit_after>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import ConfiguredRadium from './ConfiguredRadium';
import baseStyles from './baseStyles';
import BurgerIcon from './BurgerIcon';
import CrossIcon from './CrossIcon';

export default (styles) => {

  return ConfiguredRadium(React.createClass({

    propTypes: {
      customBurgerIcon: React.PropTypes.element,
      customCrossIcon: React.PropTypes.element,
      id: React.PropTypes.string,
      isOpen: React.PropTypes.bool,
      noOverlay: React.PropTypes.bool,
      onStateChange: React.PropTypes.func,
      outerContainerId: React.PropTypes.string,
      pageWrapId: React.PropTypes.string,
      right: React.PropTypes.bool,
      styles: React.PropTypes.object,
      width: React.PropTypes.number
    },

    toggleMenu() {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      const newState = { isOpen: !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper(id, wrapperStyles, set) {
      const html = document.querySelector('html');
      const body = document.querySelector('body');
      const wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      const builtStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (const prop in builtStyles) {
        if (builtStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? builtStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach((element) => {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles(el, index) {
      const propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      let output = baseStyles[el] ? [baseStyles[el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: () => {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState() {
      return { isOpen: false };
    },

    componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Warn if the selected menu requires external wrapper elements
      // but none were supplied.
      if (styles.pageWrap && !this.props.pageWrapId) {
        console.warn('No pageWrapId supplied');
      }

      if (styles.outerContainer && !this.props.outerContainerId) {
        console.warn('No outerContainerId supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount() {
      window.onkeydown = this.listenForClose;
    },

    componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate() {
      if (styles.svg && this.isMounted()) {
        const morphShape = ReactDOM.findDOMNode(this, 'bm-morph-shape');
        let Snap, s, path;

        try {
          // This will throw with Webpack.
          Snap = require('snapsvg');
          s = Snap(morphShape);
          path = s.select('path');
        } catch (e) {
          console.warn('It looks like you might be using Webpack. Unfortunately, Elastic and Bubble are not currently supported with Webpack builds due to their Snap.svg dependency. See https://github.com/adobe-webplatform/Snap.svg/issues/341 for more info.');
          return;
        }

        if (this.state.isOpen) {
          // Animate SVG path.
          styles.svg.animate(path);
        } else {
          // Reset path (timeout ensures animation happens off screen).
          setTimeout(() => {
            path.attr('d', styles.svg.pathInitial);
          }, 300);
        }
      }
    },

    componentWillReceiveProps(nextProps) {
      if (typeof nextProps.isOpen !== 'undefined' && nextProps.isOpen !== this.state.isOpen) {
        this.toggleMenu();
      }
    },

    render() {
      let items, svg, overlay;

      // Add styles to user-defined menu items.
      if (this.props.children) {
        items = React.Children.map(this.props.children, (item, index) => {
          const extraProps = {
            key: index,
            style: this.getStyles('item', index)
          };
          return React.cloneElement(item, extraProps);
        });
      }

      // Add a morph shape for animations that use SVG.
      if (styles.svg) {
        svg = (

            <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 800" preserveAspectRatio="none">
              <path d={ styles.svg.pathInitial }/>
            </svg>

        );
      }

      if (!this.props.noOverlay) {
        overlay =

;
      }

      return (

          { overlay }

            { svg }

                { items }

              <CrossIcon onClick={ this.toggleMenu } styles={ this.props.styles } customIcon={ this.props.customCrossIcon } />

          <BurgerIcon onClick={ this.toggleMenu } styles={ this.props.styles } customIcon={ this.props.customBurgerIcon } />

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


<commit_before>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import Radium from 'radium';
import baseStyles from './baseStyles';
import BurgerIcon from './BurgerIcon';
import CrossIcon from './CrossIcon';

export default (styles) => {

  return Radium(React.createClass({

    propTypes: {
      customBurgerIcon: React.PropTypes.oneOfType([React.PropTypes.element, React.PropTypes.oneOf([false])]),
      customCrossIcon: React.PropTypes.oneOfType([React.PropTypes.element, React.PropTypes.oneOf([false])]),
      id: React.PropTypes.string,
      isOpen: React.PropTypes.bool,
      noOverlay: React.PropTypes.bool,
      onStateChange: React.PropTypes.func,
      outerContainerId: styles && styles.outerContainer ? React.PropTypes.string.isRequired : React.PropTypes.string,
      pageWrapId: styles && styles.pageWrap ? React.PropTypes.string.isRequired : React.PropTypes.string,
      right: React.PropTypes.bool,
      styles: React.PropTypes.object,
      width: React.PropTypes.number
    },

    toggleMenu() {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      const newState = { isOpen: !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper(id, wrapperStyles, set) {
      const html = document.querySelector('html');
      const body = document.querySelector('body');
      const wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      const builtStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (const prop in builtStyles) {
        if (builtStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? builtStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach((element) => {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles(el, index) {
      const propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      let output = baseStyles[el] ? [baseStyles[el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: () => {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState() {
      return { isOpen: false };
    },

    componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount() {
      window.onkeydown = this.listenForClose;
    },

    componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate() {
      if (styles.svg && this.isMounted()) {
        const morphShape = ReactDOM.findDOMNode(this, 'bm-morph-shape');
        let Snap, s, path;

        try {
          // This will throw with Webpack.
          Snap = require('snapsvg');
          s = Snap(morphShape);
          path = s.select('path');
        } catch (e) {
          console.warn('It looks like you might be using Webpack. Unfortunately, Elastic and Bubble are not currently supported with Webpack builds due to their Snap.svg dependency. See https://github.com/adobe-webplatform/Snap.svg/issues/341 for more info.');
          return;
        }

        if (this.state.isOpen) {
          // Animate SVG path.
          styles.svg.animate(path);
        } else {
          // Reset path (timeout ensures animation happens off screen).
          setTimeout(() => {
            path.attr('d', styles.svg.pathInitial);
          }, 300);
        }
      }
    },

    componentWillReceiveProps(nextProps) {
      if (typeof nextProps.isOpen !== 'undefined' && nextProps.isOpen !== this.state.isOpen) {
        this.toggleMenu();
      }
    },

    render() {
      return (

          {!this.props.noOverlay ?

 : null}

            {styles.svg ? (

                <svg width="100%" height="100%" viewBox="0 0 100 800" preserveAspectRatio="none">
                  <path d={styles.svg.pathInitial}/>
                </svg>

            ) : null}

                {React.Children.map(this.props.children, (item, index) => {
                  const extraProps = {
                    key: index,
                    style: this.getStyles('item', index)
                  };
                  return React.cloneElement(item, extraProps);
                })}

              <CrossIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customCrossIcon ? this.props.customCrossIcon : null} />

          <BurgerIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customBurgerIcon ? this.props.customBurgerIcon : null} />

      );
    }
  }));
};
<commit_msg>Allow initial open state to be set by props for animations with wrapper elements<commit_after>'use strict';

import React from 'react';
import ReactDOM from 'react-dom';
import Radium from 'radium';
import baseStyles from './baseStyles';
import BurgerIcon from './BurgerIcon';
import CrossIcon from './CrossIcon';

export default (styles) => {

  return Radium(React.createClass({

    propTypes: {
      customBurgerIcon: React.PropTypes.oneOfType([React.PropTypes.element, React.PropTypes.oneOf([false])]),
      customCrossIcon: React.PropTypes.oneOfType([React.PropTypes.element, React.PropTypes.oneOf([false])]),
      id: React.PropTypes.string,
      isOpen: React.PropTypes.bool,
      noOverlay: React.PropTypes.bool,
      onStateChange: React.PropTypes.func,
      outerContainerId: styles && styles.outerContainer ? React.PropTypes.string.isRequired : React.PropTypes.string,
      pageWrapId: styles && styles.pageWrap ? React.PropTypes.string.isRequired : React.PropTypes.string,
      right: React.PropTypes.bool,
      styles: React.PropTypes.object,
      width: React.PropTypes.number
    },

    toggleMenu() {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      const newState = { isOpen: !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper(id, wrapperStyles, set) {
      const html = document.querySelector('html');
      const body = document.querySelector('body');
      const wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      const builtStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (const prop in builtStyles) {
        if (builtStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? builtStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach((element) => {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles(el, index) {
      const propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      let output = baseStyles[el] ? [baseStyles[el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: () => {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState() {
      const initialIsOpenProp = this.props && typeof this.props.isOpen !== 'undefined';
      return { isOpen: initialIsOpenProp ? this.props.isOpen : false };
    },

    componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount() {
      window.onkeydown = this.listenForClose;

      // Allow initial open state to be set by props for animations with wrapper elements.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate() {
      if (styles.svg && this.isMounted()) {
        const morphShape = ReactDOM.findDOMNode(this, 'bm-morph-shape');
        let Snap, s, path;

        try {
          // This will throw with Webpack.
          Snap = require('snapsvg');
          s = Snap(morphShape);
          path = s.select('path');
        } catch (e) {
          console.warn('It looks like you might be using Webpack. Unfortunately, Elastic and Bubble are not currently supported with Webpack builds due to their Snap.svg dependency. See https://github.com/adobe-webplatform/Snap.svg/issues/341 for more info.');
          return;
        }

        if (this.state.isOpen) {
          // Animate SVG path.
          styles.svg.animate(path);
        } else {
          // Reset path (timeout ensures animation happens off screen).
          setTimeout(() => {
            path.attr('d', styles.svg.pathInitial);
          }, 300);
        }
      }
    },

    componentWillReceiveProps(nextProps) {
      if (typeof nextProps.isOpen !== 'undefined' && nextProps.isOpen !== this.state.isOpen) {
        this.toggleMenu();
      }
    },

    render() {
      return (

          {!this.props.noOverlay ?

 : null}

            {styles.svg ? (

                <svg width="100%" height="100%" viewBox="0 0 100 800" preserveAspectRatio="none">
                  <path d={styles.svg.pathInitial}/>
                </svg>

            ) : null}

                {React.Children.map(this.props.children, (item, index) => {
                  const extraProps = {
                    key: index,
                    style: this.getStyles('item', index)
                  };
                  return React.cloneElement(item, extraProps);
                })}

              <CrossIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customCrossIcon ? this.props.customCrossIcon : null} />

          <BurgerIcon onClick={this.toggleMenu} styles={this.props.styles} customIcon={this.props.customBurgerIcon ? this.props.customBurgerIcon : null} />

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


<commit_before>var expect = require('expect.js'),
    common = require('./common');
    _ = require('underscore')._,
    sinon = require("sinon"),
    models = require("../lib/server-models"),
    request = require('superagent'),
    mandrill = require("mandrill-api"),
    outbox = [],

describe("SUPERUSER SENDS FOLLOWUP EMAILS (BROWSER)", function() {
    var browser = null;

    if (process.env.SKIP_SELENIUM_TESTS) {
        return;
    }
    this.timeout(60000); // Extra long timeout for selenium :(

    before(function(done) {
        this.timeout(240000);

        /* Mock Mandrill's API here */

        mandrill.Mandrill = function(apiKey) {

            this.messages = {
                send: function(messageObj) {
                    outbox.push(messageObj.message);
                }
            }
        };

        common.getSeleniumBrowser(function (theBrowser) {
            browser = theBrowser;
            common.standardSetup(function() {
                event = common.server.db.events.findWhere({shortName: "writers-at-work"});
                event.set("open", true);
                done();
            });
        });
    });

    after(function(done) {
        browser.quit().then(function() {
            common.standardShutdown(done);
        });
    });

    function generateUserData() {
        var clock = sinon.useFakeTimers(0, "setTimeout", "clearTimeout", "Date");

        var session = event.get("sessions").at(1);
        session.set("approved", true);

        session.set("hangout-url", "http://example.com");

        var user_one = common.server.db.users.get(1);
        user_one.set("displayName", "Srishti");
        user_one.set("picture", "http://pldb.media.mit.edu/face/srishti");

        var preferredContact = {};
        preferredContact.emailInfo = "srishakatux@gmail.com";
        preferredContact.twitterHandle = "srishakatux";

        user_one.set("preferredContact", preferredContact)

        var user_two = common.server.db.users.get(2);
        user_two.set("displayName", "Unhangout Developer");
        user_two.set("picture", "https://lh3.googleusercontent.com/-OP7MAxbSCvs/AAAAAAAAAAI/AAAAAAAAAEA/js2MqRDWiJk/photo.jpg");

        var user_three = common.server.db.users.get(3);
        user_three.set("displayName", "Jules");
        user_three.set("picture", "http://lh4.googleusercontent.com/-8NHi4O5-AF0/AAAAAAAAAAI/AAAAAAAAAAA/8kJJNYEwztM/s32-c/photo.jpg");

        var superuser1 = common.server.db.users.findWhere({"sock-key": "superuser1"});

        event.get("connectedUsers").add(user_one);
        event.get("connectedUsers").add(user_two);
        event.get("connectedUsers").add(user_three);
        event.get("connectedUsers").add(superuser1);

        session.addConnectedParticipant(user_one);
        session.addConnectedParticipant(user_two);
        session.addConnectedParticipant(user_three);

        var history = {event: {}, sessions: {}};

        history.sessions[session.id] = {"1": {start: 0, total: 1000}, "2": {start: 0, total: 1000}, "3": {start: 0, total: 1000}};

        clock.restore();

        var userData = [];

        _.each(history, function(elapsedTime, userId) {

            //Get the user object for a specific ID
            var user = common.server.db.users.get(userId);

            // Find all userIDs for users who shared sessions with me at this event.
            var userIds = event.getUserIdsSharingSessionsWith(userId);

            // get user objects for the IDs.
            var users = _.map(userIds, function(userId) {
                return common.server.db.users.get(userId);
            });

            userData.push({ user: user, users: users });

        });

        return userData;

    };

    it("Is prompted to login when unauthenticated", function(done) {
        browser.get(common.URL);
        browser.byCss("#login-first-button").click();
        browser.waitForSelector("#login-first-modal h4");
        browser.byCss("#login-first-modal h4").getText().then(function(text) {
            expect(text).to.eql("Please log in!");
            done();
        });
    });

    it("Super User sends followup emails", function(done) {

        browser.mockAuthenticate("superuser1");
        //Superuser goes to the event page.  Connect a socket to a session.
        browser.get(common.URL + "/event/" + event.id)
        browser.waitForEventReady(event, "superuser1");
        browser.byCss("#submit-contact-info").click();

        userData = generateUserData();
        userData.unshift(null);

        request.get(common.URL + '/followup/event/' + event.id + '/participant_1')
            .send({userData: userData, participantIndex: 1})
            .redirects(0)
            .end(function(res) {
                done();
            });

        browser.byCss(".admin-button").click();
        browser.waitForSelector("#superuser-page-for-followupemail");
        browser.byCss("#superuser-page-for-followupemail").click();

        browser.get(common.URL + '/followup/event/' + event.id + '/participant_1');

        browser.byCss("#send-email-to-all").click();

        browser.waitForSelector("#send-now-button");

        browser.byCss("#send-now-button").click().then(function() {
            generateUserData();

            var noOfUsers = event.get("connectedUsers").length;

            expect(outbox.length).to.be(noOfUsers);

            expect(outbox[0].to[0].email).to.be("regular2@example.com");
            expect(outbox[0].from_email).to.be("noreply@media.mit.edu");
            expect(outbox[0].subject).to.be("Unhangout Event: Followup");

            //expect(outbox[0].html).to.be("Unhangout Event: Followup");

            outbox.length =  0;

        });

    });

});
<commit_msg>few more changes<commit_after>var expect = require('expect.js'),
    common = require('./common');
    _ = require('underscore')._,
    sinon = require("sinon"),
    models = require("../lib/server-models"),
    request = require('superagent'),
    mandrill = require("mandrill-api"),
    outbox = [],

describe("SUPERUSER SENDS FOLLOWUP EMAILS (BROWSER)", function() {
    var browser = null;

    if (process.env.SKIP_SELENIUM_TESTS) {
        return;
    }
    this.timeout(60000); // Extra long timeout for selenium :(

    before(function(done) {
        this.timeout(240000);

        /* Mock Mandrill's API here */

        mandrill.Mandrill = function(apiKey) {

            this.messages = {
                send: function(messageObj) {
                    outbox.push(messageObj.message);
                }
            }
        };

        common.getSeleniumBrowser(function (theBrowser) {
            browser = theBrowser;
            common.standardSetup(function() {
                event = common.server.db.events.findWhere({shortName: "writers-at-work"});
                event.set("open", true);
                done();
            });
        });
    });

    after(function(done) {
        browser.quit().then(function() {
            common.standardShutdown(done);
        });
    });

    function generateUserData() {
        var clock = sinon.useFakeTimers(1, "setTimeout", "clearTimeout", "Date");

        var session = event.get("sessions").at(1);
        session.set("approved", true);

        session.set("hangout-url", "http://example.com");

        var user_one = common.server.db.users.get(1);
        user_one.set("displayName", "Srishti");
        user_one.set("picture", "http://pldb.media.mit.edu/face/srishti");

        var preferredContact = {};
        preferredContact.emailInfo = "srishakatux@gmail.com";
        preferredContact.twitterHandle = "srishakatux";

        user_one.set("preferredContact", preferredContact)

        var user_two = common.server.db.users.get(2);
        user_two.set("displayName", "Unhangout Developer");
        user_two.set("picture", "https://lh3.googleusercontent.com/-OP7MAxbSCvs/AAAAAAAAAAI/AAAAAAAAAEA/js2MqRDWiJk/photo.jpg");

        var user_three = common.server.db.users.get(3);
        user_three.set("displayName", "Jules");
        user_three.set("picture", "http://lh4.googleusercontent.com/-8NHi4O5-AF0/AAAAAAAAAAI/AAAAAAAAAAA/8kJJNYEwztM/s32-c/photo.jpg");

        var superuser1 = common.server.db.users.findWhere({"sock-key": "superuser1"});

        event.get("connectedUsers").add(user_one);
        event.get("connectedUsers").add(user_two);
        event.get("connectedUsers").add(user_three);
        event.get("connectedUsers").add(superuser1);

        session.addConnectedParticipant(user_one);
        session.addConnectedParticipant(user_two);
        session.addConnectedParticipant(user_three);

        var history = {events: {}, sessions: {}};

        history.event = {"1" : {start: 0, total: 1000}, "2": {start: 0, total: 1000}, "3" : {start: 0, total: 1000}};

        history.sessions[session.id] = {"1": {"1": {total: 2346, start: 0}, "2": {total: 2346, start: 0}, "3": {total: 2346, start: 0}}};

        clock.restore();

        var userData = [];

        _.each(history, function(elapsedTime, userId) {

            //Get the user object for a specific ID
            var user = common.server.db.users.get(userId);

            // Find all userIDs for users who shared sessions with me at this event.
            var userIds = event.getUserIdsSharingSessionsWith(userId);

            // get user objects for the IDs.
            var users = _.map(userIds, function(userId) {
                return common.server.db.users.get(userId);
            });

            userData.push({ user: user, users: users });

        });

        return userData;

    };

    it("Is prompted to login when unauthenticated", function(done) {
        browser.get(common.URL);
        browser.byCss("#login-first-button").click();
        browser.waitForSelector("#login-first-modal h4");
        browser.byCss("#login-first-modal h4").getText().then(function(text) {
            expect(text).to.eql("Please log in!");
            done();
        });
    });

    it("Super User sends followup emails", function(done) {

        browser.mockAuthenticate("superuser1");
        //Superuser goes to the event page.  Connect a socket to a session.
        browser.get(common.URL + "/event/" + event.id)
        browser.waitForEventReady(event, "superuser1");
        browser.byCss("#submit-contact-info").click();

        userData = generateUserData();
        userData.unshift(null);

        request.get(common.URL + '/followup/event/' + event.id + '/participant_1')
            .send({userData: userData, participantIndex: 1})
            .redirects(0)
            .end(function(res) {
                done();
            });

        browser.byCss(".admin-button").click();
        browser.waitForSelector("#superuser-page-for-followupemail");
        browser.byCss("#superuser-page-for-followupemail").click();

        browser.get(common.URL + '/followup/event/' + event.id + '/participant_1');

        browser.byCss("#send-email-to-all").click();

        browser.waitForSelector("#send-now-button");

        browser.byCss("#send-now-button").click().then(function() {
            generateUserData();

            var noOfUsers = event.get("connectedUsers").length;

            expect(outbox.length).to.be(noOfUsers);

            expect(outbox[0].to[0].email).to.be("regular2@example.com");
            expect(outbox[0].from_email).to.be("noreply@media.mit.edu");
            expect(outbox[0].subject).to.be("Unhangout Event: Followup");
            expect(outbox[0].html).to.not.eql(-1);
            //expect(outbox[0].html).to.be("Unhangout Event: Followup");

            outbox.length =  0;

        });

    });

});
<|endoftext|>


<commit_before>import { StreamApiNotSupportedError, InsecureContextError } from "./errors.js";
import { imageDataFromVideo } from "./image-data.js";
import { eventOn, timeout } from "callforth";
import shimGetUserMedia from "./shimGetUserMedia";

class Camera {
  constructor(videoEl, stream) {
    this.videoEl = videoEl;
    this.stream = stream;
  }

  stop() {
    this.stream.getTracks().forEach(track => track.stop());
  }

  captureFrame() {
    return imageDataFromVideo(this.videoEl);
  }

  getCapabilities() {
    const [track] = this.stream.getVideoTracks();
    // Firefox does not yet support getCapabilities as of August 2020
    return track?.getCapabilities?.() ?? {};
  }
}

const narrowDownFacingMode = async camera => {
  // Modern phones often have multipe front/rear cameras.
  // Sometimes special purpose cameras like the wide-angle camera are picked
  // by default. Those are not optimal for scanning QR codes but standard
  // media constraints don't allow us to specify which camera we want exactly.
  // However, explicitly picking the first entry in the list of all videoinput
  // devices for as the default front camera and the last entry as the default
  // rear camera seems to be a workaround.
  const devices = (await navigator.mediaDevices.enumerateDevices()).filter(
    ({ kind }) => kind === "videoinput"
  );

  if (devices.length > 2) {
    const frontCamera = devices[0];
    const rearCamera = devices[devices.length - 1];

    switch (camera) {
      case "auto":
        return { deviceId: { exact: rearCamera.deviceId } };
      case "rear":
        return { deviceId: { exact: rearCamera.deviceId } };
      case "front":
        return { deviceId: { exact: frontCamera.deviceId } };
      default:
        return undefined;
    }
  } else {
    switch (camera) {
      case "auto":
        return { facingMode: { ideal: "environment" } };
      case "rear":
        return { facingMode: { exact: "environment" } };
      case "front":
        return { facingMode: { exact: "user" } };
      default:
        return undefined;
    }
  }
};

export default async function(videoEl, { camera, torch }) {
  // At least in Chrome `navigator.mediaDevices` is undefined when the page is
  // loaded using HTTP rather than HTTPS. Thus `STREAM_API_NOT_SUPPORTED` is
  // initialized with `false` although the API might actually be supported.
  // So although `getUserMedia` already should have a built-in mechanism to
  // detect insecure context (by throwing `NotAllowedError`), we have to do a
  // manual check before even calling `getUserMedia`.
  if (window.isSecureContext !== true) {
    throw new InsecureContextError();
  }

  if (navigator?.mediaDevices?.getUserMedia === undefined) {
    throw new StreamApiNotSupportedError();
  }

  // This is a browser API only shim. It patches the global window object which
  // is not available during SSR. So we lazily apply this shim at runtime.
  await shimGetUserMedia();

  const constraints = {
    audio: false,
    video: {
      width: { min: 360, ideal: 640, max: 1920 },
      height: { min: 240, ideal: 480, max: 1080 },
      ...(await narrowDownFacingMode(camera))
    }
  };

  const stream = await navigator.mediaDevices.getUserMedia(constraints);

  if (videoEl.srcObject !== undefined) {
    videoEl.srcObject = stream;
  } else if (videoEl.mozSrcObject !== undefined) {
    videoEl.mozSrcObject = stream;
  } else if (window.URL.createObjectURL) {
    videoEl.src = window.URL.createObjectURL(stream);
  } else if (window.webkitURL) {
    videoEl.src = window.webkitURL.createObjectURL(stream);
  } else {
    videoEl.src = stream;
  }

  await eventOn(videoEl, "loadeddata");

  // According to: https://oberhofer.co/mediastreamtrack-and-its-capabilities/#queryingcapabilities
  // On some devices, getCapabilities only returns a non-empty object after
  // some delay. There is no appropriate event so we have to add a constant timeout
  await timeout(500);

  if (torch) {
    const [track] = stream.getVideoTracks();
    const capabilities = track.getCapabilities();

    if (capabilities.torch) {
      track.applyConstraints({ advanced: [{ torch: true }] });
    } else {
      console.warn("device does not support torch capability");
    }
  }

  return new Camera(videoEl, stream);
}
<commit_msg>fix: application freezes when stream is paused or stopped<commit_after>import { StreamApiNotSupportedError, InsecureContextError } from "./errors.js";
import { imageDataFromVideo } from "./image-data.js";
import { eventOn, timeout } from "callforth";
import shimGetUserMedia from "./shimGetUserMedia";

class Camera {
  constructor(videoEl, stream) {
    this.videoEl = videoEl;
    this.stream = stream;
  }

  stop() {
    this.videoEl.srcObject = null;

    this.stream.getTracks().forEach(track => {
      this.stream.removeTrack(track);
      track.stop();
    });
  }

  captureFrame() {
    return imageDataFromVideo(this.videoEl);
  }

  getCapabilities() {
    const [track] = this.stream.getVideoTracks();
    // Firefox does not yet support getCapabilities as of August 2020
    return track?.getCapabilities?.() ?? {};
  }
}

const narrowDownFacingMode = async camera => {
  // Modern phones often have multipe front/rear cameras.
  // Sometimes special purpose cameras like the wide-angle camera are picked
  // by default. Those are not optimal for scanning QR codes but standard
  // media constraints don't allow us to specify which camera we want exactly.
  // However, explicitly picking the first entry in the list of all videoinput
  // devices for as the default front camera and the last entry as the default
  // rear camera seems to be a workaround.
  const devices = (await navigator.mediaDevices.enumerateDevices()).filter(
    ({ kind }) => kind === "videoinput"
  );

  if (devices.length > 2) {
    const frontCamera = devices[0];
    const rearCamera = devices[devices.length - 1];

    switch (camera) {
      case "auto":
        return { deviceId: { exact: rearCamera.deviceId } };
      case "rear":
        return { deviceId: { exact: rearCamera.deviceId } };
      case "front":
        return { deviceId: { exact: frontCamera.deviceId } };
      default:
        return undefined;
    }
  } else {
    switch (camera) {
      case "auto":
        return { facingMode: { ideal: "environment" } };
      case "rear":
        return { facingMode: { exact: "environment" } };
      case "front":
        return { facingMode: { exact: "user" } };
      default:
        return undefined;
    }
  }
};

export default async function(videoEl, { camera, torch }) {
  // At least in Chrome `navigator.mediaDevices` is undefined when the page is
  // loaded using HTTP rather than HTTPS. Thus `STREAM_API_NOT_SUPPORTED` is
  // initialized with `false` although the API might actually be supported.
  // So although `getUserMedia` already should have a built-in mechanism to
  // detect insecure context (by throwing `NotAllowedError`), we have to do a
  // manual check before even calling `getUserMedia`.
  if (window.isSecureContext !== true) {
    throw new InsecureContextError();
  }

  if (navigator?.mediaDevices?.getUserMedia === undefined) {
    throw new StreamApiNotSupportedError();
  }

  // This is a browser API only shim. It patches the global window object which
  // is not available during SSR. So we lazily apply this shim at runtime.
  await shimGetUserMedia();

  const constraints = {
    audio: false,
    video: {
      width: { min: 360, ideal: 640, max: 1920 },
      height: { min: 240, ideal: 480, max: 1080 },
      ...(await narrowDownFacingMode(camera))
    }
  };

  const stream = await navigator.mediaDevices.getUserMedia(constraints);

  if (videoEl.srcObject !== undefined) {
    videoEl.srcObject = stream;
  } else if (videoEl.mozSrcObject !== undefined) {
    videoEl.mozSrcObject = stream;
  } else if (window.URL.createObjectURL) {
    videoEl.src = window.URL.createObjectURL(stream);
  } else if (window.webkitURL) {
    videoEl.src = window.webkitURL.createObjectURL(stream);
  } else {
    videoEl.src = stream;
  }

  await eventOn(videoEl, "loadeddata");

  // According to: https://oberhofer.co/mediastreamtrack-and-its-capabilities/#queryingcapabilities
  // On some devices, getCapabilities only returns a non-empty object after
  // some delay. There is no appropriate event so we have to add a constant timeout
  await timeout(500);

  if (torch) {
    const [track] = stream.getVideoTracks();
    const capabilities = track.getCapabilities();

    if (capabilities.torch) {
      track.applyConstraints({ advanced: [{ torch: true }] });
    } else {
      console.warn("device does not support torch capability");
    }
  }

  return new Camera(videoEl, stream);
}
<|endoftext|>


<commit_before>import itemTypes from './data/itemTypes.json';
import blockTypes from './data/blockTypes.json';
import defaultToolbar from './data/toolbar.json';
import auth from '../auth';
import clone from 'clone';

var toolbars = {};

var lastBlockId = 0;
blockTypes.forEach(blockType => {
  if(blockType.id > lastBlockId) {
    lastBlockId = blockType.id;
  }
});

var lastItemId = 0;
itemTypes.forEach(itemType => {
  if(itemType.id > lastItemId) {
    lastItemId = itemType.id;
  }
});

// function getById(types, id) {
//   for(let i = 0; i < types.length; i++) {
//     let type = types[i];
//     if(type.id == id) {
//       return type;
//     }
//   }
// }

export default {
  getToolbar(token) {
    return auth.getUser(token).then(user => {
      if(!toolbars[user.id]) {
        toolbars[user.id] = defaultToolbar;
      }

      return toolbars[user.id];
    });
  },
  setToolbarItem(token, position, type, id) {
    return auth.getUser(token).then(user => {
      var toolbar = toolbars[user.id];
      toolbar[position] = {type, id};
    });
  },
  removeToolbarItem(token, position) {
    return auth.getUser(token).then(user => {
      var toolbar = toolbars[user.id];
      toolbar[position] = null;
    });
  },
  getAll() {
    return {
      itemTypes,
      blockTypes
    };
  },
  getItemTypes(token, ids) {
    if(typeof ids == 'string') {
      ids = ids.split(',');
    }

    return itemTypes.filter(type => ids.includes(type.id.toString()));
  },
  getBlockTypes(token, ids) {
    if(typeof ids == 'string') {
      ids = ids.split(',');
    }

    return blockTypes.filter(type => ids.includes(type.id.toString()));
  },
  updateBlockCode(token, id, codeObj) {
    let original = this.getBlockTypes(token, [id])[0];

    let updated = clone(original);
    updated.code = codeObj;
    updated.id = ++lastBlockId;
    blockTypes.push(updated);

    original.newerVersion = updated.id;
    return updated;
  },
  updateItemCode(token, id, codeObj) {
    let original = this.getItemTypes(token, [id])[0];

    let updated = clone(original);
    updated.code = codeObj;
    updated.id = ++lastItemId;
    itemTypes.push(updated);

    original.newerVersion = updated.id;
    return updated;
  },
  addBlockType(token, codeObj, material, name) {
    var newType = {};
    newType.code = codeObj;
    newType.id = ++lastBlockId;
    newType.material = material;
    newType.name = name;
    newType.icon = 'code';
    blockTypes.push(newType);

    return newType;
  },
  addItemType(token, codeObj, props) {
    var newType = {};
    newType.code = codeObj;
    newType.id = ++lastItemId;
    newType.name = props.name;
    newType.crosshairIcon = props.crosshairIcon;
    newType.adjacentActive = props.adjacentActive;
    newType.icon = 'code';
    itemTypes.push(newType);

    return newType;
  }
};
<commit_msg>make new items not have newerVersion, so they reflect they are the latest<commit_after>import itemTypes from './data/itemTypes.json';
import blockTypes from './data/blockTypes.json';
import defaultToolbar from './data/toolbar.json';
import auth from '../auth';
import clone from 'clone';

var toolbars = {};

var lastBlockId = 0;
blockTypes.forEach(blockType => {
  if(blockType.id > lastBlockId) {
    lastBlockId = blockType.id;
  }
});

var lastItemId = 0;
itemTypes.forEach(itemType => {
  if(itemType.id > lastItemId) {
    lastItemId = itemType.id;
  }
});

// function getById(types, id) {
//   for(let i = 0; i < types.length; i++) {
//     let type = types[i];
//     if(type.id == id) {
//       return type;
//     }
//   }
// }

export default {
  getToolbar(token) {
    return auth.getUser(token).then(user => {
      if(!toolbars[user.id]) {
        toolbars[user.id] = defaultToolbar;
      }

      return toolbars[user.id];
    });
  },
  setToolbarItem(token, position, type, id) {
    return auth.getUser(token).then(user => {
      var toolbar = toolbars[user.id];
      toolbar[position] = {type, id};
    });
  },
  removeToolbarItem(token, position) {
    return auth.getUser(token).then(user => {
      var toolbar = toolbars[user.id];
      toolbar[position] = null;
    });
  },
  getAll() {
    return {
      itemTypes,
      blockTypes
    };
  },
  getItemTypes(token, ids) {
    if(typeof ids == 'string') {
      ids = ids.split(',');
    }

    return itemTypes.filter(type => ids.includes(type.id.toString()));
  },
  getBlockTypes(token, ids) {
    if(typeof ids == 'string') {
      ids = ids.split(',');
    }

    return blockTypes.filter(type => ids.includes(type.id.toString()));
  },
  updateBlockCode(token, id, codeObj) {
    let original = this.getBlockTypes(token, [id])[0];

    let updated = clone(original);
    updated.code = codeObj;
    updated.id = ++lastBlockId;
    delete updated.newerVersion;
    blockTypes.push(updated);

    original.newerVersion = updated.id;
    return updated;
  },
  updateItemCode(token, id, codeObj) {
    let original = this.getItemTypes(token, [id])[0];

    let updated = clone(original);
    updated.code = codeObj;
    updated.id = ++lastItemId;
    delete updated.newerVersion;
    itemTypes.push(updated);

    original.newerVersion = updated.id;
    return updated;
  },
  addBlockType(token, codeObj, material, name) {
    var newType = {};
    newType.code = codeObj;
    newType.id = ++lastBlockId;
    newType.material = material;
    newType.name = name;
    newType.icon = 'code';
    blockTypes.push(newType);

    return newType;
  },
  addItemType(token, codeObj, props) {
    var newType = {};
    newType.code = codeObj;
    newType.id = ++lastItemId;
    newType.name = props.name;
    newType.crosshairIcon = props.crosshairIcon;
    newType.adjacentActive = props.adjacentActive;
    newType.icon = 'code';
    itemTypes.push(newType);

    return newType;
  }
};
<|endoftext|>


<commit_before>// old comment, left for future reference because may re-implement
// Browserify entry point for the functions.js bundle (yay JavaScript!)
// global.js already contains jQuery, so in our config.js file, we are exposing it to other files like this one in the
// `require` array. Also in config.js, jquery is listed in `external` array for this bundle. This combination lets this
// file use the jquery module bundled with global.js, instead of including it twice!

var _ = require('underscore');
var Backbone = require('backbone');
var $ = require('jquery');
Backbone.$ = $;

$(document)
    .ajaxStart(function () {})
    .ajaxStop(function () {})
;

$(function()
{
    $(".hiButton").on( "click", function() {
      alert('hi');
    });

    var ListView = Backbone.View.extend({
        el: $('.backbone'), // attaches `this.el` to an existing element.

        events: {
            'click button#add': 'addItem'
        },
        initialize: function(){
            // every function that uses 'this' as the current object should be in here
            _.bindAll(this, 'render', 'addItem'); // fixes loss of context for 'this' within methods

            this.counter = 0; //total nubmer of items added so far
            this.render(); // not all views are self-rendering. This one is.
        },

        render: function(){
            $(this.el).append("<button id='add'>Add list item</button>");
            $(this.el).append("

");
        },

        addItem: function(){
            this.counter++;
            $('ul', this.el).append("
hello world"+this.counter+"
");
        }

    });

    var listView = new ListView();

});
<commit_msg>end of tutorial 3<commit_after>// old comment, left for future reference because may re-implement
// Browserify entry point for the functions.js bundle (yay JavaScript!)
// global.js already contains jQuery, so in our config.js file, we are exposing it to other files like this one in the
// `require` array. Also in config.js, jquery is listed in `external` array for this bundle. This combination lets this
// file use the jquery module bundled with global.js, instead of including it twice!

var _ = require('underscore');
var Backbone = require('backbone');
var $ = require('jquery');
Backbone.$ = $;

$(document)
    .ajaxStart(function () {})
    .ajaxStop(function () {})
;

$(function()
{
    $(".hiButton").on( "click", function() {
      alert('hi');
    });

    var Item = Backbone.Model.extend({
        defaults: {
            part1: 'hello',
            part2: 'world'
        }
    });

    var List = Backbone.Collection.extend({
        model: Item
    });

    var ListView = Backbone.View.extend({
        el: $('.backbone'), // attaches `this.el` to an existing element.

        events: {
            'click button#add': 'addItem'
        },

        initialize: function(){
            // every function that uses 'this' as the current object should be in here
            _.bindAll(this, 'render', 'addItem', 'appendItem'); // fixes loss of context for 'this' within methods

            this.collection = new List();
            this.collection.bind('add', this.appendItem); //collection event binder

            this.counter = 0; //total nubmer of items added so far
            this.render(); // not all views are self-rendering. This one is.
        },

        render: function(){

            //Save reference to this so it can be accessed from within the scope of the callback below
            var self = this;
            $(this.el).append("<button id='add'>Add list item</button>");
            $(this.el).append("

");
            _(this.collection.models).each(function(item){ //in case collection is not empty
                self.appendItem(item);
            }, this);
        },

        //addItem() now deals solely with models/collections.
        addItem: function(){
            this.counter++;
            var item = new Item();
            item.set({
               part2: item.get('part2') + this.counter //modify item details
            });
            this.collection.add(item); // add item to collection; view is updated via event 'add'
        },

        //View updates are delegated to the add event listener appendItem() below.
        appendItem: function(item){
            $('ul', this.el).append("
"+item.get('part1')+" "+item.get('part2')+"
");
        }

    });

    var listView = new ListView();

});
<|endoftext|>


<commit_before>function TypeAheadControl(jsonObj, box, orig, submit, maxchars, getName, getEntityId, geticon, ie6hack, alwaysShow, maxResults, getKeywords)
{
    //
    // Squirrel away the parameters we were given
    //
    this.elementList = jsonObj;
    this.textBox = box;
    this.origin = orig;
    this.submit = submit;
    this.results = 0;
    this.alwaysShow = alwaysShow;
    this.maxResults = maxResults;
    this.ie6hack = ie6hack;
    this.maxchars = maxchars;
    this.getName = getName;
    this.getEntityId = getEntityId;
    this.geticon = geticon;
    this.getKeywords = getKeywords;
}

TypeAheadControl.prototype.draw = function(setFocus) {

    //
    // Make a closure on this so that the embedded functions
    // get access to it.
    //
    var myThis = this;

    //
    // Set up the 'dropDown'
    //
    this.dropDown = document.createElement('div');
    this.dropDown.className = 'IdPSelectDropDown';
    this.dropDown.style.visibility = 'hidden';

    this.dropDown.style.width = this.textBox.offsetWidth;
    this.dropDown.current = -1;
    document.body.appendChild(this.dropDown);

    //
    // mouse listeners for the dropdown box
    //
    this.dropDown.onmouseover = function(event) {
        if (!event) {
            event = window.event;
        }
        var target;
        if (event.target){
            target = event.target;
        }
        if (typeof target == 'undefined') {
            target = event.srcElement;
        }
        myThis.select(target);
    };

    this.dropDown.onmousedown = function(event) {
        if (-1 != myThis.dropDown.current) {
            myThis.textBox.value = myThis.results[myThis.dropDown.current][0];
        }
    };

    //
    // Add the listeners to the text box
    //
    this.textBox.onkeyup = function(event) {
        //
        // get window event if needed (because of browser oddities)
        //
        if (!event) {
            event = window.event;
        }
        myThis.handleKeyUp(event);
    };

    this.textBox.onkeydown = function(event) {
        if (!event) {
            event = window.event;
        }

        myThis.handleKeyDown(event);
    };

    this.textBox.onblur = function() {
        myThis.hideDrop();
    };

    this.textBox.onfocus = function() {
        myThis.handleChange();
    };

    if (null == setFocus || setFocus) {
        this.textBox.focus();
    }
};

//
// Given a name return the first maxresults, or all possibles
//
TypeAheadControl.prototype.getPossible = function(name) {
    var possibles = [];
    var inIndex = 0;
    var outIndex = 0;
    var strIndex = 0;
    var str;
    var ostr;

    name = name.toLowerCase();

    while (outIndex <= this.maxResults && inIndex < this.elementList.length) {
        var hit = false;
        var thisName = this.getName(this.elementList[inIndex]);

        //
        // Check name
        //
        if (thisName.toLowerCase().indexOf(name) != -1) {
            hit = true;
        }
        //
        // Check entityID
        //
        if (!hit && this.getEntityId(this.elementList[inIndex]).toLowerCase().indexOf(name) != -1) {
            hit = true;
        }

        if (!hit) {
            var thisKeywords = this.getKeywords(this.elementList[inIndex]);
            if (null != thisKeywords &&
                thisKeywords.toLowerCase().indexOf(name) != -1) {
                hit = true;
            }
        }

        if (hit) {
            possibles[outIndex] = [thisName, this.getEntityId(this.elementList[inIndex]), this.geticon(this.elementList[inIndex])];
            outIndex ++;
        }

        inIndex ++;
    }
    //
    // reset the cursor to the top
    //
    this.dropDown.current = -1;

    return possibles;
};

TypeAheadControl.prototype.handleKeyUp = function(event) {
    var key = event.keyCode;

    if (27 == key) {
        //
        // Escape - clear
        //
        this.textBox.value = '';
        this.handleChange();
    } else if (8 == key || 32 == key || (key >= 46 && key < 112) || key > 123) {
        //
        // Backspace, Space and >=Del to <F1 and > F12
        //
        this.handleChange();
    }
};

TypeAheadControl.prototype.handleKeyDown = function(event) {

    var key = event.keyCode;

    if (38 == key) {
        //
        // up arrow
        //
        this.upSelect();

    } else if (40 == key) {
        //
        // down arrow
        //
        this.downSelect();
    }
};

TypeAheadControl.prototype.hideDrop = function() {
    var i = 0;
    if (null !== this.ie6hack) {
        while (i < this.ie6hack.length) {
            this.ie6hack[i].style.visibility = 'visible';
            i++;
        }
    }
    this.dropDown.style.visibility = 'hidden';

    if (-1 == this.dropDown.current) {
        this.doUnselected();
    }
};

TypeAheadControl.prototype.showDrop = function() {
    var i = 0;
    if (null !== this.ie6hack) {
        while (i < this.ie6hack.length) {
            this.ie6hack[i].style.visibility = 'hidden';
            i++;
        }
    }
    this.dropDown.style.visibility = 'visible';
};

TypeAheadControl.prototype.doSelected = function() {
    this.submit.disabled = false;
};

TypeAheadControl.prototype.doUnselected = function() {
    this.submit.disabled = true;
};

TypeAheadControl.prototype.handleChange = function() {

    var val = this.textBox.value;
    var res = this.getPossible(val);

    if (0 === val.length ||
        0 === res.length ||
        (!this.alwaysShow && this.maxResults < res.length)) {
        this.hideDrop();
        this.doUnselected();
        this.results = [];
        this.dropDown.current = -1;
    } else {
        this.results = res;
        this.populateDropDown(res);
        if (1 == res.length) {
            this.select(this.dropDown.childNodes[0]);
            this.doSelected();
        } else {
            this.doUnselected();
        }
    }
};

//
// A lot of the stuff below comes from
// http://www.webreference.com/programming/javascript/ncz/column2
//
// With thanks to Nicholas C Zakas
//
TypeAheadControl.prototype.populateDropDown = function(list) {
    this.dropDown.innerHTML = '';
    var i = 0;
    var div;
    var img;
    var str;

    while (i < list.length) {
        div = document.createElement('div');
        str = list[i][0];

	if (null !== list[i][2]) {

	    img = document.createElement('img');
	    img.src = list[i][2];
	    img.width = 16;
	    img.height = 16;
	    img.alt = '';
	    div.appendChild(img);
	    //
	    // trim string back further in this case
	    //
	    if (str.length > this.maxchars - 2) {
		str = str.substring(0, this.maxchars - 2);
	    }
	    str = ' ' + str;
	} else {
	    if (str.length > this.maxchars) {
		str = str.substring(0, this.maxchars);
	    }
	}
        div.appendChild(document.createTextNode(str));

        this.dropDown.appendChild(div);
        i++;
    }
    var off = this.getXY();
    this.dropDown.style.left = off[0] + 'px';
    this.dropDown.style.top = off[1] + 'px';
    this.showDrop();
};

TypeAheadControl.prototype.getXY = function() {

    var node = this.textBox;
    var sumX = 0;
    var sumY = node.offsetHeight;

    while(node.tagName != 'BODY') {
        sumX += node.offsetLeft;
        sumY += node.offsetTop;
        node = node.offsetParent;
    }
    //
    // And add in the offset for the Body
    //
    sumX += node.offsetLeft;
    sumY += node.offsetTop;

    return [sumX, sumY];
};

TypeAheadControl.prototype.select = function(selected) {
    var i = 0;
    var node;
    this.dropDown.current = -1;
    this.doUnselected();
    while (i < this.dropDown.childNodes.length) {
        node = this.dropDown.childNodes[i];
        if (node == selected) {
            //
            // Highlight it
            //
            node.className = 'IdPSelectCurrent';
            //
            // turn on the button
            //
            this.doSelected();
            //
            // setup the cursor
            //
            this.dropDown.current = i;
            //
            // and the value for the Server
            //
            this.origin.value = this.results[i][1];
            this.origin.textValue = this.results[i][0];
        } else {
            node.className = '';
        }
        i++;
    }
    this.textBox.focus();
};

TypeAheadControl.prototype.downSelect = function() {
    if (this.results.length > 0) {

        if (-1 == this.dropDown.current) {
            //
            // mimic a select()
            //
            this.dropDown.current = 0;
            this.dropDown.childNodes[0].className = 'IdPSelectCurrent';
            this.doSelected();
            this.origin.value = this.results[0][1];
            this.origin.textValue = this.results[0][0];

        } else if (this.dropDown.current < (this.results.length-1)) {
            //
            // turn off highlight
            //
            this.dropDown.childNodes[this.dropDown.current].className = '';
            //
            // move cursor
            //
            this.dropDown.current++;
            //
            // and 'select'
            //
            this.dropDown.childNodes[this.dropDown.current].className = 'IdPSelectCurrent';
            this.doSelected();
            this.origin.value = this.results[this.dropDown.current][1];
            this.origin.textValue = this.results[this.dropDown.current][0];

        }
    }
};

TypeAheadControl.prototype.upSelect = function() {
    if ((this.results.length > 0) &&
        (this.dropDown.current > 0)) {

            //
            // turn off highlight
            //
            this.dropDown.childNodes[this.dropDown.current].className = '';
            //
            // move cursor
            //
            this.dropDown.current--;
            //
            // and 'select'
            //
            this.dropDown.childNodes[this.dropDown.current].className = 'IdPSelectCurrent';
            this.doSelected();
            this.origin.value = this.results[this.dropDown.current][1];
            this.origin.textValue = this.results[this.dropDown.current][0];
        }
};
<commit_msg>EDS-26 Add some ARIA annotations to the autocomplete.  Work in progress<commit_after>function TypeAheadControl(jsonObj, box, orig, submit, maxchars, getName, getEntityId, geticon, ie6hack, alwaysShow, maxResults, getKeywords)
{
    //
    // Squirrel away the parameters we were given
    //
    this.elementList = jsonObj;
    this.textBox = box;
    this.origin = orig;
    this.submit = submit;
    this.results = 0;
    this.alwaysShow = alwaysShow;
    this.maxResults = maxResults;
    this.ie6hack = ie6hack;
    this.maxchars = maxchars;
    this.getName = getName;
    this.getEntityId = getEntityId;
    this.geticon = geticon;
    this.getKeywords = getKeywords;
}

TypeAheadControl.prototype.draw = function(setFocus) {

    //
    // Make a closure on this so that the embedded functions
    // get access to it.
    //
    var myThis = this;

    //
    // Set up the 'dropDown'
    //
    this.dropDown = document.createElement('div');
    this.dropDown.className = 'IdPSelectDropDown';
    this.dropDown.style.visibility = 'hidden';

    this.dropDown.style.width = this.textBox.offsetWidth;
    this.dropDown.current = -1;
    this.textBox.setAttribute('role', 'listbox');
    document.body.appendChild(this.dropDown);

    //
    // Set ARIA on the input
    //
    this.textBox.setAttribute('role', 'combobox');
    this.textBox.setAttribute('aria-controls', 'IdPSelectDropDown');

    //
    // mouse listeners for the dropdown box
    //
    this.dropDown.onmouseover = function(event) {
        if (!event) {
            event = window.event;
        }
        var target;
        if (event.target){
            target = event.target;
        }
        if (typeof target == 'undefined') {
            target = event.srcElement;
        }
        myThis.select(target);
    };

    this.dropDown.onmousedown = function(event) {
        if (-1 != myThis.dropDown.current) {
            myThis.textBox.value = myThis.results[myThis.dropDown.current][0];
        }
    };

    //
    // Add the listeners to the text box
    //
    this.textBox.onkeyup = function(event) {
        //
        // get window event if needed (because of browser oddities)
        //
        if (!event) {
            event = window.event;
        }
        myThis.handleKeyUp(event);
    };

    this.textBox.onkeydown = function(event) {
        if (!event) {
            event = window.event;
        }

        myThis.handleKeyDown(event);
    };

    this.textBox.onblur = function() {
        myThis.hideDrop();
    };

    this.textBox.onfocus = function() {
        myThis.handleChange();
    };

    if (null == setFocus || setFocus) {
        this.textBox.focus();
    }
};

//
// Given a name return the first maxresults, or all possibles
//
TypeAheadControl.prototype.getPossible = function(name) {
    var possibles = [];
    var inIndex = 0;
    var outIndex = 0;
    var strIndex = 0;
    var str;
    var ostr;

    name = name.toLowerCase();

    while (outIndex <= this.maxResults && inIndex < this.elementList.length) {
        var hit = false;
        var thisName = this.getName(this.elementList[inIndex]);

        //
        // Check name
        //
        if (thisName.toLowerCase().indexOf(name) != -1) {
            hit = true;
        }
        //
        // Check entityID
        //
        if (!hit && this.getEntityId(this.elementList[inIndex]).toLowerCase().indexOf(name) != -1) {
            hit = true;
        }

        if (!hit) {
            var thisKeywords = this.getKeywords(this.elementList[inIndex]);
            if (null != thisKeywords &&
                thisKeywords.toLowerCase().indexOf(name) != -1) {
                hit = true;
            }
        }

        if (hit) {
            possibles[outIndex] = [thisName, this.getEntityId(this.elementList[inIndex]), this.geticon(this.elementList[inIndex])];
            outIndex ++;
        }

        inIndex ++;
    }
    //
    // reset the cursor to the top
    //
    this.dropDown.current = -1;

    return possibles;
};

TypeAheadControl.prototype.handleKeyUp = function(event) {
    var key = event.keyCode;

    if (27 == key) {
        //
        // Escape - clear
        //
        this.textBox.value = '';
        this.handleChange();
    } else if (8 == key || 32 == key || (key >= 46 && key < 112) || key > 123) {
        //
        // Backspace, Space and >=Del to <F1 and > F12
        //
        this.handleChange();
    }
};

TypeAheadControl.prototype.handleKeyDown = function(event) {

    var key = event.keyCode;

    if (38 == key) {
        //
        // up arrow
        //
        this.upSelect();

    } else if (40 == key) {
        //
        // down arrow
        //
        this.downSelect();
    }
};

TypeAheadControl.prototype.hideDrop = function() {
    var i = 0;
    if (null !== this.ie6hack) {
        while (i < this.ie6hack.length) {
            this.ie6hack[i].style.visibility = 'visible';
            i++;
        }
    }
    this.dropDown.style.visibility = 'hidden';
    this.dropDown.setAttribute('aria-expanded', 'false');

    if (-1 == this.dropDown.current) {
        this.doUnselected();
    }
};

TypeAheadControl.prototype.showDrop = function() {
    var i = 0;
    if (null !== this.ie6hack) {
        while (i < this.ie6hack.length) {
            this.ie6hack[i].style.visibility = 'hidden';
            i++;
        }
    }
    this.dropDown.style.visibility = 'visible';
    this.dropDown.setAttribute('aria-expanded', 'true');
};

TypeAheadControl.prototype.doSelected = function() {
    this.submit.disabled = false;
};

TypeAheadControl.prototype.doUnselected = function() {
    this.submit.disabled = true;
};

TypeAheadControl.prototype.handleChange = function() {

    var val = this.textBox.value;
    var res = this.getPossible(val);

    if (0 === val.length ||
        0 === res.length ||
        (!this.alwaysShow && this.maxResults < res.length)) {
        this.hideDrop();
        this.doUnselected();
        this.results = [];
        this.dropDown.current = -1;
    } else {
        this.results = res;
        this.populateDropDown(res);
        if (1 == res.length) {
            this.select(this.dropDown.childNodes[0]);
            this.doSelected();
        } else {
            this.doUnselected();
        }
    }
};

//
// A lot of the stuff below comes from
// http://www.webreference.com/programming/javascript/ncz/column2
//
// With thanks to Nicholas C Zakas
//
TypeAheadControl.prototype.populateDropDown = function(list) {
    this.dropDown.innerHTML = '';
    var i = 0;
    var div;
    var img;
    var str;

    while (i < list.length) {
        div = document.createElement('div');
        str = list[i][0];

	if (null !== list[i][2]) {

	    img = document.createElement('img');
	    img.src = list[i][2];
	    img.width = 16;
	    img.height = 16;
	    img.alt = '';
	    div.appendChild(img);
	    //
	    // trim string back further in this case
	    //
	    if (str.length > this.maxchars - 2) {
		str = str.substring(0, this.maxchars - 2);
	    }
	    str = ' ' + str;
	} else {
	    if (str.length > this.maxchars) {
		str = str.substring(0, this.maxchars);
	    }
	}
        div.appendChild(document.createTextNode(str));
        div.setAttribute('role', 'option');
        this.dropDown.appendChild(div);
        i++;
    }
    var off = this.getXY();
    this.dropDown.style.left = off[0] + 'px';
    this.dropDown.style.top = off[1] + 'px';
    this.showDrop();
};

TypeAheadControl.prototype.getXY = function() {

    var node = this.textBox;
    var sumX = 0;
    var sumY = node.offsetHeight;

    while(node.tagName != 'BODY') {
        sumX += node.offsetLeft;
        sumY += node.offsetTop;
        node = node.offsetParent;
    }
    //
    // And add in the offset for the Body
    //
    sumX += node.offsetLeft;
    sumY += node.offsetTop;

    return [sumX, sumY];
};

TypeAheadControl.prototype.select = function(selected) {
    var i = 0;
    var node;
    this.dropDown.current = -1;
    this.doUnselected();
    while (i < this.dropDown.childNodes.length) {
        node = this.dropDown.childNodes[i];
        if (node == selected) {
            //
            // Highlight it
            //
            node.className = 'IdPSelectCurrent';
            node.setAttribute('aria-selected', 'true');

            //
            // turn on the button
            //
            this.doSelected();
            //
            // setup the cursor
            //
            this.dropDown.current = i;
            //
            // and the value for the Server
            //
            this.origin.value = this.results[i][1];
            this.origin.textValue = this.results[i][0];
        } else {
            node.setAttribute('aria-selected', 'false');
            node.className = '';
        }
        i++;
    }
    this.textBox.focus();
};

TypeAheadControl.prototype.downSelect = function() {
    if (this.results.length > 0) {

        if (-1 == this.dropDown.current) {
            //
            // mimic a select()
            //
            this.dropDown.current = 0;
            this.dropDown.childNodes[0].className = 'IdPSelectCurrent';
            this.doSelected();
            this.origin.value = this.results[0][1];
            this.origin.textValue = this.results[0][0];

        } else if (this.dropDown.current < (this.results.length-1)) {
            //
            // turn off highlight
            //
            this.dropDown.childNodes[this.dropDown.current].className = '';
            //
            // move cursor
            //
            this.dropDown.current++;
            //
            // and 'select'
            //
            this.dropDown.childNodes[this.dropDown.current].className = 'IdPSelectCurrent';
            this.doSelected();
            this.origin.value = this.results[this.dropDown.current][1];
            this.origin.textValue = this.results[this.dropDown.current][0];

        }
    }
};

TypeAheadControl.prototype.upSelect = function() {
    if ((this.results.length > 0) &&
        (this.dropDown.current > 0)) {

            //
            // turn off highlight
            //
            this.dropDown.childNodes[this.dropDown.current].className = '';
            //
            // move cursor
            //
            this.dropDown.current--;
            //
            // and 'select'
            //
            this.dropDown.childNodes[this.dropDown.current].className = 'IdPSelectCurrent';
            this.doSelected();
            this.origin.value = this.results[this.dropDown.current][1];
            this.origin.textValue = this.results[this.dropDown.current][0];
        }
};
<|endoftext|>


<commit_before>/*
 * jquery-filestyle
 * doc: http://markusslima.github.io/jquery-filestyle/
 * github: https://github.com/markusslima/jquery-filestyle
 *
 * Copyright (c) 2017 Markus Vinicius da Silva Lima
 * Version 2.0.0
 * Licensed under the MIT license.
 */
!function(e){"use strict";var t=0,i=function(t,i){this.options=i,this.$elementjFilestyle=[],this.$element=e(t)};i.prototype={clear:function(){this.$element.val(""),this.$elementjFilestyle.find(":text").val(""),this.$elementjFilestyle.find(".count-jfilestyle").remove()},destroy:function(){this.$element.removeAttr("style").removeData("jfilestyle").val(""),this.$elementjFilestyle.remove()},disabled:function(e){if(!0===e)this.options.disabled||(this.$element.attr("disabled","true"),this.$elementjFilestyle.find("label").attr("disabled","true"),this.options.disabled=!0);else{if(!1!==e)return this.options.disabled;this.options.disabled&&(this.$element.removeAttr("disabled"),this.$elementjFilestyle.find("label").removeAttr("disabled"),this.options.disabled=!1)}},buttonBefore:function(e){if(!0===e)this.options.buttonBefore||(this.options.buttonBefore=!0,this.options.input&&(this.$elementjFilestyle.remove(),this.constructor(),this.pushNameFiles()));else{if(!1!==e)return this.options.buttonBefore;this.options.buttonBefore&&(this.options.buttonBefore=!1,this.options.input&&(this.$elementjFilestyle.remove(),this.constructor(),this.pushNameFiles()))}},input:function(e){if(!0===e)this.options.input||(this.options.input=!0,this.$elementjFilestyle.find("label").before(this.htmlInput()),this.$elementjFilestyle.find(".count-jfilestyle").remove(),this.pushNameFiles());else{if(!1!==e)return this.options.input;if(this.options.input){this.options.input=!1,this.$elementjFilestyle.find(":text").remove();var t=this.pushNameFiles();t.length>0&&this.$elementjFilestyle.find("label").append(' '+t.length+"")}}},text:function(e){if(void 0===e)return this.options.text;this.options.text=e,this.$elementjFilestyle.find("label span").html(this.options.text)},inputSize:function(e){if(void 0===e)return this.options.inputSize;this.options.inputSize=e,this.$elementjFilestyle.find(":text").css("width",this.options.inputSize)},placeholder:function(e){if(void 0===e)return this.options.placeholder;this.options.placeholder=e,this.$elementjFilestyle.find(":text").attr("placeholder",e)},htmlInput:function(){return this.options.input?'<input type="text" style="width:'+this.options.inputSize+'" placeholder="'+this.options.placeholder+'" disabled> ':""},pushNameFiles:function(){var e="",t=[];void 0===this.$element[0].files?t[0]={name:this.$element.value}:t=this.$element[0].files;for(var i=0;i<t.length;i++)e+=t[i].name.split("\\").pop()+", ";return""!==e?this.$elementjFilestyle.find(":text").val(e.replace(/\, $/g,"")):this.$elementjFilestyle.find(":text").val(""),t},constructor:function(){var i=this,n="",l=i.$element.attr("id");""!==l&&l||(l="jfilestyle-"+t,i.$element.attr({id:l}),t++),n='"+i.options.text+"",!0===i.options.buttonBefore?n+=i.htmlInput():n=i.htmlInput()+n,i.$elementjFilestyle=e('

'+n+"
"),i.$elementjFilestyle.find(".focus-jfilestyle").attr("tabindex","0").keypress(function(e){if(13===e.keyCode||32===e.charCode)return i.$elementjFilestyle.find("label").click(),!1}),i.$element.css({position:"absolute",clip:"rect(0px 0px 0px 0px)"}).attr("tabindex","-1").after(i.$elementjFilestyle),i.options.disabled&&i.$element.attr("disabled","true"),i.$elementjFilestyle.find('[name="filedrag"]').css({position:"absolute",width:"100%",height:i.$elementjFilestyle.height()+"px","z-index":-1}),i.$element.change(function(){var e=i.pushNameFiles();0==i.options.input?0==i.$elementjFilestyle.find(".count-jfilestyle").length?i.$elementjFilestyle.find("label").append(' '+e.length+""):0==e.length?i.$elementjFilestyle.find(".count-jfilestyle").remove():i.$elementjFilestyle.find(".count-jfilestyle").html(e.length):i.$elementjFilestyle.find(".count-jfilestyle").remove(),i.options.onChange(e)}),window.navigator.userAgent.search(/firefox/i)>-1&&this.$elementjFilestyle.find("label").click(function(){return i.$element.click(),!1}),e(document).on("dragover",function(t){if(!i.options.dragdrop)return!1;t.preventDefault(),t.stopPropagation(),e('[name="filedrag"]').css("z-index","9")}).on("drop",function(t){if(!i.options.dragdrop)return!1;t.preventDefault(),t.stopPropagation(),e('[name="filedrag"]').css("z-index","-1")}),i.$elementjFilestyle.find('[name="filedrag"]').on("dragover",function(e){e.preventDefault(),e.stopPropagation()}).on("dragenter",function(e){e.preventDefault(),e.stopPropagation()}).on("drop",function(t){if(!i.options.dragdrop)return!1;if(t.originalEvent.dataTransfer&&!i.options.disabled&&t.originalEvent.dataTransfer.files.length){t.preventDefault(),t.stopPropagation(),i.$element[0].files=t.originalEvent.dataTransfer.files;var n=i.pushNameFiles();0==i.options.input?0==i.$elementjFilestyle.find(".count-jfilestyle").length?i.$elementjFilestyle.find("label").append(' '+n.length+""):0==n.length?i.$elementjFilestyle.find(".count-jfilestyle").remove():i.$elementjFilestyle.find(".count-jfilestyle").html(n.length):i.$elementjFilestyle.find(".count-jfilestyle").remove(),i.options.onChange(n),e('[name="filedrag"]').css("z-index","-1")}})}};var n=e.fn.jfilestyle;e.fn.jfilestyle=function(t,n){var l="",s=this.each(function(){if("file"===e(this).attr("type")){var s=e(this),o=s.data("jfilestyle"),a=e.extend({},e.fn.jfilestyle.defaults,t,"object"==typeof t&&t);o||(s.data("jfilestyle",o=new i(this,a)),o.constructor()),"string"==typeof t&&(l=o[t](n))}});return void 0!==typeof l?l:s},e.fn.jfilestyle.defaults={text:"Choose file",input:!0,disabled:!1,buttonBefore:!1,inputSize:"200px",placeholder:"",dragdrop:!0,onChange:function(){}},e.fn.jfilestyle.noConflict=function(){return e.fn.jfilestyle=n,this},e(function(){e(".jfilestyle").each(function(){var t=e(this),i={text:t.attr("data-text"),input:"false"!==t.attr("data-input"),disabled:"true"===t.attr("data-disabled"),buttonBefore:"true"===t.attr("data-buttonBefore"),inputSize:t.attr("data-inputSize"),placeholder:t.attr("data-placeholder"),dragdrop:"false"!==t.attr("data-dragdrop")};t.jfilestyle(i)})})}(window.jQuery);<commit_msg>Correction verion 2.0<commit_after>/*
 * jquery-filestyle
 * doc: http://markusslima.github.io/jquery-filestyle/
 * github: https://github.com/markusslima/jquery-filestyle
 *
 * Copyright (c) 2017 Markus Vinicius da Silva Lima
 * Version 2.0.0
 * Licensed under the MIT license.
 */
!function(e){"use strict";var t=0,i=function(t,i){this.options=i,this.$elementjFilestyle=[],this.$element=e(t)};i.prototype={clear:function(){this.$element.val(""),this.$elementjFilestyle.find(":text").val(""),this.$elementjFilestyle.find(".count-jfilestyle").remove()},destroy:function(){this.$element.removeAttr("style").removeData("jfilestyle").val(""),this.$elementjFilestyle.remove()},dragdrop:function(e){return e!==!0&&e!==!1?this.options.dragdrop:void(this.options.dragdrop=e)},disabled:function(e){if(e===!0)this.options.disabled||(this.$element.attr("disabled","true"),this.$elementjFilestyle.find("label").attr("disabled","true"),this.options.disabled=!0);else{if(e!==!1)return this.options.disabled;this.options.disabled&&(this.$element.removeAttr("disabled"),this.$elementjFilestyle.find("label").removeAttr("disabled"),this.options.disabled=!1)}},buttonBefore:function(e){if(e===!0)this.options.buttonBefore||(this.options.buttonBefore=!0,this.options.input&&(this.$elementjFilestyle.remove(),this.constructor(),this.pushNameFiles()));else{if(e!==!1)return this.options.buttonBefore;this.options.buttonBefore&&(this.options.buttonBefore=!1,this.options.input&&(this.$elementjFilestyle.remove(),this.constructor(),this.pushNameFiles()))}},input:function(e){if(e===!0)this.options.input||(this.options.input=!0,this.$elementjFilestyle.find("label").before(this.htmlInput()),this.$elementjFilestyle.find(".count-jfilestyle").remove(),this.pushNameFiles());else{if(e!==!1)return this.options.input;if(this.options.input){this.options.input=!1,this.$elementjFilestyle.find(":text").remove();var t=this.pushNameFiles();t.length>0&&this.$elementjFilestyle.find("label").append(' '+t.length+"")}}},text:function(e){return void 0===e?this.options.text:(this.options.text=e,void this.$elementjFilestyle.find("label span").html(this.options.text))},inputSize:function(e){return void 0===e?this.options.inputSize:(this.options.inputSize=e,void this.$elementjFilestyle.find(":text").css("width",this.options.inputSize))},placeholder:function(e){return void 0===e?this.options.placeholder:(this.options.placeholder=e,void this.$elementjFilestyle.find(":text").attr("placeholder",e))},htmlInput:function(){return this.options.input?'<input type="text" style="width:'+this.options.inputSize+'" placeholder="'+this.options.placeholder+'" disabled> ':""},pushNameFiles:function(){var e="",t=[];void 0===this.$element[0].files?t[0]={name:this.$element.value}:t=this.$element[0].files;for(var i=0;i<t.length;i++)e+=t[i].name.split("\\").pop()+", ";return""!==e?this.$elementjFilestyle.find(":text").val(e.replace(/\, $/g,"")):this.$elementjFilestyle.find(":text").val(""),t},constructor:function(){var i=this,n="",l=i.$element.attr("id");""!==l&&l||(l="jfilestyle-"+t,i.$element.attr({id:l}),t++),n='"+i.options.text+"",i.options.buttonBefore===!0?n+=i.htmlInput():n=i.htmlInput()+n,i.$elementjFilestyle=e('

'+n+"
"),i.$elementjFilestyle.find(".focus-jfilestyle").attr("tabindex","0").keypress(function(e){return 13===e.keyCode||32===e.charCode?(i.$elementjFilestyle.find("label").click(),!1):void 0}),i.$element.css({position:"absolute",clip:"rect(0px 0px 0px 0px)"}).attr("tabindex","-1").after(i.$elementjFilestyle),i.options.disabled&&i.$element.attr("disabled","true"),i.$elementjFilestyle.find('[name="filedrag"]').css({position:"absolute",width:"100%",height:i.$elementjFilestyle.height()+"px","z-index":-1}),i.$element.change(function(){var e=i.pushNameFiles();0==i.options.input?0==i.$elementjFilestyle.find(".count-jfilestyle").length?i.$elementjFilestyle.find("label").append(' '+e.length+""):0==e.length?i.$elementjFilestyle.find(".count-jfilestyle").remove():i.$elementjFilestyle.find(".count-jfilestyle").html(e.length):i.$elementjFilestyle.find(".count-jfilestyle").remove(),i.options.onChange(e)}),window.navigator.userAgent.search(/firefox/i)>-1&&this.$elementjFilestyle.find("label").click(function(){return i.$element.click(),!1}),e(document).on("dragover",function(t){t.preventDefault(),t.stopPropagation(),i.options.dragdrop||e('[name="filedrag"]').css("z-index","9")}).on("drop",function(t){t.preventDefault(),t.stopPropagation(),i.options.dragdrop||e('[name="filedrag"]').css("z-index","-1")}),i.$elementjFilestyle.find('[name="filedrag"]').on("dragover",function(e){e.preventDefault(),e.stopPropagation()}).on("dragenter",function(e){e.preventDefault(),e.stopPropagation()}).on("drop",function(t){if(t.originalEvent.dataTransfer&&!i.options.disabled&&i.options.dragdrop&&t.originalEvent.dataTransfer.files.length){t.preventDefault(),t.stopPropagation(),i.$element[0].files=t.originalEvent.dataTransfer.files;var n=i.pushNameFiles();0==i.options.input?0==i.$elementjFilestyle.find(".count-jfilestyle").length?i.$elementjFilestyle.find("label").append(' '+n.length+""):0==n.length?i.$elementjFilestyle.find(".count-jfilestyle").remove():i.$elementjFilestyle.find(".count-jfilestyle").html(n.length):i.$elementjFilestyle.find(".count-jfilestyle").remove(),e('[name="filedrag"]').css("z-index","-1")}})}};var n=e.fn.jfilestyle;e.fn.jfilestyle=function(t,n){var l="",s=this.each(function(){if("file"===e(this).attr("type")){var s=e(this),o=s.data("jfilestyle"),a=e.extend({},e.fn.jfilestyle.defaults,t,"object"==typeof t&&t);o||(s.data("jfilestyle",o=new i(this,a)),o.constructor()),"string"==typeof t&&(l=o[t](n))}});return void 0!==typeof l?l:s},e.fn.jfilestyle.defaults={text:"Choose file",input:!0,disabled:!1,buttonBefore:!1,inputSize:"200px",placeholder:"",dragdrop:!0,onChange:function(){}},e.fn.jfilestyle.noConflict=function(){return e.fn.jfilestyle=n,this},e(function(){e(".jfilestyle").each(function(){var t=e(this),i={text:t.attr("data-text"),input:"false"!==t.attr("data-input"),disabled:"true"===t.attr("data-disabled"),buttonBefore:"true"===t.attr("data-buttonBefore"),inputSize:t.attr("data-inputSize"),placeholder:t.attr("data-placeholder"),dragdrop:"false"!==t.attr("data-dragdrop")};t.jfilestyle(i)})})}(window.jQuery);<|endoftext|>