vue.js 掃碼槍 input 輸入法問題

Chobits發表於2017-02-21
import { Observable } from "rxjs";

const Sdic = {
  "1": "!",
  "2": "@",
  "3": "#",
  "4": "$",
  "5": "%",
  "6": "^",
  "7": "&",
  "8": "*",
  "9": "(",
  "0": ")",
  "-": "_",
  "=": "+",
  "[": "{",
  "]": "}",
  "\": "|",
  ";": ":",
  "`": `"`,
  ",": "<",
  ".": ">",
  "/": "?"
};

function IsLower(s: string) {
  return s.toLowerCase() === s;
}

function GetShiftChar(cur: KeyboardEvent): string {
  if (cur.keyCode >= 65 && cur.keyCode <= 90) {
    return IsLower(cur.key) ? cur.key.toUpperCase() : cur.key.toLowerCase();
  } else {
    return Sdic[cur.key];
  }
}

function GetStop(input: HTMLInputElement) {
  const end$ = Observable.fromEvent(input, "compositionend");
  const keyup$ = Observable.fromEvent<KeyboardEvent>(input, "keyup");
  const enter$ = keyup$.filter(e => e.keyCode === 13);
  return Observable.combineLatest(end$.merge(enter$), keyup$).debounceTime(250);
}

function GetLast(str: string) {
  return str.substr(str.length - 1, 1);
}

export function GetInputSource(input: HTMLInputElement) {
  const stop$ = GetStop(input);

  return Observable.fromEvent<KeyboardEvent>(input, "keyup")
    .scan(
      (prev, cur) => {
        // //漢字
        // if (cur.keyCode === 231) {
        //   return {
        //     IsShift: false,
        //     key: GetLast(input.value)
        //   };
        // }

        return {
          IsShift: cur.keyCode === 16,
          key: prev.IsShift ? GetShiftChar(cur) : cur.key
        };
      },
      { IsShift: false, key: "" }
    )
    .map(t => t.key)
    .filter(t => t != null && t.length === 1)
    .bufferWhen(() => stop$)
    .map(arr => arr.join("").trim());
}

<template>
  <div>
    <div class="input-group">
      <input type="text"
             class="form-control"
             :readonly="readonly"
             ref="input" />
      <span class="input-group-btn">
        <button type="button"
                class="btn btn-danger"
                @click="clear">X</button>
      </span>
    </div>
    <ul>
      <li v-for="(s, i) in list"
          :key="i"
          v-text="s">
      </li>
    </ul>
  </div>
</template>

<script>
  import { GetInputSource } from `@/utils/Typeahead.ts`;
  const TRUE_RESULT = `123abc!@#$%^&<>;[]`;

  export default {
    data() {
      return {
        value: ``,
        TRUE_RESULT,
        list: []
      }
    },
    computed: {
      readonly() {
        return this.value != null && this.value != ``;
      }
    },
    mounted() {
      this.clear();
    },
    methods: {
      init() {
        const input = this.$refs.input;
        this.sub && this.sub.unsubscribe();
        this.sub = GetInputSource(input)
          .takeWhile(() => !this.readonly)
          .subscribe(this.add);
      },
      add(str) {
        console.log(str);
        console.log(str === TRUE_RESULT);
        this.SetValue(str);
        this.list.push(str);
      },
      async SetValue(val) {
        this.value = val;
        await this.$nextTick();
        const input = this.$refs.input;
        input.value = val;
        input.focus();
      },
      clear() {
        this.init();
        this.SetValue(``);
      }
    },
    beforeDestroy() {
      this.sub && this.sub.unsubscribe();
    }
  }
</script>

相關文章