# Input demo

* order: 2

信用卡类型

---

```js
/** @jsx createElement */
import { createElement, Component, findDOMNode, render } from 'rax';
import View from 'nuke-view';
import Text from 'nuke-text';
import Input from 'nuke-input';
import Icon from 'nuke-icon';
import Env from 'nuke-env';
const { isWeex } = Env;
import Button from 'nuke-button';
import Page from 'nuke-page';
import { StyleProvider } from 'nuke-theme-provider';

const KEYS = {
  '0': 48,
  '9': 57,
  DELETE: 46,
  BACKSPACE: 8,
  ARROW_LEFT: 37,
  ARROW_RIGHT: 39,
  ARROW_UP: 38,
  ARROW_DOWN: 40,
  HOME: 36,
  END: 35,
  TAB: 9,
  A: 65,
  X: 88,
  C: 67,
  V: 86
};
const CREDIT_CARD_NUMBER_DEFAULT_MASK = 'XXXX XXXX XXXX XXXX';

let md = {
  Core: {
    'color-brand1-1': '#00BBD3',
    'color-brand1-6': '#1A9CB7',
    'color-brand1-9': '#0096A6',
    'color-error-3': '#D50000',
    'color-line1-1': '#DADADA',
    'color-line1-2': '#E0E0E0',
    'color-text1-1': '#9E9E9E',
    ['font-size-title']: 40,
    ['font-size-subhead']: 32,
    ['font-size-body-3']: 28,
    ['font-size-body-2']: 28,
    ['font-size-body-1']: 28,
    ['font-size-caption']: 24,
    ['font-size-footnote']: 20
  },
  Input: {
    'md-border-radius': 0,
    'single-radius': 4,
    'single-font-size': 28,
    'error-text-color': '#F44336',
    'error-border-color': '#F44336',
    'md-placeholder-height': 50,
    'md-help-margin-top': 16,
    'md-help-height': 56,
    'md-input-height': 50,
    'md-focus-placeholder-color': '#9E9E9E',
    'md-placeholder-font-size': 28,
    'md-input-margin-bottom': 0,
    'md-input-margin-top': 14,
    'md-error-text-font-size': 24
  }
};
let App = class NukeDemoIndex extends Component {
  constructor() {
    super();
  }
  input = () => {};
  change = () => {};

  // 过滤非数字输入，在android端可能存在兼容性问题
  filterNumberOnlyKey(event) {
    var isNumber = this.keyIsNumber(event);
    var isDeletion = this.keyIsDeletion(event);
    var isArrow = this.keyIsArrow(event);

    if (!isNumber && !isDeletion && !isArrow) {
      event.preventDefault();
      return false;
    }
  }
  keyCodeFromEvent(event) {
    var charKeyCode = event.which || event.keyCode;
    return charKeyCode;
  }

  keyIsNumber(event) {
    var keyCode = this.keyCodeFromEvent(event);
    return (keyCode >= KEYS['0'] && keyCode <= KEYS['9']) || keyCode == 229;
  }
  keyIsDelete(event) {
    return this.keyCodeFromEvent(event) == KEYS['DELETE'];
  }
  keyIsBackSpace(event) {
    return this.keyCodeFromEvent(event) == KEYS['BACKSPACE'];
  }
  keyIsDeletion(event) {
    return this.keyIsDelete(event) || this.keyIsBackSpace(event);
  }
  keyIsArrow(event) {
    const keyCode = this.keyCodeFromEvent(event);
    return keyCode >= KEYS['ARROW_LEFT'] && keyCode <= KEYS['ARROW_DOWN'];
  }
  // 选取开始
  caretStartPosition(element) {
    if (typeof element.selectionStart == 'number') {
      return element.selectionStart;
    }
    return false;
  }
  //选取结束
  caretEndPosition(element) {
    if (typeof element.selectionEnd == 'number') {
      return element.selectionEnd;
    }
    return false;
  }
  // 设置回删
  setCaretPosition(element, caretPos) {
    if (element != null) {
      if (element.createTextRange) {
        var range = element.createTextRange();
        range.move('character', caretPos);
        range.select();
      } else {
        if (element.selectionStart) {
          element.focus();
          element.setSelectionRange(caretPos, caretPos);
        } else {
          element.focus();
        }
      }
    }
  }
  digitFromKeyCode(keyCode) {
    if (keyCode >= KEYS['0'] && keyCode <= KEYS['9']) {
      return keyCode - KEYS['0'];
    }
  }
  normaliseCaretPosition(mask, caretPosition) {
    var numberPos = 0;
    if (caretPosition < 0 || caretPosition > mask.length) {
      return 0;
    }
    for (var i = 0; i < mask.length; i++) {
      if (i == caretPosition) {
        return numberPos;
      }
      if (mask[i] == 'X') {
        numberPos++;
      }
    }
    return numberPos;
  }
  denormaliseCaretPosition(mask, caretPosition) {
    var numberPos = 0;
    if (caretPosition < 0 || caretPosition > mask.length) {
      return 0;
    }
    for (var i = 0; i < mask.length; i++) {
      if (numberPos == caretPosition) {
        return i;
      }
      if (mask[i] == 'X') {
        numberPos++;
      }
    }
    return mask.length;
  }
  numbersOnlyString(string) {
    var numbersOnlyString = '';
    for (var i = 0; i < string.length; i++) {
      var currentChar = string.charAt(i);
      var isValid = !isNaN(parseInt(currentChar));
      if (isValid) {
        numbersOnlyString += currentChar;
      }
    }
    return numbersOnlyString;
  }
  applyFormatMask(string, mask) {
    var formattedString = '';
    var numberPos = 0;
    for (var j = 0; j < mask.length; j++) {
      var currentMaskChar = mask[j];
      if (currentMaskChar == 'X') {
        var digit = string.charAt(numberPos);
        if (!digit) {
          break;
        }
        formattedString += string.charAt(numberPos);
        numberPos++;
      } else {
        if (!digit) break;
        formattedString += currentMaskChar;
      }
    }
    return formattedString;
  }

  handleMaskedNumberInputKey = e => {
    console.log('handleMaskedNumberInputKey', e);

    const mask = CREDIT_CARD_NUMBER_DEFAULT_MASK;
    this.filterNumberOnlyKey(e);

    var keyCode = this.keyCodeFromEvent(e);

    var element = e.target;

    var caretStart = this.caretStartPosition(element);
    var caretEnd = this.caretEndPosition(element);

    // Calculate normalised caret position
    var normalisedStartCaretPosition = this.normaliseCaretPosition(
      mask,
      caretStart
    );
    var normalisedEndCaretPosition = this.normaliseCaretPosition(
      mask,
      caretEnd
    );
    var newCaretPosition = caretStart;

    var isNumber = this.keyIsNumber(e);
    var isDelete = this.keyIsDelete(e);
    var isBackspace = this.keyIsBackSpace(e);

    if (isNumber || isDelete || isBackspace) {
      e.preventDefault();
      var rawText = element.value;
      var numbersOnly = this.numbersOnlyString(rawText);

      var digit = this.digitFromKeyCode(keyCode);

      var rangeHighlighted =
        normalisedEndCaretPosition > normalisedStartCaretPosition;

      // Remove values highlighted (if highlighted)
      if (rangeHighlighted) {
        numbersOnly =
          numbersOnly.slice(0, normalisedStartCaretPosition) +
          numbersOnly.slice(normalisedEndCaretPosition);
      }

      // Forward Action
      if (caretStart != mask.length && digit) {
        // Insert number digit
        if (isNumber && rawText.length <= mask.length) {
          numbersOnly =
            numbersOnly.slice(0, normalisedStartCaretPosition) +
            digit +
            numbersOnly.slice(normalisedStartCaretPosition);

          newCaretPosition = Math.max(
            this.denormaliseCaretPosition(
              mask,
              normalisedStartCaretPosition + 1
            ),
            this.denormaliseCaretPosition(
              mask,
              normalisedStartCaretPosition + 2
            ) - 1
          );
        }

        // Delete
        if (isDelete) {
          numbersOnly =
            numbersOnly.slice(0, normalisedStartCaretPosition) +
            numbersOnly.slice(normalisedStartCaretPosition + 1);
        }
      }

      // Backward Action
      if (caretStart != 0) {
        // Backspace
        if (isBackspace && !rangeHighlighted) {
          numbersOnly =
            numbersOnly.slice(0, normalisedStartCaretPosition - 1) +
            numbersOnly.slice(normalisedStartCaretPosition);
          newCaretPosition = this.denormaliseCaretPosition(
            mask,
            normalisedStartCaretPosition - 1
          );
        }
      }
      console.log(numbersOnly);
      element.value = this.applyFormatMask(numbersOnly, mask);
      this.setCaretPosition(element, newCaretPosition);
    }
  };
  render() {
    return (
      <StyleProvider
        style={md}
        commonConfigs={{ fixedFont: true }}
        androidConfigs={{ materialDesign: true }}
      >
        <Page title="Card Payment">
          <Page.Intro main="CardNumber" />
          <Input
            ref="myinput"
            name="card-number"
            type={'text'}
            onKeyDown={this.handleMaskedNumberInputKey}
            autocomplete={'cc-number'}
            x-autocompletetype="cc-number"
            autocorrect={'off'}
            spellcheck={'off'}
            autocapitalize={'off'}
            onInput={this.input}
            placeholder={'Card Number'}
            onChange={this.change}
            hasClear={true}
          />
        </Page>
      </StyleProvider>
    );
  }
};

render(<App />);
```
