weex-nuke
Version: 
基于 Rax 、Weex 的高性能组件体系 ~~
218 lines (205 loc) • 5.51 kB
JSX
'use strict';
/** @jsx createElement */
import { createElement, Component, PropTypes } from 'rax';
import { isWeb, isWeex } from 'nuke-env';
import { getText, genEventObject } from './util';
class BaseInput extends Component {
  constructor(props, context) {
    super(props);
    this.fixedFont = context.commonConfigs && context.commonConfigs.fixedFont;
    if ('fixedFont' in props) {
      this.fixedFont = props.fixedFont;
    }
    this.getRef = this.getRef.bind(this);
    this.setNativeFormatRule = this.setNativeFormatRule.bind(this);
    this.inputHandler = this.inputHandler.bind(this);
    this.returnHandler = this.returnHandler.bind(this);
    this.changeHandler = this.changeHandler.bind(this);
    this.focusHandler = this.focusHandler.bind(this);
    this.blurHandler = this.blurHandler.bind(this);
    this.focus = this.focus.bind(this);
    this.blur = this.blur.bind(this);
  }
  shouldComponentUpdate(nextProps) {
    if (nextProps.value !== null) {
      return (
        nextProps.value !== this.props.value ||
        nextProps.readOnly !== this.props.readOnly ||
        nextProps.type !== this.props.type ||
        nextProps.disabled !== this.props.disabled ||
        nextProps.maxLength !== this.props.maxLength ||
        nextProps['data-style'] !== this.props['data-style'] ||
        nextProps.style !== this.props.style ||
        nextProps.placeholder !== this.props.placeholder
      );
    }
    return (
      typeof nextProps.value !== typeof this.props.value ||
      nextProps.readOnly !== this.props.readOnly ||
      nextProps.type !== this.props.type ||
      nextProps.disabled !== this.props.disabled ||
      nextProps.maxLength !== this.props.maxLength ||
      nextProps.style !== this.props['data-style'] ||
      nextProps.style !== this.props.style ||
      nextProps.placeholder !== this.props.placeholder
    );
  }
  getValue() {
    if (isWeb) {
      return this.refs.input.value;
    }
    return this.refs.input.attr.value;
  }
  getRef() {
    return this.refs.input;
  }
  setNativeFormatRule(rules) {
    this.refs.input.setTextFormatter(rules);
  }
  trigger(fn, ...attrs) {
    if (typeof fn === 'string') fn = this.props[fn];
    if (!(typeof fn === 'function')) return;
    return fn.apply(this, attrs);
  }
  focusHandler(e) {
    this.trigger('onFocus', e);
  }
  focus() {
    this.focusInput();
  }
  focusInput() {
    this.refs.input.focus && this.refs.input.focus();
  }
  blur() {
    this.blurInput();
  }
  blurInput() {
    this.refs.input.blur && this.refs.input.blur();
  }
  blurHandler(e) {
    this.setState({
      focus: false,
    });
    this.trigger('onBlur', e);
  }
  returnHandler(e) {
    if (isWeb) {
      if (e.keyCode === 13) {
        this.trigger('onReturn', genEventObject(e));
      }
    } else {
      this.trigger('onReturn', e);
    }
  }
  inputHandler(e) {
    this.trigger('onInput', getText(e), genEventObject(e));
  }
  changeHandler(e) {
    const value = getText(e);
    const { maxLength } = this.props;
    if (maxLength && value && value.length > maxLength) return;
    if ('value' in this.props) {
      this.setState({ value });
    }
    this.trigger('onChange', value, genEventObject(e));
  }
  render() {
    const {
      value,
      // onChange,
      onFocus,
      onInput,
      onBlur,
      readOnly,
      disabled,
      style,
      maxLength,
      multiple,
      returnKeyType,
      autoFocus,
      fixedFont,
      rows,
      type,
      placeholderColor,
      ...others
    } = this.props;
    const attrs = {
      onChange: this.changeHandler,
      onInput: this.inputHandler,
      onFocus: this.focusHandler,
      onBlur: this.blurHandler,
      disabled,
      rows,
      returnKeyType,
      maxlength: maxLength,
      readOnly,
      autofocus: autoFocus,
      placeholderColor,
      style: Object.assign({}, styles.default, isWeb ? styles.defaultWeb : {}, style),
    };
    if (!multiple) {
      attrs.type = type;
    }
    if ('value' in this.props) {
      attrs.value = value;
    }
    if (isWeb) {
      attrs.onKeyUp = this.returnHandler;
      // keys that should not be passed
      ['readOnly', 'autofocus'].map((item) => {
        if (item in attrs && !attrs[item]) {
          delete attrs[item];
        }
      });
    } else {
      attrs.onReturn = this.returnHandler;
      attrs['data-placeholder-color'] = placeholderColor;
      // in multiple mode, passing returnKeyType to weex will get single line input
      if (multiple && !this.props.onReturn) {
        delete attrs.onReturn;
        delete attrs.returnKeyType;
      }
    }
    let inputElement;
    if (multiple) {
      if (isWeb) {
        inputElement = (
          <textarea {...others} {...attrs} ref="input">
            {attrs.value}
          </textarea>
        );
      } else {
        inputElement = <textarea {...others} {...attrs} ref="input" />;
      }
    } else {
      inputElement = <input {...others} {...attrs} ref="input" />;
    }
    return inputElement;
  }
}
BaseInput.contextTypes = {
  androidConfigs: PropTypes.any,
};
BaseInput.defaultProps = {
  rows: 2,
  style: {},
  readOnly: false,
};
const styles = {
  default: {
    backgroundColor: 'transparent',
    borderWidth: 0,
    color: '#000000',
    padding: 0,
    fontSize: 24,
    lineHeight: 60,
  },
  defaultWeb: {
    width: '100%',
    boxSizing: 'border-box',
    outline: 'none',
    appearance: 'none',
  },
};
BaseInput.displayName = 'BaseInput';
export default BaseInput;