<commit_before>
/**
 * Created by Raphaël Morineau on 28 Oct 2016.
 */
import React, { Component } from 'react'
import InfiniteScroller from 'react-infinite'
import ListItem from 'material-ui/List/ListItem'
import Popover from 'material-ui/Popover/Popover'
import TextField from 'material-ui/TextField/TextField'
import SelectionsPresenter from './SelectionsPresenter'
import { getChildrenLength, areEqual } from './utils'
import PropTypes from 'prop-types'
import { selectFieldTypes } from './types'
import { selectFieldDefaultProps } from './defaultProps'

class SelectField extends Component {
  constructor(props, context) {
    super(props, context)
    const { children, value, multiple, showAutocompleteThreshold } = props
    const itemsLength = getChildrenLength(children)
    this.state = {
      isOpen: false,
      isFocused: false,
      itemsLength,
      showAutocomplete: (itemsLength > showAutocompleteThreshold) || false,
      selectedItems: value || (multiple ? [] : null),
      searchText: ''
    }
    this.menuItems = []
  }

  componentWillReceiveProps(nextProps) {
    if (!areEqual(nextProps.value, this.state.selectedItems)) {
      this.setState({ selectedItems: nextProps.value })
    }
    if (!areEqual(nextProps.children, this.props.children)) {
      const itemsLength = getChildrenLength(nextProps.children)
      this.setState({
        itemsLength,
        showAutocomplete: itemsLength > this.props.showAutocompleteThreshold
      })
    }
  }

  componentDidMount() {
    // Potential problem with Popover ?
    // https://github.com/callemall/material-ui/blob/master/src/DropDownMenu/DropDownMenu.js#L237
    if (this.props.openImmediately) this.openMenu()
  }

  onFocus = () => this.setState({ isFocused: true })

  onBlur = (event) => {
    if (!this.state.isOpen) this.setState({ isFocused: false })
  }

  closeMenu = (reason) => {
    const { onChange, name } = this.props
    if (reason) this.setState({ isFocused: false }) // if reason === 'clickaway' or 'offscreen'
    this.setState({ isOpen: false, searchText: '' }, () => {
      if (!reason) {
        this.root.focus()
      }
      onChange(this.state.selectedItems, name)
    })
  }

  openMenu() {
    if (!this.state.isOpen) this.props.onMenuOpen()
    if (this.state.itemsLength) this.setState({ isOpen: true }, () => this.focusTextField())
  }

  // FIXME: both focusTextField and focusMenuItem don't really focus the targeted element, user must hit another key to trigger the actual focus... need to find a solution for a true direct focus
  focusMenuItem(index) {
    const targetMenuItem = this.menuItems.find(item => {
      return !!item && (index ? item.props.tabIndex === index : true)
    })
    if (targetMenuItem) targetMenuItem.applyFocusState('keyboard-focused')
  }

  focusTextField() {
    this.state.showAutocomplete && this.searchTextField
      ? this.searchTextField.focus()
      : this.focusMenuItem()
  }

  clearTextField(callback) {
    this.props.keepSearchOnSelect
      ? callback() // don't reset the autocomplete
      : this.setState({ searchText: '' }, callback)
  }

  /**
   * Main Component Wrapper methods
   */
  // toggle instead of close ? (in case user changes targetOrigin/anchorOrigin)
  handleClick = (event) => !this.props.disabled && this.openMenu()

  handleKeyDown = (event) =>
    !this.props.disabled && /ArrowDown|Enter/.test(event.key) && this.openMenu()

  /**
   * TextField autocomplete methods
   */
  handleTextFieldAutocompletionFiltering = (event, searchText) => {
    this.props.onAutoCompleteTyping(searchText)
    this.setState({ searchText }, () => this.focusTextField())
  }

  handleTextFieldKeyDown = ({ key }) => {
    switch (key) {
      case 'ArrowDown':
        this.focusMenuItem()
        break

      case 'Escape':
        this.clearTextField()
        this.closeMenu()
        break

      default: break
    }
  }

  /**
   * Menu methods
   */
  handleMenuSelection = (selectedItem) => (event) => {
    event.preventDefault()
    const { selectedItems } = this.state
    if (this.props.multiple) {
      const selectedItemExists = selectedItems.some(obj => areEqual(obj.value, selectedItem.value))
      const updatedValues = selectedItemExists
        ? selectedItems.filter(obj => !areEqual(obj.value, selectedItem.value))
        : selectedItems.concat(selectedItem)
      this.setState({ selectedItems: updatedValues })
      this.clearTextField(() => this.focusTextField())
    }
    else {
      const updatedValue = areEqual(selectedItems, selectedItem) ? null : selectedItem
      this.setState({ selectedItems: updatedValue }, () => this.closeMenu())
    }
  }

  // TODO: add Shift+Tab
  /**
   * this.menuItems can contain uncontinuous React elements, because of filtering
   */
  handleMenuKeyDown = ({ key, target: { tabIndex } }) => {
    const cleanMenuItems = this.menuItems.filter(item => !!item)
    const firstTabIndex = cleanMenuItems[0].props.tabIndex
    const lastTabIndex = cleanMenuItems[cleanMenuItems.length - 1].props.tabIndex
    const currentElementIndex = cleanMenuItems.findIndex(item => item.props.tabIndex === tabIndex)
    switch (key) {
      case 'ArrowUp':
        if (+tabIndex === firstTabIndex) {
          this.state.showAutocomplete
            ? this.focusTextField()
            : this.focusMenuItem(lastTabIndex)
        }
        else {
          const previousTabIndex = cleanMenuItems
            .slice(0, currentElementIndex)
            .slice(-1)[0]
            .props.tabIndex
          this.focusMenuItem(previousTabIndex)
        }
        break

      case 'ArrowDown':
        if (+tabIndex === lastTabIndex) {
          this.state.showAutocomplete
            ? this.focusTextField()
            : this.focusMenuItem()
        }
        else {
          const nextTabIndex = cleanMenuItems
            .slice(currentElementIndex + 1)[0]
            .props.tabIndex
          this.focusMenuItem(nextTabIndex)
        }
        break

      case 'PageUp':
        this.focusMenuItem()
        break

      case 'PageDown':
        this.focusMenuItem(lastTabIndex)
        break

      case 'Escape':
        this.closeMenu()
        break

      default: break
    }
  }

  render() {
    const { children, floatingLabel, hintText, hintTextAutocomplete, multiple, disabled, nb2show,
      autocompleteFilter, selectionsRenderer, menuCloseButton, anchorOrigin, canAutoPosition,
      style, menuStyle, elementHeight, innerDivStyle, selectedMenuItemStyle, menuGroupStyle, menuFooterStyle,
      floatingLabelStyle, floatingLabelFocusStyle, underlineStyle, underlineFocusStyle,
      autocompleteUnderlineStyle, autocompleteUnderlineFocusStyle, noMatchFound, noMatchFoundStyle,
      checkedIcon, unCheckedIcon, hoverColor, checkPosition, errorText, errorStyle, underlineErrorStyle
    } = this.props

    // Default style depending on Material-UI context (muiTheme)
    const { baseTheme: { palette }, menuItem } = this.context.muiTheme

    const mergedSelectedMenuItemStyle = {
      color: menuItem.selectedTextColor, ...selectedMenuItemStyle
    }
    if (checkedIcon) checkedIcon.props.style.fill = mergedSelectedMenuItemStyle.color
    const mergedHoverColor = hoverColor || menuItem.hoverColor

    /**
     * MenuItems building, based on user's children
     * 1st function is the base process for producing a MenuItem,
     * including filtering from the Autocomplete.
     * 2nd function is the main loop over children array,
     * accounting for optgroups.
     */
    const menuItemBuilder = (nodes, child, index) => {
      const { selectedItems } = this.state
      const { value: childValue, label } = child.props
      if (!autocompleteFilter(this.state.searchText, label || childValue)) return nodes
      const isSelected = Array.isArray(selectedItems)
        ? selectedItems.some(obj => areEqual(obj.value, childValue))
        : selectedItems ? selectedItems.value === childValue : false
      const leftCheckbox = (multiple && checkPosition === 'left' && (isSelected ? checkedIcon : unCheckedIcon)) || null
      const rightCheckbox = (multiple && checkPosition === 'right' && (isSelected ? checkedIcon : unCheckedIcon)) || null
      if (multiple && checkPosition !== '') {
        if (checkedIcon) checkedIcon.props.style.marginTop = 0
        if (unCheckedIcon) unCheckedIcon.props.style.marginTop = 0
      }
      return [...nodes, (
        <ListItem
          key={++index}
          tabIndex={index}
          ref={ref => (this.menuItems[++index] = ref)}
          onClick={this.handleMenuSelection({ value: childValue, label })}
          disableFocusRipple
          leftIcon={leftCheckbox}
          rightIcon={rightCheckbox}
          primaryText={child}
          hoverColor={mergedHoverColor}
          innerDivStyle={{
            paddingTop: 10,
            paddingBottom: 10,
            paddingLeft: (multiple && checkPosition === 'left') ? 56 : 16,
            paddingRight: (multiple && checkPosition === 'right') ? 56 : 16,
            ...innerDivStyle
          }}
          style={isSelected ? mergedSelectedMenuItemStyle : {}}
        />)]
    }

    const fixedChildren = Array.isArray(children) ? children : [children]

    const menuItems = !disabled && fixedChildren.length && this.state.isOpen &&
      fixedChildren.reduce((nodes, child, index) => {
        if (child.type !== 'optgroup') return menuItemBuilder(nodes, child, index)
        const nextIndex = nodes.length ? +nodes[nodes.length - 1].key + 1 : 0
        const menuGroup =
          <ListItem
            disabled
            key={nextIndex}
            primaryText={child.props.label}
            style={{ cursor: 'default', paddingTop: 10, paddingBottom: 10, ...menuGroupStyle }}
          />
        let groupedItems = []
        const cpc = child.props.children
        if (cpc) {
          if (Array.isArray(cpc) && cpc.length) {
            groupedItems = cpc.reduce((nodes, child, idx) =>
              menuItemBuilder(nodes, child, nextIndex + idx), [])
          }
          else if (typeof cpc === 'object') groupedItems = menuItemBuilder(nodes, cpc, nextIndex)
        }
        return groupedItems.length
          ? [...nodes, menuGroup, ...groupedItems]
          : nodes
      }, [])

    /*
    const menuItemsHeights = this.state.isOpen
      ? this.menuItems.map(item => findDOMNode(item).clientHeight) // can't resolve since items not rendered yet, need componentDiDMount
      : elementHeight
    */
    const autoCompleteHeight = this.state.showAutocomplete ? 53 : 0
    const footerHeight = menuCloseButton ? 36 : 0
    const noMatchFoundHeight = 36
    const containerHeight = (Array.isArray(elementHeight)
      ? elementHeight.reduce((totalHeight, height) => totalHeight + height, 6)
      : (elementHeight * (nb2show < menuItems.length ? nb2show : menuItems.length)) + 6
    ) || 0
    const popoverHeight = autoCompleteHeight + (containerHeight || noMatchFoundHeight) + footerHeight
    const scrollableStyle = { overflowY: nb2show >= menuItems.length ? 'hidden' : 'scroll' }
    const menuWidth = this.root ? this.root.clientWidth : null

    return (
      <div
        ref={ref => (this.root = ref)}
        tabIndex={disabled ? '-1' : '0'}
        onFocus={this.onFocus}
        onBlur={this.onBlur}
        onKeyDown={this.handleKeyDown}
        onClick={this.handleClick}
        title={!this.state.itemsLength ? 'Nothing to show' : ''}
        style={{
          cursor: disabled ? 'not-allowed' : 'pointer',
          color: disabled ? palette.disabledColor : palette.textColor,
          ...style
        }}
      >

        <SelectionsPresenter
          isFocused={this.state.isFocused}
          isOpen={this.state.isOpen}
          disabled={disabled}
          hintText={hintText}
          errorText={errorText}
          errorStyle={errorStyle}
          underlineErrorStyle={underlineErrorStyle}
          muiTheme={this.context.muiTheme}
          selectedValues={this.state.selectedItems}
          selectionsRenderer={selectionsRenderer}
          floatingLabel={floatingLabel}
          floatingLabelStyle={floatingLabelStyle}
          floatingLabelFocusStyle={floatingLabelFocusStyle}
          underlineStyle={underlineStyle}
          underlineFocusStyle={underlineFocusStyle}
        />

        <Popover
          open={this.state.isOpen}
          anchorEl={this.root}
          canAutoPosition={canAutoPosition}
          anchorOrigin={anchorOrigin}
          useLayerForClickAway={false}
          onRequestClose={this.closeMenu}
          style={{ height: popoverHeight }}
        >
          {this.state.showAutocomplete &&
            <TextField
              ref={ref => (this.searchTextField = ref)}
              value={this.state.searchText}
              hintText={hintTextAutocomplete}
              onChange={this.handleTextFieldAutocompletionFiltering}
              onKeyDown={this.handleTextFieldKeyDown}
              style={{ marginLeft: 16, marginBottom: 5, width: menuWidth - (16 * 2) }}
              underlineStyle={autocompleteUnderlineStyle}
              underlineFocusStyle={autocompleteUnderlineFocusStyle}
              autoFocus
            />
          }
          <div
            ref={ref => (this.menu = ref)}
            onKeyDown={this.handleMenuKeyDown}
            style={{ width: menuWidth, ...menuStyle }}
          >
            {menuItems.length
              ? <InfiniteScroller
                elementHeight={elementHeight}
                containerHeight={containerHeight}
                styles={{ scrollableStyle }}
              >
                {menuItems}
              </InfiniteScroller>
              : <ListItem disabled primaryText={noMatchFound}
                style={{ cursor: 'default', padding: '10px 16px', ...noMatchFoundStyle }} />
            }
          </div>
          {multiple &&
            <footer style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>
              <div onClick={this.closeMenu} style={menuFooterStyle}>
                {menuCloseButton}
              </div>
            </footer>
          }
        </Popover>

      </div>
    )
  }
}

SelectField.contextTypes = {
  muiTheme: PropTypes.object.isRequired
}
SelectField.propTypes = selectFieldTypes
SelectField.defaultProps = selectFieldDefaultProps

export default SelectField
<commit_msg>Allow empty Menu with AutoComplete if Threshold is 0<commit_after>
/**
 * Created by Raphaël Morineau on 28 Oct 2016.
 */
import React, { Component } from 'react'
import InfiniteScroller from 'react-infinite'
import ListItem from 'material-ui/List/ListItem'
import Popover from 'material-ui/Popover/Popover'
import TextField from 'material-ui/TextField/TextField'
import SelectionsPresenter from './SelectionsPresenter'
import { getChildrenLength, areEqual } from './utils'
import PropTypes from 'prop-types'
import { selectFieldTypes } from './types'
import { selectFieldDefaultProps } from './defaultProps'

class SelectField extends Component {
  constructor(props, context) {
    super(props, context)
    const { children, value, multiple, showAutocompleteThreshold } = props
    const itemsLength = getChildrenLength(children)
    this.state = {
      isOpen: false,
      isFocused: false,
      itemsLength,
      showAutocomplete: (itemsLength >= showAutocompleteThreshold) || false,
      selectedItems: value || (multiple ? [] : null),
      searchText: ''
    }
    this.menuItems = []
  }

  componentWillReceiveProps(nextProps) {
    if (!areEqual(nextProps.value, this.state.selectedItems)) {
      this.setState({ selectedItems: nextProps.value })
    }
    if (!areEqual(nextProps.children, this.props.children)) {
      const itemsLength = getChildrenLength(nextProps.children)
      this.setState({
        itemsLength,
        showAutocomplete: itemsLength > this.props.showAutocompleteThreshold
      })
    }
  }

  componentDidMount() {
    // Potential problem with Popover ?
    // https://github.com/callemall/material-ui/blob/master/src/DropDownMenu/DropDownMenu.js#L237
    if (this.props.openImmediately) this.openMenu()
  }

  onFocus = () => this.setState({ isFocused: true })

  onBlur = (event) => {
    if (!this.state.isOpen) this.setState({ isFocused: false })
  }

  closeMenu = (reason) => {
    const { onChange, name } = this.props
    if (reason) this.setState({ isFocused: false }) // if reason === 'clickaway' or 'offscreen'
    this.setState({ isOpen: false, searchText: '' }, () => {
      if (!reason) {
        this.root.focus()
      }
      onChange(this.state.selectedItems, name)
    })
  }

  openMenu() {
    if (!this.state.isOpen) this.props.onMenuOpen()
    if (this.state.itemsLength || this.props.showAutocompleteThreshold === 0) this.setState({ isOpen: true }, () => this.focusTextField())
  }

  // FIXME: both focusTextField and focusMenuItem don't really focus the targeted element, user must hit another key to trigger the actual focus... need to find a solution for a true direct focus
  focusMenuItem(index) {
    const targetMenuItem = this.menuItems.find(item => {
      return !!item && (index ? item.props.tabIndex === index : true)
    })
    if (targetMenuItem) targetMenuItem.applyFocusState('keyboard-focused')
  }

  focusTextField() {
    this.state.showAutocomplete && this.searchTextField
      ? this.searchTextField.focus()
      : this.focusMenuItem()
  }

  clearTextField(callback) {
    this.props.keepSearchOnSelect
      ? callback() // don't reset the autocomplete
      : this.setState({ searchText: '' }, callback)
  }

  /**
   * Main Component Wrapper methods
   */
  // toggle instead of close ? (in case user changes targetOrigin/anchorOrigin)
  handleClick = (event) => !this.props.disabled && this.openMenu()

  handleKeyDown = (event) =>
    !this.props.disabled && /ArrowDown|Enter/.test(event.key) && this.openMenu()

  /**
   * TextField autocomplete methods
   */
  handleTextFieldAutocompletionFiltering = (event, searchText) => {
    this.props.onAutoCompleteTyping(searchText)
    this.setState({ searchText }, () => this.focusTextField())
  }

  handleTextFieldKeyDown = ({ key }) => {
    switch (key) {
      case 'ArrowDown':
        this.focusMenuItem()
        break

      case 'Escape':
        this.clearTextField()
        this.closeMenu()
        break

      default: break
    }
  }

  /**
   * Menu methods
   */
  handleMenuSelection = (selectedItem) => (event) => {
    event.preventDefault()
    const { selectedItems } = this.state
    if (this.props.multiple) {
      const selectedItemExists = selectedItems.some(obj => areEqual(obj.value, selectedItem.value))
      const updatedValues = selectedItemExists
        ? selectedItems.filter(obj => !areEqual(obj.value, selectedItem.value))
        : selectedItems.concat(selectedItem)
      this.setState({ selectedItems: updatedValues })
      this.clearTextField(() => this.focusTextField())
    }
    else {
      const updatedValue = areEqual(selectedItems, selectedItem) ? null : selectedItem
      this.setState({ selectedItems: updatedValue }, () => this.closeMenu())
    }
  }

  // TODO: add Shift+Tab
  /**
   * this.menuItems can contain uncontinuous React elements, because of filtering
   */
  handleMenuKeyDown = ({ key, target: { tabIndex } }) => {
    const cleanMenuItems = this.menuItems.filter(item => !!item)
    const firstTabIndex = cleanMenuItems[0].props.tabIndex
    const lastTabIndex = cleanMenuItems[cleanMenuItems.length - 1].props.tabIndex
    const currentElementIndex = cleanMenuItems.findIndex(item => item.props.tabIndex === tabIndex)
    switch (key) {
      case 'ArrowUp':
        if (+tabIndex === firstTabIndex) {
          this.state.showAutocomplete
            ? this.focusTextField()
            : this.focusMenuItem(lastTabIndex)
        }
        else {
          const previousTabIndex = cleanMenuItems
            .slice(0, currentElementIndex)
            .slice(-1)[0]
            .props.tabIndex
          this.focusMenuItem(previousTabIndex)
        }
        break

      case 'ArrowDown':
        if (+tabIndex === lastTabIndex) {
          this.state.showAutocomplete
            ? this.focusTextField()
            : this.focusMenuItem()
        }
        else {
          const nextTabIndex = cleanMenuItems
            .slice(currentElementIndex + 1)[0]
            .props.tabIndex
          this.focusMenuItem(nextTabIndex)
        }
        break

      case 'PageUp':
        this.focusMenuItem()
        break

      case 'PageDown':
        this.focusMenuItem(lastTabIndex)
        break

      case 'Escape':
        this.closeMenu()
        break

      default: break
    }
  }

  render() {
    const { children, floatingLabel, hintText, hintTextAutocomplete, multiple, disabled, nb2show,
      autocompleteFilter, selectionsRenderer, menuCloseButton, anchorOrigin, canAutoPosition,
      style, menuStyle, elementHeight, innerDivStyle, selectedMenuItemStyle, menuGroupStyle, menuFooterStyle,
      floatingLabelStyle, floatingLabelFocusStyle, underlineStyle, underlineFocusStyle,
      autocompleteUnderlineStyle, autocompleteUnderlineFocusStyle, noMatchFound, noMatchFoundStyle,
      checkedIcon, unCheckedIcon, hoverColor, checkPosition, errorText, errorStyle, underlineErrorStyle
    } = this.props

    // Default style depending on Material-UI context (muiTheme)
    const { baseTheme: { palette }, menuItem } = this.context.muiTheme

    const mergedSelectedMenuItemStyle = {
      color: menuItem.selectedTextColor, ...selectedMenuItemStyle
    }
    if (checkedIcon) checkedIcon.props.style.fill = mergedSelectedMenuItemStyle.color
    const mergedHoverColor = hoverColor || menuItem.hoverColor

    /**
     * MenuItems building, based on user's children
     * 1st function is the base process for producing a MenuItem,
     * including filtering from the Autocomplete.
     * 2nd function is the main loop over children array,
     * accounting for optgroups.
     */
    const menuItemBuilder = (nodes, child, index) => {
      const { selectedItems } = this.state
      const { value: childValue, label } = child.props
      if (!autocompleteFilter(this.state.searchText, label || childValue)) return nodes
      const isSelected = Array.isArray(selectedItems)
        ? selectedItems.some(obj => areEqual(obj.value, childValue))
        : selectedItems ? selectedItems.value === childValue : false
      const leftCheckbox = (multiple && checkPosition === 'left' && (isSelected ? checkedIcon : unCheckedIcon)) || null
      const rightCheckbox = (multiple && checkPosition === 'right' && (isSelected ? checkedIcon : unCheckedIcon)) || null
      if (multiple && checkPosition !== '') {
        if (checkedIcon) checkedIcon.props.style.marginTop = 0
        if (unCheckedIcon) unCheckedIcon.props.style.marginTop = 0
      }
      return [...nodes, (
        <ListItem
          key={++index}
          tabIndex={index}
          ref={ref => (this.menuItems[++index] = ref)}
          onClick={this.handleMenuSelection({ value: childValue, label })}
          disableFocusRipple
          leftIcon={leftCheckbox}
          rightIcon={rightCheckbox}
          primaryText={child}
          hoverColor={mergedHoverColor}
          innerDivStyle={{
            paddingTop: 10,
            paddingBottom: 10,
            paddingLeft: (multiple && checkPosition === 'left') ? 56 : 16,
            paddingRight: (multiple && checkPosition === 'right') ? 56 : 16,
            ...innerDivStyle
          }}
          style={isSelected ? mergedSelectedMenuItemStyle : {}}
        />)]
    }

    const fixedChildren = Array.isArray(children) ? children : [children]

    const menuItems = !disabled && fixedChildren.length && this.state.isOpen &&
      fixedChildren.reduce((nodes, child, index) => {
        if (child.type !== 'optgroup') return menuItemBuilder(nodes, child, index)
        const nextIndex = nodes.length ? +nodes[nodes.length - 1].key + 1 : 0
        const menuGroup =
          <ListItem
            disabled
            key={nextIndex}
            primaryText={child.props.label}
            style={{ cursor: 'default', paddingTop: 10, paddingBottom: 10, ...menuGroupStyle }}
          />
        let groupedItems = []
        const cpc = child.props.children
        if (cpc) {
          if (Array.isArray(cpc) && cpc.length) {
            groupedItems = cpc.reduce((nodes, child, idx) =>
              menuItemBuilder(nodes, child, nextIndex + idx), [])
          }
          else if (typeof cpc === 'object') groupedItems = menuItemBuilder(nodes, cpc, nextIndex)
        }
        return groupedItems.length
          ? [...nodes, menuGroup, ...groupedItems]
          : nodes
      }, [])

    /*
    const menuItemsHeights = this.state.isOpen
      ? this.menuItems.map(item => findDOMNode(item).clientHeight) // can't resolve since items not rendered yet, need componentDiDMount
      : elementHeight
    */
    const autoCompleteHeight = this.state.showAutocomplete ? 53 : 0
    const footerHeight = menuCloseButton ? 36 : 0
    const noMatchFoundHeight = 36
    const containerHeight = (Array.isArray(elementHeight)
      ? elementHeight.reduce((totalHeight, height) => totalHeight + height, 6)
      : (elementHeight * (nb2show < menuItems.length ? nb2show : menuItems.length)) + 6
    ) || 0
    const popoverHeight = autoCompleteHeight + (containerHeight || noMatchFoundHeight) + footerHeight
    const scrollableStyle = { overflowY: nb2show >= menuItems.length ? 'hidden' : 'scroll' }
    const menuWidth = this.root ? this.root.clientWidth : null

    return (
      <div
        ref={ref => (this.root = ref)}
        tabIndex={disabled ? '-1' : '0'}
        onFocus={this.onFocus}
        onBlur={this.onBlur}
        onKeyDown={this.handleKeyDown}
        onClick={this.handleClick}
        title={!this.state.itemsLength ? 'Nothing to show' : ''}
        style={{
          cursor: disabled ? 'not-allowed' : 'pointer',
          color: disabled ? palette.disabledColor : palette.textColor,
          ...style
        }}
      >

        <SelectionsPresenter
          isFocused={this.state.isFocused}
          isOpen={this.state.isOpen}
          disabled={disabled}
          hintText={hintText}
          errorText={errorText}
          errorStyle={errorStyle}
          underlineErrorStyle={underlineErrorStyle}
          muiTheme={this.context.muiTheme}
          selectedValues={this.state.selectedItems}
          selectionsRenderer={selectionsRenderer}
          floatingLabel={floatingLabel}
          floatingLabelStyle={floatingLabelStyle}
          floatingLabelFocusStyle={floatingLabelFocusStyle}
          underlineStyle={underlineStyle}
          underlineFocusStyle={underlineFocusStyle}
        />

        <Popover
          open={this.state.isOpen}
          anchorEl={this.root}
          canAutoPosition={canAutoPosition}
          anchorOrigin={anchorOrigin}
          useLayerForClickAway={false}
          onRequestClose={this.closeMenu}
          style={{ height: popoverHeight }}
        >
          {this.state.showAutocomplete &&
            <TextField
              ref={ref => (this.searchTextField = ref)}
              value={this.state.searchText}
              hintText={hintTextAutocomplete}
              onChange={this.handleTextFieldAutocompletionFiltering}
              onKeyDown={this.handleTextFieldKeyDown}
              style={{ marginLeft: 16, marginBottom: 5, width: menuWidth - (16 * 2) }}
              underlineStyle={autocompleteUnderlineStyle}
              underlineFocusStyle={autocompleteUnderlineFocusStyle}
              autoFocus
            />
          }
          <div
            ref={ref => (this.menu = ref)}
            onKeyDown={this.handleMenuKeyDown}
            style={{ width: menuWidth, ...menuStyle }}
          >
            {menuItems.length
              ? <InfiniteScroller
                elementHeight={elementHeight}
                containerHeight={containerHeight}
                styles={{ scrollableStyle }}
              >
                {menuItems}
              </InfiniteScroller>
              : <ListItem disabled primaryText={noMatchFound}
                style={{ cursor: 'default', padding: '10px 16px', ...noMatchFoundStyle }} />
            }
          </div>
          {multiple &&
            <footer style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>
              <div onClick={this.closeMenu} style={menuFooterStyle}>
                {menuCloseButton}
              </div>
            </footer>
          }
        </Popover>

      </div>
    )
  }
}

SelectField.contextTypes = {
  muiTheme: PropTypes.object.isRequired
}
SelectField.propTypes = selectFieldTypes
SelectField.defaultProps = selectFieldDefaultProps

export default SelectField
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import autosize from 'autosize';
import { t, props } from 'tcomb-react';

const UPDATE = 'autosize:update',
  DESTROY = 'autosize:destroy',
  RESIZED = 'autosize:resized';

export const Props = {
  onResize: t.maybe(t.Function)
};

/** A light replacement for built-in textarea component which automaticaly adjusts its height to match the content
 * @param onResize - called whenever the textarea resizes
 */
@props(Props, { strict: false })
export default class TextareaAutosize extends React.Component {

  static defaultProps = {
    rows: 1
  };

  getTextareaDOMNode = () => (
    this.refs.textarea.nodeType === 1 ?
      this.refs.textarea :
      ReactDOM.findDOMNode(this.refs.textarea)
  );

  componentDidMount() {
    autosize(this.getTextareaDOMNode());
    if (this.props.onResize) {
      this.getTextareaDOMNode().addEventListener(RESIZED, this.props.onResize);
    }
  }

  componentWillUnmount() {
    if (this.props.onResize) {
      this.getTextareaDOMNode().removeEventListener(RESIZED, this.props.onResize);
    }
    this.dispatchEvent(DESTROY);
  }

  dispatchEvent = (EVENT_TYPE, defer) => {
    const event = document.createEvent('Event');
    event.initEvent(EVENT_TYPE, true, false);
    const dispatch = () => this.getTextareaDOMNode().dispatchEvent(event);
    if (defer) {
      setTimeout(dispatch);
    } else {
      dispatch();
    }
  };

  getValue = ({ valueLink, value }) => valueLink ? valueLink.value : value;

  render() {
    const { children, onResize, ...props } = this.props;  // eslint-disable-line no-unused-vars
    return (
      <textarea {...props} ref='textarea'>
        {children}
      </textarea>
    );
  }

  componentWillReceiveProps(nextProps) {
    if (this.getValue(nextProps) !== this.getValue(this.props)) {
      this.dispatchEvent(UPDATE, true);
    }
  }

}
<commit_msg>fix lint errors<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import autosize from 'autosize';
import { t, props } from 'tcomb-react';

const UPDATE = 'autosize:update',
  DESTROY = 'autosize:destroy',
  RESIZED = 'autosize:resized';

export const Props = {
  onResize: t.maybe(t.Function)
};

/** A light replacement for built-in textarea component
 * which automaticaly adjusts its height to match the content
 * @param onResize - called whenever the textarea resizes
 */
@props(Props, { strict: false })
export default class TextareaAutosize extends React.Component {

  static defaultProps = {
    rows: 1
  };

  getTextareaDOMNode = () => (
    this.refs.textarea.nodeType === 1 ?
      this.refs.textarea :
      ReactDOM.findDOMNode(this.refs.textarea)
  );

  componentDidMount() {
    autosize(this.getTextareaDOMNode());
    if (this.props.onResize) {
      this.getTextareaDOMNode().addEventListener(RESIZED, this.props.onResize);
    }
  }

  componentWillUnmount() {
    if (this.props.onResize) {
      this.getTextareaDOMNode().removeEventListener(RESIZED, this.props.onResize);
    }
    this.dispatchEvent(DESTROY);
  }

  dispatchEvent = (EVENT_TYPE, defer) => {
    const event = document.createEvent('Event');
    event.initEvent(EVENT_TYPE, true, false);
    const dispatch = () => this.getTextareaDOMNode().dispatchEvent(event);
    if (defer) {
      setTimeout(dispatch);
    } else {
      dispatch();
    }
  };

  getValue = ({ valueLink, value }) => valueLink ? valueLink.value : value;

  render() {
    const { children, onResize, ...props } = this.props;  // eslint-disable-line no-unused-vars
    return (
      <textarea {...props} ref='textarea'>
        {children}
      </textarea>
    );
  }

  componentWillReceiveProps(nextProps) {
    if (this.getValue(nextProps) !== this.getValue(this.props)) {
      this.dispatchEvent(UPDATE, true);
    }
  }

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Vanderbilt University, All rights reserved.
 *
 * Author: Tamas Kecskes
 */

'use strict';

define([],
    function(){
        var AddOnBase = function(Core,Storage){
            this._Core = Core;
            this._Storage = Storage;
            this.core = null;
            this.logger = null;
            this.project = null;
            this.branchName = '';
            this.projectName = '';
            this.commit = null;

        };
        AddOnBase.prototype.getName = function () {
            throw new Error('implement this function in the derived class - getting type automatically is a bad idea,' +
                'when the js scripts are minified names are useless.');
        };

        AddOnBase.prototype._eventer = function(){
            var lastGuid = '',
                self = this,
                nextServerEvent = function(err,guid,parameters){
                    lastGuid = guid || lastGuid;
                    if(!err && parameters){
                        switch (parameters.type){
                            case "PROJECT_CREATED":
                            case "PROJECT_DELETED":
                            case "BRANCH_CREATED":
                            case "BRANCH_DELETED":
                                //TODO can be handled later
                                return self._Storage.getNextServerEvent(lastGuid,nextServerEvent);
                            case "BRANCH_UPDATED":
                                if(self.projectName === parameters.project && self.branchName === parameters.branch){
                                    self.project.loadObject(parameters.commit,function(err,commit){
                                        if(err || !commit){
                                            return self._Storage.getNextServerEvent(lastGuid,nextServerEvent);
                                        }

                                        self.commit = parameters.commit;
                                        self.core.loadRoot(commit.root,function(err,root){
                                            if(err){
                                                return self._Storage.getNextServerEvent(lastGuid,nextServerEvent);
                                            }
                                            self.update(root);
                                            return self._Storage.getNextServerEvent(lastGuid,nextServerEvent);
                                        });
                                    });
                                } else {
                                    return self._Storage.getNextServerEvent(lastGuid,nextServerEvent);
                                }
                        }
                    } else {
                        setTimeout(function(){
                            return self._Storage.getNextServerEvent(lastGuid,nextServerEvent);
                        },1000);
                    }
                };
            self._Storage.getNextServerEvent(lastGuid,nextServerEvent);
        };

        AddOnBase.prototype.init = function(parameters){
            //this is the part of the start process which should be always done, so this function should be always called from the start
            if(!(parameters.projectName && parameters.branchName && parameters.project)){
                return false;
            }
            this.project = parameters.project;
            this.core = new this._Core(this.project);
            this.projectName = parameters.projectName;
            this.branchName = parameters.branchName;

            //start the eventing
            this._eventer();
            return true;
        };
        AddOnBase.prototype.start = function(parameters,callback){
            //this is the initialization function it could be overwritten or use as it is
            if(this.init(parameters)){
                callback(null);
            } else {
                callback(new Error('basic initialization failed, check parameters!'));
            }
        };

        AddOnBase.prototype.update = function(root){
            throw new Error('the update function is a main point of an AddOn\'s functionality so it must be overwritten');
        };

        AddOnBase.prototype.query = function(parameters,callback){
            callback(new Error('the function is the main function of the AddOn so it must be overwritten'));
        };

        AddOnBase.prototype.stop = function(callback){
            callback(new Error('this function must be overwritten to make sure that the addon stops properly'));
        };

        return AddOnBase;
    });<commit_msg>no message<commit_after><|endoftext|>


<commit_before>'use strict';
/**
 * Created by abol on 12/9/16.
 */

const ML = require('ml-curve-fitting');
const LM = ML.LM;
const math = ML.algebra;

/**
 * This function extract the grandient of concentration from a spatial (z) profile acquired with successives
 * experiments of spatially selective NMR . more information with descriptive pictures are found here: 10.1002/mrc.4561
 *
 * @param {array} pdata - array of SD instances with peakPicking done.
 * @param {array} signals - list of chemical shift of signals.
 * @param {number} maxShiftDiference - maximal difference between two signals from subsequent slices.
 * @returns {Array}
 */

function profile(pdata, signals, maxShiftDiference) {

    var peaks = pdata[0].peakPicking;

    var Data = new Array(signals.length);

    var dataShift = {}, dataProfile = {};

    for (var i = 0; i < signals.length; i++) {
        var ini = true;
        for (var k = 0; k < peaks.length; k++) {
            if (Math.abs(peaks[k].signal[0].delta - signals[i]) <= maxShiftDiference) {
                dataShift = {x: [peaks[k].signal[0].delta], y: [Number(pdata[0].filename)]};
                dataProfile = {x: [Number(pdata[0].filename)], y: [peaks[k].integral]};
                Data[i] = {title: signals[i].toString(), shift: {data: dataShift}, profile: {data: dataProfile}};
                k = peaks.length;
                ini = false;
            }
        }
        if (ini) {
            dataShift = {x: [], y: []};
            dataProfile = {x: [], y: []};
            Data[i] = {title: signals[i].toString(), shift: {data: dataShift}, profile: {data: dataProfile}};
        }
    }

    for (i = 1; i < pdata.length; i++) {
        peaks = pdata[i].peakPicking;
        for (var j = 0; j < signals.length; j++) {
            for (k = 0; k < peaks.length; k++) {
                if (Math.abs(peaks[k].signal[0].delta - signals[j]) <= maxShiftDiference) {
                    var temp = Data[j];
                    temp.profile.data.y.push(peaks[k].integral);
                    temp.profile.data.x.push(Number(pdata[i].filename));
                    temp.shift.data.y.push(Number(pdata[i].filename));
                    temp.shift.data.x.push(peaks[k].signal[0].delta);
                    signals[j] = peaks[k].signal[0].delta;
                    k = peaks.length;
                }
            }
        }
    }
    return Data;
}

module.exports = profile;<commit_msg>removed the use of object to store the information<commit_after>'use strict';
/**
 * Created by abol on 12/9/16.
 */

const ML = require('ml-curve-fitting');
const LM = ML.LM;
const math = ML.algebra;

/**
 * This function extract the grandient of concentration from a spatial (z) profile acquired with successives
 * experiments of spatially selective NMR. More information with descriptive pictures are found here: 10.1002/mrc.4561
 *
 * @param {array} pdata - array of SD instances with peakPicking done.
 * @param {array} signals - list of chemical shift of signals.
 * @param {number} maxShiftDiference - maximal difference between two signals from subsequent slices.
 * @returns {Array}
 */

function profile(pdata, signals, maxShiftDiference) {

    var peaks = pdata[0].peakPicking;

    var Data = new Array(signals.length);

    // @TODO Is needed to modified something to obtain spoffs information by default.
    for (var i = 0; i < signals.length; i++) {
        var profileData = [];
        var shiftData = [];
        var ini = true;
        for (var k = 0; k < peaks.length; k++) {
            if (Math.abs(peaks[k].signal[0].delta - signals[i]) <= maxShiftDiference) {
                profileData.push(Number(pdata[0].filename));
                profileData.push(peaks[k].integral);
                shiftData.push(peaks[k].signal[0].delta);
                shiftData.push(Number(pdata[0].filename));
                Data[i] = [profileData, shiftData];
                k = peaks.length;
                ini = false;
            }
        }
        if (ini) Data[i] = [profileData,shiftData];
    }

    for (i = 1; i < pdata.length; i++) {
        peaks = pdata[i].peakPicking;
        for (var j = 0; j < signals.length; j++) {
            for (k = 0; k < peaks.length; k++) {
                if (Math.abs(peaks[k].signal[0].delta - signals[j]) <= maxShiftDiference) {
                    var temp = Data[j];
                    profileData = temp[0];
                    shiftData = temp[1];
                    profileData.push(Number(pdata[i].filename));
                    profileData.push(peaks[k].integral);
                    shiftData.push(peaks[k].signal[0].delta);
                    shiftData.push(Number(pdata[i].filename));
                    signals[j] = peaks[k].signal[0].delta;
                    k = peaks.length;
                }
            }
        }
    }
    return Data;
}
//// Old version of profile, this funtion use objecto to store the information and the use of object is always slow
// function profile(pdata, signals, maxShiftDiference) {
//
//     var peaks = pdata[0].peakPicking;
//
//     var Data = new Array(signals.length);
//
//     var dataShift = {}, dataProfile = {};
//
//     for (var i = 0; i < signals.length; i++) {
//         var ini = true;
//         for (var k = 0; k < peaks.length; k++) {
//             if (Math.abs(peaks[k].signal[0].delta - signals[i]) <= maxShiftDiference) {
//                 dataShift = {x: [peaks[k].signal[0].delta], y: [Number(pdata[0].filename)]};
//                 dataProfile = {x: [Number(pdata[0].filename)], y: [peaks[k].integral]};
//                 Data[i] = {title: signals[i].toString(), shift: {data: dataShift}, profile: {data: dataProfile}};
//                 k = peaks.length;
//                 ini = false;
//             }
//         }
//         if (ini) {
//             dataShift = {x: [], y: []};
//             dataProfile = {x: [], y: []};
//             Data[i] = {title: signals[i].toString(), shift: {data: dataShift}, profile: {data: dataProfile}};
//         }
//     }
//
//     for (i = 1; i < pdata.length; i++) {
//         peaks = pdata[i].peakPicking;
//         for (var j = 0; j < signals.length; j++) {
//             for (k = 0; k < peaks.length; k++) {
//                 if (Math.abs(peaks[k].signal[0].delta - signals[j]) <= maxShiftDiference) {
//                     var temp = Data[j];
//                     temp.profile.data.y.push(peaks[k].integral);
//                     temp.profile.data.x.push(Number(pdata[i].filename));
//                     temp.shift.data.y.push(Number(pdata[i].filename));
//                     temp.shift.data.x.push(peaks[k].signal[0].delta);
//                     signals[j] = peaks[k].signal[0].delta;
//                     k = peaks.length;
//                 }
//             }
//         }
//     }
//     return Data;
// }

module.exports = profile;<|endoftext|>


<commit_before>/**
 *	Angular directive to truncate multi-line text to visible height
 *
 *	@param bind (angular bound value to append) REQUIRED
 *	@param ellipsisAppend (string) string to append at end of truncated text after ellipsis, can be HTML OPTIONAL
 *	@param ellipsisAppendClick (function) function to call if ellipsisAppend is clicked (ellipsisAppend must be clicked) OPTIONAL
 *	@param ellipsisSymbol (string) string to use as ellipsis, replaces default '...' OPTIONAL
 *	@param ellipsisSeparator (string) separator to split string, replaces default ' ' OPTIONAL
 *
 *	@example

 *	@example

 *	@example

 *	@example

 *
 */
angular.module('dibari.angular-ellipsis',[])

.directive('ellipsis', ['$timeout', '$window', function($timeout, $window) {

	return {
		restrict	: 'A',
		scope		: {
			ngBind				: '=',
			ellipsisAppend		: '@',
			ellipsisAppendClick	: '&',
			ellipsisSymbol		: '@',
			ellipsisSeparator	: '@',
			ellipsisSeparatorReg: '='
		},
		compile : function(elem, attr, linker) {

			return function(scope, element, attributes) {
				/* Window Resize Variables */
					attributes.lastWindowResizeTime = 0;
					attributes.lastWindowResizeWidth = 0;
					attributes.lastWindowResizeHeight = 0;
					attributes.lastWindowTimeoutEvent = null;
				/* State Variables */
					attributes.isTruncated = false;

				function buildEllipsis() {
					if (scope.ngBind) {
						var i = 0,
							ellipsisSymbol = (typeof(attributes.ellipsisSymbol) !== 'undefined') ? attributes.ellipsisSymbol : '…',
							ellipsisSeparator = (typeof(scope.ellipsisSeparator) !== 'undefined') ? attributes.ellipsisSeparator  : ' ',
							ellipsisSeparatorReg =  (typeof(scope.ellipsisSeparatorReg) !== 'undefined') ? scope.ellipsisSeparatorReg : false,
							appendString = (typeof(scope.ellipsisAppend) !== 'undefined' && scope.ellipsisAppend !== '') ? ellipsisSymbol + '' + scope.ellipsisAppend + '' : ellipsisSymbol,
							bindArray = ellipsisSeparatorReg ? binding.match(ellipsisSeparatorReg) : binding.split(ellipsisSeparator);

						attributes.isTruncated = false;
						element.text(scope.ngBind);

						// If text has overflow
						if (isOverflowed(element)) {
							var bindArrayStartingLength = bindArray.length,
								initialMaxHeight = element[0].clientHeight;

							element.text(scope.ngBind).html(element.html() + appendString);

							//Set data-overflow on element for targeting
							element.attr('data-overflowed', 'true');

							// Set complete text and remove one word at a time, until there is no overflow
							for ( ; i < bindArrayStartingLength; i++) {
								bindArray.pop();
								element.text(bindArray.join(ellipsisSeparator)).html(element.html() + appendString);

								if (element[0].scrollHeight < initialMaxHeight || isOverflowed(element) === false) {
									attributes.isTruncated = true;
									break;
								}
							}

							// If append string was passed and append click function included
							if (ellipsisSymbol != appendString && typeof(scope.ellipsisAppendClick) !== 'undefined' && scope.ellipsisAppendClick !== '' ) {
								element.find('span').bind("click", function (e) {
									scope.$apply(function () {
										scope.ellipsisAppendClick.call(scope, {event:e});
									});
								});
							}
						}
					}
				}

			   /**
				*	Test if element has overflow of text beyond height or max-height
				*
				*	@param element (DOM object)
				*
				*	@return bool
				*
				*/
				function isOverflowed(thisElement) {
					return thisElement[0].scrollHeight > thisElement[0].clientHeight;
				}

			   /**
				*	Watchers
				*/

				   /**
					*	Execute ellipsis truncate on ngBind update
					*/
					scope.$watch('ngBind', function () {
						$timeout(function() {
							buildEllipsis();
						});
					});

				   /**
					*	Execute ellipsis truncate on ngBind update
					*/
					scope.$watch('ellipsisAppend', function () {
						buildEllipsis();
					});

				   /**
					*	When window width or height changes - re-init truncation
					*/

					function onResize() {
						$timeout.cancel(attributes.lastWindowTimeoutEvent);

						attributes.lastWindowTimeoutEvent = $timeout(function() {
							if (attributes.lastWindowResizeWidth != window.innerWidth || attributes.lastWindowResizeHeight != window.innerHeight) {
								buildEllipsis();
							}

							attributes.lastWindowResizeWidth = window.innerWidth;
							attributes.lastWindowResizeHeight = window.innerHeight;
						}, 75);
					}

					var $win = angular.element($window);
					$win.bind('resize', onResize);

					/**
					* Clean up after ourselves
					*/
					scope.$on('$destroy', function() {
					  $win.unbind('resize', onResize);
					});

			};
		}
	};
}]);
<commit_msg>Revert "enable split using regular expression"<commit_after>/**
 *	Angular directive to truncate multi-line text to visible height
 *
 *	@param bind (angular bound value to append) REQUIRED
 *	@param ellipsisAppend (string) string to append at end of truncated text after ellipsis, can be HTML OPTIONAL
 *	@param ellipsisAppendClick (function) function to call if ellipsisAppend is clicked (ellipsisAppend must be clicked) OPTIONAL
 *	@param ellipsisSymbol (string) string to use as ellipsis, replaces default '...' OPTIONAL
 *	@param ellipsisSeparator (string) separator to split string, replaces default ' ' OPTIONAL
 *
 *	@example

 *	@example

 *	@example

 *	@example

 *
 */
angular.module('dibari.angular-ellipsis',[])

.directive('ellipsis', ['$timeout', '$window', function($timeout, $window) {

	return {
		restrict	: 'A',
		scope		: {
			ngBind				: '=',
			ellipsisAppend		: '@',
			ellipsisAppendClick	: '&',
			ellipsisSymbol		: '@',
			ellipsisSeparator	: '@'
		},
		compile : function(elem, attr, linker) {

			return function(scope, element, attributes) {
				/* Window Resize Variables */
					attributes.lastWindowResizeTime = 0;
					attributes.lastWindowResizeWidth = 0;
					attributes.lastWindowResizeHeight = 0;
					attributes.lastWindowTimeoutEvent = null;
				/* State Variables */
					attributes.isTruncated = false;

				function buildEllipsis() {
					if (scope.ngBind) {
						var i = 0,
							ellipsisSymbol = (typeof(attributes.ellipsisSymbol) !== 'undefined') ? attributes.ellipsisSymbol : '…',
							ellipsisSeparator = (typeof(scope.ellipsisSeparator) !== 'undefined') ? attributes.ellipsisSeparator : ' ',
							appendString = (typeof(scope.ellipsisAppend) !== 'undefined' && scope.ellipsisAppend !== '') ? ellipsisSymbol + '' + scope.ellipsisAppend + '' : ellipsisSymbol,
							bindArray = scope.ngBind.split(ellipsisSeparator);

						attributes.isTruncated = false;
						element.text(scope.ngBind);

						// If text has overflow
						if (isOverflowed(element)) {
							var bindArrayStartingLength = bindArray.length,
								initialMaxHeight = element[0].clientHeight;

							element.text(scope.ngBind).html(element.html() + appendString);

							//Set data-overflow on element for targeting
							element.attr('data-overflowed', 'true');

							// Set complete text and remove one word at a time, until there is no overflow
							for ( ; i < bindArrayStartingLength; i++) {
								bindArray.pop();
								element.text(bindArray.join(ellipsisSeparator)).html(element.html() + appendString);

								if (element[0].scrollHeight < initialMaxHeight || isOverflowed(element) === false) {
									attributes.isTruncated = true;
									break;
								}
							}

							// If append string was passed and append click function included
							if (ellipsisSymbol != appendString && typeof(scope.ellipsisAppendClick) !== 'undefined' && scope.ellipsisAppendClick !== '' ) {
								element.find('span').bind("click", function (e) {
									scope.$apply(function () {
										scope.ellipsisAppendClick.call(scope, {event:e});
									});
								});
							}
						}
					}
				}

			   /**
				*	Test if element has overflow of text beyond height or max-height
				*
				*	@param element (DOM object)
				*
				*	@return bool
				*
				*/
				function isOverflowed(thisElement) {
					return thisElement[0].scrollHeight > thisElement[0].clientHeight;
				}

			   /**
				*	Watchers
				*/

				   /**
					*	Execute ellipsis truncate on ngBind update
					*/
					scope.$watch('ngBind', function () {
						$timeout(function() {
							buildEllipsis();
						});
					});

				   /**
					*	Execute ellipsis truncate on ngBind update
					*/
					scope.$watch('ellipsisAppend', function () {
						buildEllipsis();
					});

				   /**
					*	When window width or height changes - re-init truncation
					*/

					function onResize() {
						$timeout.cancel(attributes.lastWindowTimeoutEvent);

						attributes.lastWindowTimeoutEvent = $timeout(function() {
							if (attributes.lastWindowResizeWidth != window.innerWidth || attributes.lastWindowResizeHeight != window.innerHeight) {
								buildEllipsis();
							}

							attributes.lastWindowResizeWidth = window.innerWidth;
							attributes.lastWindowResizeHeight = window.innerHeight;
						}, 75);
					}

					var $win = angular.element($window);
					$win.bind('resize', onResize);

					/**
					* Clean up after ourselves
					*/
					scope.$on('$destroy', function() {
					  $win.unbind('resize', onResize);
					});

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


<commit_before>/**!
 * AngularJS Plupload directive
 * @author Chungsub Kim <subicura@subicura.com>
 */

/* global plupload */
(function () {
  'use strict';

  angular.module('angular-plupload', [])
    .provider('pluploadOption', function () {
      /* jshint camelcase: false */
      var opts = {
        flash_swf_url: '/bower_components/plupload/js/Moxie.swf',
        silverlight_xap_url: '/bower_components/plupload/js/Moxie.xap',
        runtimes: 'html5, flash, silverlight, html4',
        max_file_size: '2mb',
        filters: [
          { title: 'Image files', extensions: 'jpg,jpeg,gif,png' }
        ]
      };
      return {
        setOptions: function (newOpts) {
          angular.extend(opts, newOpts);
        },
        $get: function () {
          return opts;
        }
      };
    })
    .directive('plupload', [
      '$timeout', 'pluploadOption',
      function ($timeout, pluploadOption) {
        function lowercaseFirstLetter(string) {
          return string.charAt(0).toLowerCase() + string.slice(1);
        }

        return {
          scope: {
            url:'=plupload',
            options:'=pluploadOptions',
            callbacks:'=pluploadCallbacks'
          },
          /* jshint camelcase: false */
          link: function postLink(scope, element, attrs) {
            var opts = pluploadOption;
            opts.url = scope.url;
            /* jshint unused: false */
            opts.browse_button = element[0];
            angular.extend(opts, scope.options);

            var uploader = new plupload.Uploader(opts);

            if(scope.callbacks) {
              var callbackMethods = ['Init', 'PostInit', 'OptionChanged',
                'Refresh', 'StateChanged', 'UploadFile', 'BeforeUpload', 'QueueChanged',
                'UploadProgress', 'FilesRemoved', 'FileFiltered', 'FilesAdded',
                'FileUploaded', 'ChunkUploaded', 'UploadComplete', 'Error', 'Destroy'];
              angular.forEach(callbackMethods, function(method) {
                var callback = (scope.callbacks[lowercaseFirstLetter(method)] || angular.noop);
                uploader.bind(method, function() {
                  callback.apply(null, arguments);
                  if (!scope.$$phase && !scope.$root.$$phase) {
                    scope.$apply();
                  }
                });
              });
            }

            uploader.init();
          }
        };
      }
    ]
  );
})();
<commit_msg>Fix to not strip url if no opts.url is specified<commit_after>/**!
 * AngularJS Plupload directive
 * @author Chungsub Kim <subicura@subicura.com>
 */

/* global plupload */
(function () {
  'use strict';

  angular.module('angular-plupload', [])
    .provider('pluploadOption', function () {
      /* jshint camelcase: false */
      var opts = {
        flash_swf_url: '/bower_components/plupload/js/Moxie.swf',
        silverlight_xap_url: '/bower_components/plupload/js/Moxie.xap',
        runtimes: 'html5, flash, silverlight, html4',
        max_file_size: '2mb',
        filters: [
          { title: 'Image files', extensions: 'jpg,jpeg,gif,png' }
        ]
      };
      return {
        setOptions: function (newOpts) {
          angular.extend(opts, newOpts);
        },
        $get: function () {
          return opts;
        }
      };
    })
    .directive('plupload', [
      '$timeout', 'pluploadOption',
      function ($timeout, pluploadOption) {
        function lowercaseFirstLetter(string) {
          return string.charAt(0).toLowerCase() + string.slice(1);
        }

        return {
          scope: {
            url:'=plupload',
            options:'=pluploadOptions',
            callbacks:'=pluploadCallbacks'
          },
          /* jshint camelcase: false */
          link: function postLink(scope, element, attrs) {
            var opts = pluploadOption;
            opts.url = scope.url || opts.url;
            /* jshint unused: false */
            opts.browse_button = element[0];
            angular.extend(opts, scope.options);

            var uploader = new plupload.Uploader(opts);

            if(scope.callbacks) {
              var callbackMethods = ['Init', 'PostInit', 'OptionChanged',
                'Refresh', 'StateChanged', 'UploadFile', 'BeforeUpload', 'QueueChanged',
                'UploadProgress', 'FilesRemoved', 'FileFiltered', 'FilesAdded',
                'FileUploaded', 'ChunkUploaded', 'UploadComplete', 'Error', 'Destroy'];
              angular.forEach(callbackMethods, function(method) {
                var callback = (scope.callbacks[lowercaseFirstLetter(method)] || angular.noop);
                uploader.bind(method, function() {
                  callback.apply(null, arguments);
                  if (!scope.$$phase && !scope.$root.$$phase) {
                    scope.$apply();
                  }
                });
              });
            }

            uploader.init();
          }
        };
      }
    ]
  );
})();
<|endoftext|>


<commit_before>import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
import simulationApp from 'redux/reducers/index.js'

const store = createStore(
  simulationApp,
  applyMiddleware(thunk),
  applyMiddleware(logger),
);

export default store
<commit_msg>removing cruft<commit_after>import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger';
import simulationApp from 'redux/reducers/index.js'

const store = createStore(
  simulationApp,
  applyMiddleware(logger),
);

export default store
<|endoftext|>


<commit_before>'use strict'
var $ = require('jquery')
var yo = require('yo-yo')
var helper = require('../../lib/helper.js')
var txExecution = require('../execution/txExecution')
var txFormat = require('../execution/txFormat')
var txHelper = require('../execution/txHelper')
var modalDialogCustom = require('../ui/modal-dialog-custom')
var executionContext = require('../../execution-context')
const copy = require('clipboard-copy')

// -------------- styling ----------------------
var csjs = require('csjs-inject')
var remix = require('ethereum-remix')
var styleGuide = remix.ui.styleGuide
var styles = styleGuide()

var css = csjs`
  .runTabView {
    padding: 2%;
    display: flex;
    flex-direction: column;
  }
  .settings {
    ${styles.displayBox}
    margin-bottom: 2%;
    padding: 10px 15px 15px 15px;
  }
  .crow {
    margin-top: .5em;
    display: flex;
  }
  .col1 {
    ${styles.titleL}
    width: 30%;
    float: left;
    align-self: center;
  }
  .col1_1 {
    ${styles.titleM}
    font-size: 12px;
    width: 25%;
    min-width: 75px;
    float: left;
    align-self: center;
  }
  .col2 {
    ${styles.inputField}
  }
  .select {
    ${styles.dropdown}
    text-align: center;
    font-weight: normal;
    min-width: 150px;
  }
  .copyaddress {
    color: ${styles.colors.blue};
    margin-left: 0.5em;
    margin-top: 0.7em;
    cursor: pointer;
  }
  .copyaddress:hover {
    color: ${styles.colors.grey};
  }
  .instanceContainer {
    ${styles.displayBox}
    display: flex;
    flex-direction: column;
    background-color: ${styles.colors.transparent};
    margin-top: 2%;
    border: none;
  }
  .pendingTxsContainer  {
    ${styles.displayBox}
    display: flex;
    flex-direction: column;
    background-color: ${styles.colors.transparent};
    margin-top: 2%;
    border: none;
    padding-bottom: 0;
  }
  .container {
    ${styles.displayBox}
    margin-top: 2%;
  }
  .contractNames {
    ${styles.dropdown}
  }
  .subcontainer {
    display: flex;
    flex-direction: row;
    align-items: baseline;
  }
  .buttons {
    display: flex;
    cursor: pointer;
    justify-content: center;
    flex-direction: column;
    text-align: center;
    font-size: 12px;
  }
  .button {
    display: flex;
    align-items: center;
    margin-top: 2%;
  }
  .atAddress {
    ${styles.button}
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    background-color: ${styles.colors.lightGreen};
    border-color: ${styles.colors.lightGreen};
  }
  .create {
    ${styles.button}
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    background-color: ${styles.colors.lightRed};
    border-color: ${styles.colors.lightRed};
  }
  .input {
    ${styles.inputField}
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    padding-left: 10px;
  }
  .noInstancesText {
    ${styles.displayBox}
    text-align: center;
    color: ${styles.colors.lightGrey};
    font-style: italic;
  }
  .pendingTxsText {
    ${styles.displayBox}
    text-align: center;
    color: ${styles.colors.lightGrey};
    font-style: italic;
  }
  .item {
    margin-right: 1em;
    display: flex;
    align-items: center;
  }
  .transact {
    color: ${styles.colors.lightRed};
    margin-right: .3em;
  }
  .payable {
    color: ${styles.colors.red};
    margin-right: .3em;
  }
  .call {
    color: ${styles.colors.lightBlue};
    margin-right: .3em;
  }
  .pendingContainer {
    display: flex;
    align-items: baseline;
  }
  .pending {
    height: 25px;
    text-align: center;
    padding-left: 10px;
    border-radius: 3px;
    margin-left: 5px;
  }
  .icon {
    font-size: 12px;
    color: ${styles.colors.orange};
    margin-left: 10%;
  }
`

module.exports = runTab

var instanceContainer = yo`<div class="${css.instanceContainer}"></div>`
var noInstancesText = yo`<div class="${css.noInstancesText}">No Contract Instances.</div>`

var pendingTxsText = yo`<div class="${css.pendingTxsText}"></div>`
var pendingTxsContainer = yo`<div class="${css.pendingTxsContainer}">${pendingTxsText}</div>`

function runTab (container, appAPI, appEvents, opts) {
  var el = yo`

    ${settings(appAPI, appEvents)}
    ${contractDropdown(appAPI, appEvents, instanceContainer)}
    ${pendingTxsContainer}
    ${instanceContainer}

  `
  container.appendChild(el)

  // PENDING transactions
  function updatePendingTxs (container, appAPI) {
    var pendingCount = Object.keys(appAPI.udapp().pendingTransactions()).length
    pendingTxsText.innerText = pendingCount + ' pending transactions'
  }

  // DROPDOWN
  var selectExEnv = el.querySelector('#selectExEnvOptions')
  selectExEnv.addEventListener('change', function (event) {
    if (!executionContext.executionContextChange(selectExEnv.options[selectExEnv.selectedIndex].value)) {
      selectExEnv.value = executionContext.getProvider()
    }
    fillAccountsList(appAPI, el)
    instanceContainer.innerHTML = '' // clear the instances list
    noInstancesText.style.display = 'block'
    instanceContainer.appendChild(noInstancesText)
  })
  selectExEnv.value = executionContext.getProvider()
  fillAccountsList(appAPI, el)
  setInterval(() => {
    updateAccountBalances(container, appAPI)
    updatePendingTxs(container, appAPI)
  }, 500)
}

function fillAccountsList (appAPI, container) {
  var $txOrigin = $(container.querySelector('#txorigin'))
  $txOrigin.empty()
  appAPI.udapp().getAccounts((err, accounts) => {
    if (err) { console.log(err) }
    if (accounts && accounts[0]) {
      for (var a in accounts) { $txOrigin.append($('<option />').val(accounts[a]).text(accounts[a])) }
      $txOrigin.val(accounts[0])
    } else {
      $txOrigin.val('unknown')
    }
  })
}

function updateAccountBalances (container, appAPI) {
  var accounts = $(container.querySelector('#txorigin')).children('option')
  accounts.each(function (index, value) {
    (function (acc) {
      appAPI.getBalance(accounts[acc].value, function (err, res) {
        if (!err) {
          accounts[acc].innerText = helper.shortenAddress(accounts[acc].value, res)
        }
      })
    })(index)
  })
}

/* ------------------------------------------------
    section CONTRACT DROPDOWN and BUTTONS
------------------------------------------------ */

function contractDropdown (appAPI, appEvents, instanceContainer) {
  instanceContainer.appendChild(noInstancesText)

  appEvents.compiler.register('compilationFinished', function (success, data, source) {
    getContractNames(success, data)
  })

  var atAddressButtonInput = yo`<input class="${css.input} ataddressinput" placeholder="Enter contract's address - i.e. 0x60606..." title="atAddress" />`
  var createButtonInput = yo`<input class="${css.input}" placeholder="" title="create" />`
  var selectContractNames = yo`<select class="${css.contractNames}" disabled></select>`
  var el = yo`

        ${selectContractNames}

At Address

          ${atAddressButtonInput}

Create

          ${createButtonInput}

  `

  function setInputParamsPlaceHolder () {
    createButtonInput.value = ''
    if (appAPI.getContracts() && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) {
      var contract = appAPI.getContracts()[selectContractNames.children[selectContractNames.selectedIndex].innerHTML]
      var ctrabi = txHelper.getConstructorInterface(contract.interface)
      if (ctrabi.inputs.length) {
        createButtonInput.setAttribute('placeholder', txHelper.inputParametersDeclarationToString(ctrabi.inputs))
        createButtonInput.removeAttribute('disabled')
        return
      }
    }
    createButtonInput.setAttribute('placeholder', '')
    createButtonInput.setAttribute('disabled', true)
  }

  selectContractNames.addEventListener('change', setInputParamsPlaceHolder)

  // ADD BUTTONS AT ADDRESS AND CREATE
  function createInstance () {
    // appAPI.logMessage('transaction added ...')
    var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
    var contracts = appAPI.getContracts()
    var contract = appAPI.getContracts()[contractNames.children[contractNames.selectedIndex].innerHTML]
    var constructor = txHelper.getConstructorInterface(contract.interface)
    var args = createButtonInput.value
    txFormat.buildData(contract, contracts, true, constructor, args, appAPI.udapp(), (error, data) => {
      if (!error) {
        appAPI.logMessage('transaction added ...')
        txExecution.createContract(data, appAPI.udapp(), (error, txResult) => {
          if (!error) {
            var isVM = executionContext.isVM()
            if (isVM) {
              var vmError = txExecution.checkVMError(txResult)
              if (vmError.error) {
                modalDialogCustom.alert(vmError.message)
                return
              }
            }
            noInstancesText.style.display = 'none'
            var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress
            instanceContainer.appendChild(appAPI.udapp().renderInstance(contract, address, selectContractNames.value))
          } else {
            modalDialogCustom.alert(error)
          }
        })
      } else {
        modalDialogCustom.alert(error)
      }
    })
  }

  function loadFromAddress (appAPI) {
    noInstancesText.style.display = 'none'
    var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
    var contract = appAPI.getContracts()[contractNames.children[contractNames.selectedIndex].innerHTML]
    var address = atAddressButtonInput.value
    instanceContainer.appendChild(appAPI.udapp().renderInstance(contract, address, selectContractNames.value))
  }

  // GET NAMES OF ALL THE CONTRACTS
  function getContractNames (success, data) {
    var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
    contractNames.innerHTML = ''
    if (success) {
      selectContractNames.removeAttribute('disabled')
      for (var name in data.contracts) {
        contractNames.appendChild(yo`<option>${name}</option>`)
      }
    } else {
      selectContractNames.setAttribute('disabled', true)
    }
    setInputParamsPlaceHolder()
  }

  return el
}

/* ------------------------------------------------
    section SETTINGS: Environment, Account, Gas, Value
------------------------------------------------ */
function settings (appAPI, appEvents) {
  // COPY ADDRESS
  function copyAddress () {
    copy(document.querySelector('#runTabView #txorigin').value)
  }

  // SETTINGS HTML
  var el = yo`

          Environment

        <select id="selectExEnvOptions" class="${css.select}">
          <option id="vm-mode"
            title="Execution environment does not connect to any node, everything is local and in memory only."
            value="vm"
            checked name="executionContext">
            JavaScript VM
          </option>
          <option id="injected-mode"
            title="Execution environment has been provided by Mist or similar provider."
            value="injected"
            checked name="executionContext">
            Injected Web3
          </option>
          <option id="web3-mode"
            title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
            If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http."
            value="web3"
            name="executionContext">
            Web3 Provider
          </option>
        </select>

Account

        <select name="txorigin" class="${css.select}" id="txorigin"></select>

Gas limit

        <input type="number" class="${css.col2}" id="gasLimit" value="3000000">

Gas Price

        <input type="number" class="${css.col2}" id="gasPrice" value="0">

Value

        <input type="text" class="${css.col2}" id="value" value="0" title="(e.g. .7 ether ...)">

  `

  // EVENTS
  appEvents.udapp.register('transactionExecuted', (error, to, data, lookupOnly, txResult) => {
    if (error) return
    if (!lookupOnly) el.querySelector('#value').value = '0'
  })

  return el
}
<commit_msg>run-tab - not working right yet<commit_after>'use strict'
var $ = require('jquery')
var yo = require('yo-yo')
var helper = require('../../lib/helper.js')
var txExecution = require('../execution/txExecution')
var txFormat = require('../execution/txFormat')
var txHelper = require('../execution/txHelper')
var modalDialogCustom = require('../ui/modal-dialog-custom')
var executionContext = require('../../execution-context')
const copy = require('clipboard-copy')

// -------------- styling ----------------------
var csjs = require('csjs-inject')
var remix = require('ethereum-remix')
var styleGuide = remix.ui.styleGuide
var styles = styleGuide()

var css = csjs`
  .runTabView {
    padding: 2%;
    display: flex;
    flex-direction: column;
  }
  .settings {
    ${styles.displayBox}
    margin-bottom: 2%;
    padding: 10px 15px 15px 15px;
  }
  .crow {
    margin-top: .5em;
    display: flex;
  }
  .col1 {
    ${styles.titleL}
    width: 30%;
    float: left;
    align-self: center;
  }
  .col1_1 {
    ${styles.titleM}
    font-size: 12px;
    width: 25%;
    min-width: 75px;
    float: left;
    align-self: center;
  }
  .col2 {
    ${styles.inputField}
  }
  .select {
    ${styles.dropdown}
    text-align: center;
    font-weight: normal;
    min-width: 150px;
  }
  .copyaddress {
    color: ${styles.colors.blue};
    margin-left: 0.5em;
    margin-top: 0.7em;
    cursor: pointer;
  }
  .copyaddress:hover {
    color: ${styles.colors.grey};
  }
  .instanceContainer {
    ${styles.displayBox}
    display: flex;
    flex-direction: column;
    background-color: ${styles.colors.transparent};
    margin-top: 2%;
    border: none;
  }
  .pendingTxsContainer  {
    ${styles.displayBox}
    display: flex;
    flex-direction: column;
    background-color: ${styles.colors.transparent};
    margin-top: 2%;
    border: none;
    padding-bottom: 0;
  }
  .container {
    ${styles.displayBox}
    margin-top: 2%;
  }
  .contractNames {
    ${styles.dropdown}
  }
  .subcontainer {
    display: flex;
    flex-direction: row;
    align-items: baseline;
  }
  .buttons {
    display: flex;
    cursor: pointer;
    justify-content: center;
    flex-direction: column;
    text-align: center;
    font-size: 12px;
  }
  .button {
    display: flex;
    align-items: center;
    margin-top: 2%;
  }
  .atAddress {
    ${styles.button}
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    background-color: ${styles.colors.lightGreen};
    border-color: ${styles.colors.lightGreen};
  }
  .create {
    ${styles.button}
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    background-color: ${styles.colors.lightRed};
    border-color: ${styles.colors.lightRed};
  }
  .input {
    ${styles.inputField}
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    padding-left: 10px;
  }
  .noInstancesText {
    ${styles.displayBox}
    text-align: center;
    color: ${styles.colors.lightGrey};
    font-style: italic;
  }
  .pendingTxsText {
    ${styles.displayBox}
    text-align: center;
    color: ${styles.colors.lightGrey};
    font-style: italic;
  }
  .item {
    margin-right: 1em;
    display: flex;
    align-items: center;
  }
  .transact {
    color: ${styles.colors.lightRed};
    margin-right: .3em;
  }
  .payable {
    color: ${styles.colors.red};
    margin-right: .3em;
  }
  .call {
    color: ${styles.colors.lightBlue};
    margin-right: .3em;
  }
  .pendingContainer {
    display: flex;
    align-items: baseline;
  }
  .pending {
    height: 25px;
    text-align: center;
    padding-left: 10px;
    border-radius: 3px;
    margin-left: 5px;
  }
  .icon {
    font-size: 12px;
    color: ${styles.colors.orange};
    margin-left: 10%;
  }
`

module.exports = runTab

var instanceContainer = yo`<div class="${css.instanceContainer}"></div>`
var noInstancesText = yo`<div class="${css.noInstancesText}">No Contract Instances.</div>`

var pendingTxsText = yo`<div class="${css.pendingTxsText}"></div>`
var pendingTxsContainer = yo`<div class="${css.pendingTxsContainer}">${pendingTxsText}</div>`

function runTab (container, appAPI, appEvents, opts) {
  var el = yo`

    ${settings(appAPI, appEvents)}
    ${contractDropdown(appAPI, appEvents, instanceContainer)}
    ${pendingTxsContainer}
    ${instanceContainer}

  `
  container.appendChild(el)

  // PENDING transactions
  function updatePendingTxs (container, appAPI) {
    var pendingCount = Object.keys(appAPI.udapp().pendingTransactions()).length
    pendingTxsText.innerText = pendingCount + ' pending transactions'
  }

  // DROPDOWN
  var selectExEnv = el.querySelector('#selectExEnvOptions')
  selectExEnv.addEventListener('change', function (event) {
    if (!executionContext.executionContextChange(selectExEnv.options[selectExEnv.selectedIndex].value)) {
      selectExEnv.value = executionContext.getProvider()
    }
    fillAccountsList(appAPI, el)
    instanceContainer.innerHTML = '' // clear the instances list
    noInstancesText.style.display = 'block'
    instanceContainer.appendChild(noInstancesText)
  })
  selectExEnv.value = executionContext.getProvider()
  fillAccountsList(appAPI, el)
  setInterval(() => {
    updateAccountBalances(container, appAPI)
    updatePendingTxs(container, appAPI)
  }, 500)
}

function fillAccountsList (appAPI, container) {
  var $txOrigin = $(container.querySelector('#txorigin'))
  $txOrigin.empty()
  appAPI.udapp().getAccounts((err, accounts) => {
    if (err) { console.log(err) }
    if (accounts && accounts[0]) {
      for (var a in accounts) { $txOrigin.append($('<option />').val(accounts[a]).text(accounts[a])) }
      $txOrigin.val(accounts[0])
    } else {
      $txOrigin.val('unknown')
    }
  })
}

function updateAccountBalances (container, appAPI) {
  var accounts = $(container.querySelector('#txorigin')).children('option')
  accounts.each(function (index, value) {
    (function (acc) {
      appAPI.getBalance(accounts[acc].value, function (err, res) {
        if (!err) {
          accounts[acc].innerText = helper.shortenAddress(accounts[acc].value, res)
        }
      })
    })(index)
  })
}

/* ------------------------------------------------
    section CONTRACT DROPDOWN and BUTTONS
------------------------------------------------ */

function contractDropdown (appAPI, appEvents, instanceContainer) {
  instanceContainer.appendChild(noInstancesText)

  appEvents.compiler.register('compilationFinished', function (success, data, source) {
    getContractNames(success, data)
  })

  var atAddressButtonInput = yo`<input class="${css.input} ataddressinput" placeholder="Enter contract's address - i.e. 0x60606..." title="atAddress" />`
  var createButtonInput = yo`<input class="${css.input}" placeholder="" title="create" />`
  var selectContractNames = yo`<select class="${css.contractNames}" disabled></select>`
  var el = yo`

        ${selectContractNames}

At Address

          ${atAddressButtonInput}

Create

          ${createButtonInput}

  `

  function setInputParamsPlaceHolder () {
    createButtonInput.value = ''
    if (appAPI.getContracts() && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) {
      var contract = appAPI.getContracts()[selectContractNames.children[selectContractNames.selectedIndex].innerHTML]
      var ctrabi = txHelper.getConstructorInterface(contract.interface)
      if (ctrabi.inputs.length) {
        createButtonInput.setAttribute('placeholder', txHelper.inputParametersDeclarationToString(ctrabi.inputs))
        createButtonInput.removeAttribute('disabled')
        return
      }
    }
    createButtonInput.setAttribute('placeholder', '')
    createButtonInput.setAttribute('disabled', true)
  }

  selectContractNames.addEventListener('change', setInputParamsPlaceHolder)

  // ADD BUTTONS AT ADDRESS AND CREATE
  function createInstance () {
    // appAPI.logMessage('transaction added ...')
    var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
    var contracts = appAPI.getContracts()
    var contract = appAPI.getContracts()[contractNames.children[contractNames.selectedIndex].innerHTML]
    var constructor = txHelper.getConstructorInterface(contract.interface)
    var args = createButtonInput.value
    txFormat.buildData(contract, contracts, true, constructor, args, appAPI.udapp(), (error, data) => {
      if (!error) {
        console.log(`${JSON.parse(JSON.stringify(contract.metadata, null, 4))}`)
        appAPI.logMessage(`B creation of ${contract} pending`)
        txExecution.createContract(data, appAPI.udapp(), (error, txResult) => {
          if (!error) {
            var isVM = executionContext.isVM()
            if (isVM) {
              var vmError = txExecution.checkVMError(txResult)
              if (vmError.error) {
                modalDialogCustom.alert(vmError.message)
                return
              }
            }
            noInstancesText.style.display = 'none'
            var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress
            instanceContainer.appendChild(appAPI.udapp().renderInstance(contract, address, selectContractNames.value))
          } else {
            modalDialogCustom.alert(error)
          }
        })
      } else {
        modalDialogCustom.alert(error)
      }
    })
  }

  function loadFromAddress (appAPI) {
    noInstancesText.style.display = 'none'
    var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
    var contract = appAPI.getContracts()[contractNames.children[contractNames.selectedIndex].innerHTML]
    var address = atAddressButtonInput.value
    instanceContainer.appendChild(appAPI.udapp().renderInstance(contract, address, selectContractNames.value))
  }

  // GET NAMES OF ALL THE CONTRACTS
  function getContractNames (success, data) {
    var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
    contractNames.innerHTML = ''
    if (success) {
      selectContractNames.removeAttribute('disabled')
      for (var name in data.contracts) {
        contractNames.appendChild(yo`<option>${name}</option>`)
      }
    } else {
      selectContractNames.setAttribute('disabled', true)
    }
    setInputParamsPlaceHolder()
  }

  return el
}

/* ------------------------------------------------
    section SETTINGS: Environment, Account, Gas, Value
------------------------------------------------ */
function settings (appAPI, appEvents) {
  // COPY ADDRESS
  function copyAddress () {
    copy(document.querySelector('#runTabView #txorigin').value)
  }

  // SETTINGS HTML
  var el = yo`

          Environment

        <select id="selectExEnvOptions" class="${css.select}">
          <option id="vm-mode"
            title="Execution environment does not connect to any node, everything is local and in memory only."
            value="vm"
            checked name="executionContext">
            JavaScript VM
          </option>
          <option id="injected-mode"
            title="Execution environment has been provided by Mist or similar provider."
            value="injected"
            checked name="executionContext">
            Injected Web3
          </option>
          <option id="web3-mode"
            title="Execution environment connects to node at localhost (or via IPC if available), transactions will be sent to the network and can cause loss of money or worse!
            If this page is served via https and you access your node via http, it might not work. In this case, try cloning the repository and serving it via http."
            value="web3"
            name="executionContext">
            Web3 Provider
          </option>
        </select>

Account

        <select name="txorigin" class="${css.select}" id="txorigin"></select>

Gas limit

        <input type="number" class="${css.col2}" id="gasLimit" value="3000000">

Gas Price

        <input type="number" class="${css.col2}" id="gasPrice" value="0">

Value

        <input type="text" class="${css.col2}" id="value" value="0" title="(e.g. .7 ether ...)">

  `

  // EVENTS
  appEvents.udapp.register('transactionExecuted', (error, to, data, lookupOnly, txResult) => {
    if (error) return
    if (!lookupOnly) el.querySelector('#value').value = '0'
  })

  return el
}
<|endoftext|>


<commit_before>
import api from '../core/api';

var _ab_list = [
  '6f9f8f04a55c4b50cb888e97c75eca4d82962f69',
  '78b9fe21619c6fc652b006fd1c772284bbd18f34',
  '12093289b594f50d3971e4719eedd5c314ceb6ba',
  '0e880ca5c85eb848ec878cb6d16dc223ea3ed2a8',
  '519727259c5d55599369d19df95f75a582a9e685',
  'd78dcdcefe37c7b55cfa70ac48a4c8dc719e0875',
  '868ff632cfab95b8fec42a1e970a776686d8cf38',
  '73ee9ba32eab8893e7e07add3b133f706e95a761',
];

export default function checkoutAB (checkout_url) {

  if( _ab_list.indexOf(api.public_key) >= 0 ) return 'https://checkout-vanilla.aplazame.com/';

  return checkout_url;

}
<commit_msg>rollback checkout AB<commit_after>
import api from '../core/api';

var _ab_list = [
  // '6f9f8f04a55c4b50cb888e97c75eca4d82962f69',
  // '78b9fe21619c6fc652b006fd1c772284bbd18f34',
  // '12093289b594f50d3971e4719eedd5c314ceb6ba',
  // '0e880ca5c85eb848ec878cb6d16dc223ea3ed2a8',
  // '519727259c5d55599369d19df95f75a582a9e685',
  // 'd78dcdcefe37c7b55cfa70ac48a4c8dc719e0875',
  // '868ff632cfab95b8fec42a1e970a776686d8cf38',
  // '73ee9ba32eab8893e7e07add3b133f706e95a761',
];

export default function checkoutAB (checkout_url) {

  if( _ab_list.indexOf(api.public_key) >= 0 ) return 'https://checkout-vanilla.aplazame.com/';

  return checkout_url;

}
<|endoftext|>


<commit_before>/*

var (\w+?) =
$1:

[^}];
,

*/

module.exports = {
	selfId: "224529399003742210",
	vaebId: "107593015014486016",

	mutesDir: "mutes.json",
	histDir: "history.json",
	autoRoleDir: "autoroles.json",
	playlistDir: "playlist.json",

	rolePermissions: [
		"CREATE_INSTANT_INVITE",
		"KICK_MEMBERS",
		"BAN_MEMBERS",
		"VIEW_AUDIT_LOG",
		"ADMINISTRATOR",
		"MANAGE_CHANNELS",
		"MANAGE_GUILD",
		"ADD_REACTIONS", // add reactions to messages
		"READ_MESSAGES",
		"SEND_MESSAGES",
		"SEND_TTS_MESSAGES",
		"MANAGE_MESSAGES",
		"EMBED_LINKS",
		"ATTACH_FILES",
		"READ_MESSAGE_HISTORY",
		"MENTION_EVERYONE",
		"USE_EXTERNAL_EMOJIS", // use external emojis
		"CONNECT", // connect to voice
		"SPEAK", // speak on voice
		"MUTE_MEMBERS", // globally mute members on voice
		"DEAFEN_MEMBERS", // globally deafen members on voice
		"MOVE_MEMBERS", // move member's voice channels
		"USE_VAD", // use voice activity detection
		"CHANGE_NICKNAME",
		"MANAGE_NICKNAMES", // change nicknames of others
		"MANAGE_ROLES",
		"MANAGE_WEBHOOKS",
		"MANAGE_EMOJIS"
	],

	rolePermissionsObj: {
		"CREATE_INSTANT_INVITE": true,
		"KICK_MEMBERS": true,
		"BAN_MEMBERS": true,
		"VIEW_AUDIT_LOG": true,
		"ADMINISTRATOR": true,
		"MANAGE_CHANNELS": true,
		"MANAGE_GUILD": true,
		"ADD_REACTIONS": true, // add reactions to messages
		"READ_MESSAGES": true,
		"SEND_MESSAGES": true,
		"SEND_TTS_MESSAGES": true,
		"MANAGE_MESSAGES": true,
		"EMBED_LINKS": true,
		"ATTACH_FILES": true,
		"READ_MESSAGE_HISTORY": true,
		"MENTION_EVERYONE": true,
		"USE_EXTERNAL_EMOJIS": true, // use external emojis
		"CONNECT": true, // connect to voice
		"SPEAK": true, // speak on voice
		"MUTE_MEMBERS": true, // globally mute members on voice
		"DEAFEN_MEMBERS": true, // globally deafen members on voice
		"MOVE_MEMBERS": true, // move member's voice channels
		"USE_VAD": true, // use voice activity detection
		"CHANGE_NICKNAME": true,
		"MANAGE_NICKNAMES": true, // change nicknames of others
		"MANAGE_ROLES": true,
		"MANAGE_WEBHOOKS": true,
		"MANAGE_EMOJIS": true
	},

	textChannnelPermissions: [
		"CREATE_INSTANT_INVITE",
		"MANAGE_CHANNEL",
		"ADD_REACTIONS", // add reactions to messages
		"READ_MESSAGES",
		"SEND_MESSAGES",
		"SEND_TTS_MESSAGES",
		"MANAGE_MESSAGES",
		"EMBED_LINKS",
		"ATTACH_FILES",
		"READ_MESSAGE_HISTORY",
		"MENTION_EVERYONE",
		"USE_EXTERNAL_EMOJIS", // use external emojis
		"MANAGE_PERMISSIONS",
		"MANAGE_WEBHOOKS"
	],

	textChannnelPermissionsObj: {
		"ADD_REACTIONS": true, // add reactions to messages
		"READ_MESSAGES": true,
		"SEND_MESSAGES": true,
		"SEND_TTS_MESSAGES": true,
		"MANAGE_MESSAGES": true,
		"EMBED_LINKS": true,
		"ATTACH_FILES": true,
		"READ_MESSAGE_HISTORY": true,
		"MENTION_EVERYONE": true,
		"USE_EXTERNAL_EMOJIS": true, // use external emojis
		"CREATE_INSTANT_INVITE": true,
		"MANAGE_CHANNEL": true,
		"MANAGE_PERMISSIONS": true,
		"MANAGE_WEBHOOKS": true
	},

	voiceChannnelPermissions: [
		"CONNECT", // connect to voice
		"SPEAK", // speak on voice
		"MUTE_MEMBERS", // globally mute members on voice
		"DEAFEN_MEMBERS", // globally deafen members on voice
		"MOVE_MEMBERS", // move member's voice channels
		"USE_VAD", // use voice activity detection
		"CREATE_INSTANT_INVITE",
		"MANAGE_CHANNEL",
		"MANAGE_PERMISSIONS",
		"MANAGE_WEBHOOKS"
	],

	voiceChannnelPermissionsObj: {
		"CONNECT": true, // connect to voice
		"SPEAK": true, // speak on voice
		"MUTE_MEMBERS": true, // globally mute members on voice
		"DEAFEN_MEMBERS": true, // globally deafen members on voice
		"MOVE_MEMBERS": true, // move member's voice channels
		"USE_VAD": true, // use voice activity detection
		"CREATE_INSTANT_INVITE": true,
		"MANAGE_CHANNEL": true,
		"MANAGE_PERMISSIONS": true,
		"MANAGE_WEBHOOKS": true
	},

	permissionsOrder: {
		"ADMINISTRATOR": 27,
		"MANAGE_GUILD": 26,
		"MANAGE_ROLES": 25,
		"MANAGE_CHANNELS": 24,
		"MANAGE_CHANNEL": 24, // Channel
		"MANAGE_WEBHOOKS": 23,
		"MANAGE_EMOJIS": 22,
		"MANAGE_PERMISSIONS": 22, // Channel
		"VIEW_AUDIT_LOG": 21,
		"MENTION_EVERYONE": 20,
		"BAN_MEMBERS": 19,
		"KICK_MEMBERS": 18,
		"MOVE_MEMBERS": 17,
		"DEAFEN_MEMBERS": 16,
		"MUTE_MEMBERS": 15,
		"MANAGE_MESSAGES": 14,
		"MANAGE_NICKNAMES": 13,
		"USE_EXTERNAL_EMOJIS": 12,
		"ATTACH_FILES": 11,
		"SEND_TTS_MESSAGES": 10,
		"ADD_REACTIONS": 9,
		"EMBED_LINKS": 8,
		"CHANGE_NICKNAME": 7,
		"USE_VAD": 6,
		"SPEAK": 5,
		"CONNECT": 4,
		"CREATE_INSTANT_INVITE": 3,
		"SEND_MESSAGES": 2,
		"READ_MESSAGE_HISTORY": 1,
		"READ_MESSAGES": 0
	},
};

exports = module.exports;<commit_msg>Fixed paths<commit_after>/*

var (\w+?) =
$1:

[^}];
,

*/

module.exports = {
	selfId: "224529399003742210",
	vaebId: "107593015014486016",

	mutesDir: "./data/mutes.json",
	histDir: "./data/history.json",
	autoRoleDir: "./data/autoroles.json",
	playlistDir: "./data/playlist.json",

	rolePermissions: [
		"CREATE_INSTANT_INVITE",
		"KICK_MEMBERS",
		"BAN_MEMBERS",
		"VIEW_AUDIT_LOG",
		"ADMINISTRATOR",
		"MANAGE_CHANNELS",
		"MANAGE_GUILD",
		"ADD_REACTIONS", // add reactions to messages
		"READ_MESSAGES",
		"SEND_MESSAGES",
		"SEND_TTS_MESSAGES",
		"MANAGE_MESSAGES",
		"EMBED_LINKS",
		"ATTACH_FILES",
		"READ_MESSAGE_HISTORY",
		"MENTION_EVERYONE",
		"USE_EXTERNAL_EMOJIS", // use external emojis
		"CONNECT", // connect to voice
		"SPEAK", // speak on voice
		"MUTE_MEMBERS", // globally mute members on voice
		"DEAFEN_MEMBERS", // globally deafen members on voice
		"MOVE_MEMBERS", // move member's voice channels
		"USE_VAD", // use voice activity detection
		"CHANGE_NICKNAME",
		"MANAGE_NICKNAMES", // change nicknames of others
		"MANAGE_ROLES",
		"MANAGE_WEBHOOKS",
		"MANAGE_EMOJIS"
	],

	rolePermissionsObj: {
		"CREATE_INSTANT_INVITE": true,
		"KICK_MEMBERS": true,
		"BAN_MEMBERS": true,
		"VIEW_AUDIT_LOG": true,
		"ADMINISTRATOR": true,
		"MANAGE_CHANNELS": true,
		"MANAGE_GUILD": true,
		"ADD_REACTIONS": true, // add reactions to messages
		"READ_MESSAGES": true,
		"SEND_MESSAGES": true,
		"SEND_TTS_MESSAGES": true,
		"MANAGE_MESSAGES": true,
		"EMBED_LINKS": true,
		"ATTACH_FILES": true,
		"READ_MESSAGE_HISTORY": true,
		"MENTION_EVERYONE": true,
		"USE_EXTERNAL_EMOJIS": true, // use external emojis
		"CONNECT": true, // connect to voice
		"SPEAK": true, // speak on voice
		"MUTE_MEMBERS": true, // globally mute members on voice
		"DEAFEN_MEMBERS": true, // globally deafen members on voice
		"MOVE_MEMBERS": true, // move member's voice channels
		"USE_VAD": true, // use voice activity detection
		"CHANGE_NICKNAME": true,
		"MANAGE_NICKNAMES": true, // change nicknames of others
		"MANAGE_ROLES": true,
		"MANAGE_WEBHOOKS": true,
		"MANAGE_EMOJIS": true
	},

	textChannnelPermissions: [
		"CREATE_INSTANT_INVITE",
		"MANAGE_CHANNEL",
		"ADD_REACTIONS", // add reactions to messages
		"READ_MESSAGES",
		"SEND_MESSAGES",
		"SEND_TTS_MESSAGES",
		"MANAGE_MESSAGES",
		"EMBED_LINKS",
		"ATTACH_FILES",
		"READ_MESSAGE_HISTORY",
		"MENTION_EVERYONE",
		"USE_EXTERNAL_EMOJIS", // use external emojis
		"MANAGE_PERMISSIONS",
		"MANAGE_WEBHOOKS"
	],

	textChannnelPermissionsObj: {
		"ADD_REACTIONS": true, // add reactions to messages
		"READ_MESSAGES": true,
		"SEND_MESSAGES": true,
		"SEND_TTS_MESSAGES": true,
		"MANAGE_MESSAGES": true,
		"EMBED_LINKS": true,
		"ATTACH_FILES": true,
		"READ_MESSAGE_HISTORY": true,
		"MENTION_EVERYONE": true,
		"USE_EXTERNAL_EMOJIS": true, // use external emojis
		"CREATE_INSTANT_INVITE": true,
		"MANAGE_CHANNEL": true,
		"MANAGE_PERMISSIONS": true,
		"MANAGE_WEBHOOKS": true
	},

	voiceChannnelPermissions: [
		"CONNECT", // connect to voice
		"SPEAK", // speak on voice
		"MUTE_MEMBERS", // globally mute members on voice
		"DEAFEN_MEMBERS", // globally deafen members on voice
		"MOVE_MEMBERS", // move member's voice channels
		"USE_VAD", // use voice activity detection
		"CREATE_INSTANT_INVITE",
		"MANAGE_CHANNEL",
		"MANAGE_PERMISSIONS",
		"MANAGE_WEBHOOKS"
	],

	voiceChannnelPermissionsObj: {
		"CONNECT": true, // connect to voice
		"SPEAK": true, // speak on voice
		"MUTE_MEMBERS": true, // globally mute members on voice
		"DEAFEN_MEMBERS": true, // globally deafen members on voice
		"MOVE_MEMBERS": true, // move member's voice channels
		"USE_VAD": true, // use voice activity detection
		"CREATE_INSTANT_INVITE": true,
		"MANAGE_CHANNEL": true,
		"MANAGE_PERMISSIONS": true,
		"MANAGE_WEBHOOKS": true
	},

	permissionsOrder: {
		"ADMINISTRATOR": 27,
		"MANAGE_GUILD": 26,
		"MANAGE_ROLES": 25,
		"MANAGE_CHANNELS": 24,
		"MANAGE_CHANNEL": 24, // Channel
		"MANAGE_WEBHOOKS": 23,
		"MANAGE_EMOJIS": 22,
		"MANAGE_PERMISSIONS": 22, // Channel
		"VIEW_AUDIT_LOG": 21,
		"MENTION_EVERYONE": 20,
		"BAN_MEMBERS": 19,
		"KICK_MEMBERS": 18,
		"MOVE_MEMBERS": 17,
		"DEAFEN_MEMBERS": 16,
		"MUTE_MEMBERS": 15,
		"MANAGE_MESSAGES": 14,
		"MANAGE_NICKNAMES": 13,
		"USE_EXTERNAL_EMOJIS": 12,
		"ATTACH_FILES": 11,
		"SEND_TTS_MESSAGES": 10,
		"ADD_REACTIONS": 9,
		"EMBED_LINKS": 8,
		"CHANGE_NICKNAME": 7,
		"USE_VAD": 6,
		"SPEAK": 5,
		"CONNECT": 4,
		"CREATE_INSTANT_INVITE": 3,
		"SEND_MESSAGES": 2,
		"READ_MESSAGE_HISTORY": 1,
		"READ_MESSAGES": 0
	},
};

exports = module.exports;<|endoftext|>


<commit_before>function KIFNode(kifExpressions) {
  this.type = 'KIFNode';
  this.expressions = this.expressions || [];
  this.expressions = this.expressions.concat(kifExpressions);
}

function WordNode(identifier) {
  this.type = 'WordNode';
  this.word = identifier;
}

function VariableNode(identifier, variableType) {
  this.type = 'VariableNode';
  this.variableType = variableType || 'IND';
  this.variableName = identifier;
}

function FunctionTermNode(funcName, argsList) {
  this.type = 'FunctionTermNode';
  this.functionName = funcName;
  this.functionArgumentList = this.functionArgumentList || [];
  this.functionArgumentList = this.functionArgumentList.concat(argsList);
}

function EquationNode(firstTerm, secondTerm) {
  this.type = 'EquationNode';
  this.terms = this.terms || [];
  this.terms = this.terms.concat(firstTerm, secondTerm);
}

module.exports = {
  KIFNode: KIFNode,
  WordNode: WordNode,
  VariableNode: VariableNode,
  FunctionTermNode: FunctionTermNode,
  EquationNode: EquationNode
};
<commit_msg>Add StringLiteralNode to ast constructors<commit_after>function KIFNode(kifExpressions) {
  this.type = 'KIFNode';
  this.expressions = this.expressions || [];
  this.expressions = this.expressions.concat(kifExpressions);
}

function WordNode(identifier) {
  this.type = 'WordNode';
  this.word = identifier;
}

function VariableNode(identifier, variableType) {
  this.type = 'VariableNode';
  this.variableType = variableType || 'IND';
  this.variableName = identifier;
}

function FunctionTermNode(funcName, argsList) {
  this.type = 'FunctionTermNode';
  this.functionName = funcName;
  this.functionArgumentList = this.functionArgumentList || [];
  this.functionArgumentList = this.functionArgumentList.concat(argsList);
}

function EquationNode(firstTerm, secondTerm) {
  this.type = 'EquationNode';
  this.terms = this.terms || [];
  this.terms = this.terms.concat(firstTerm, secondTerm);
}

function StringLiteralNode(rawString) {
  this.type = 'StringLiteralNode';
  this.rawString = rawString;
  this.chars = rawString.substring(1, rawString.length - 1);
}

module.exports = {
  KIFNode: KIFNode,
  WordNode: WordNode,
  VariableNode: VariableNode,
  StringLiteralNode: StringLiteralNode,
  FunctionTermNode: FunctionTermNode,
  EquationNode: EquationNode
};
<|endoftext|>