Source: index.js

import dom from './utils/dom';
import toggle from './utils';
import layout from './config/layout';
import rule from './config/rule';
import defaultOptions from './config/defaultOptions';
import { warn, note } from './log';
import { throttle, once } from './utils';
import './stylus/index.styl';
require('core-js/fn/object/assign');
require('core-js/fn/array/virtual/includes');
require('core-js/fn/string/virtual/includes');

export default class plateNumberInput {
  /**
   * 配置项
   * @param {object} options 配置项
   * @param {string} options.el 挂载对应元素里面,传选择器字符串  必填
   * @param {string} options.defaultNumber 初始化时默认的车牌号  非必填
   * @param {boolean} options.isNewpower 车牌类型true:新能源车牌 false:普通车牌 非必填 一般不传
   * @param {string} options.btnSaveText 自定义保存按钮的文字内容  非必填
   * @param {string[]} options.switchText 自定义切换按钮的文字内容  非必填
   * @param {Function} options.onBtnSaveClick 点击保存按钮回调 非必填
   */
  constructor(options) {
    this.options = Object.assign(defaultOptions, options);
    this.el = document.querySelector(this.options.el);
    this.currentIndex = 0;
    this.containerInput = null;
    this.spareSpan = null;
    this.isNewpower = this.options.isNewpower;
    this._generateLayout();
    this.setInputFocus();
    this.setNumberType(this.isNewpower);
    this.bindEvents();
    this.setDefaultNumber(this.options.defaultNumber);
  }
  /**
   * get 当前输入的车牌号码
   * @returns {string}
   */
  getNumber() {
    return this.containerInput.textContent.replace(/\s+/g, '');
  }
  /**
   * get 当前的车牌类型
   * @returns {boolean} true:新能源车牌 false:普通车牌
   */
  getNumberType() {
    return this.isNewpower;
  }
  /**
   * 设置默认车牌号
   * @param {string} plateNumber 车牌号
   */
  setDefaultNumber(plateNumber) {
    // TODO: 设置默认车牌号
    plateNumber = plateNumber.trim();
    const onceSetInputFocus = once(index => this.setInputFocus(index));
    for (let index = 0; index < this.inputSpans.length; index++) {
      const span = this.inputSpans[index];
      span.innerText = plateNumber[index] || '';
      if (plateNumber[index] === undefined) return onceSetInputFocus(index);
      if (index === this.inputSpans.length - 1) return onceSetInputFocus(index);
    }
  }
  /**
   * 设置车牌类型
   * @param {boolean} isNewpower true:新能源车牌 false:普通车牌
   */
  setNumberType(isNewpower = false) {
    this.isNewpower = isNewpower;
    const lastIndex = this.inputSpans.length - 1;
    this.spareSpan.innerText = ''
    if (!this.spareSpan.parentNode && isNewpower) {
      this.containerInput.appendChild(this.spareSpan);
    }
    if (this.spareSpan.parentNode && !isNewpower) {
      this.containerInput.removeChild(this.spareSpan);
    }
    const index = this.currentIndex === lastIndex ? this.inputSpans.length - 1 : this.currentIndex;
    this.setInputFocus(index);
    this.setBtnSaveActive();
  }
  /**
   * 设置输入框上面的站位信息
   * @param {string} info
   */
  setInfo(info) {
    this.containerInfo.innerHTML = info;
  }
  /**初始化绑定各种事件 */
  bindEvents() {
    // 绑定输入框按钮事件
    dom.on(this.containerInput, 'click', 'span', e => {
      const { index } = e.target.dataset;
      this.setInputFocus(Number(index));
    });
    // 模拟键盘 点击事件
    dom.on(this.keyboardWrapper, 'click', 'span', e => {
      const el = e.target;
      const text = el.innerText;
      if (el.className.includes(this.disableKeyItemClassName)) {
        return note('点击的是 已被禁用的键');
      }
      if (el.className.includes(this.placeholderClassName)) {
        return note('点击的是 无效键');
      }
      // 点击的是确定键
      if (text === '确定') {
        this.keyboardWrapper.classList.add('hide');
        return note('点击的是 确定 键');
      }
      if (el.className.includes(this.deleteKeyItemClassName)) {
        this.del();
        return note('点击的是 删除 键');
      }
      // 点击的是普通键
      this.inputSpans[this.currentIndex].innerText = text;
      this.next();
    });
    // 点击切换车牌按钮
    dom.on(this.inputboxWrapper, 'click', '.container-switch-button', e => {
      const el = e.target;
      const text = el.innerText.trim();
      this.options.switchText.forEach(item => {
        if (item === text) return;
        el.innerText = el.innerText.replace(text, item);
      });
      this.setNumberType(!this.isNewpower);
      note('点击的是 切换车牌 按钮');
    });
    // 点击保存按钮
    dom.on(this.inputboxWrapper, 'click', '.btnbind', e => {
      this.options.onBtnSaveClick && this.options.onBtnSaveClick(e);
      note('点击的是 保存 按钮');
    });
  }
  /** 每输入一个字符后调用 */
  next() {
    const nextIndex = this.currentIndex === this.inputSpans.length - 1 ? this.currentIndex : this.currentIndex + 1;
    this.setInputFocus(nextIndex);
  }
  /** 点击删除按钮后调用 */
  del() {
    const prev = this.currentIndex === 0 ? 0 : this.currentIndex - 1;
    this.inputSpans[this.currentIndex].innerText = '';
    this.setInputFocus(prev);
  }
  /**
   * 生成布局
   */
  _generateLayout() {
    // TODO: 获取生成好的html字符串  不包括键盘
    const inputbox = layout.inputbox
      .replace(/{{btnSaveText}}/, this.options.btnSaveText)
      .replace(/{{switchText}}/, this.options.switchText[0]);
    const inputboxEl = dom.create(inputbox);
    this.containerInput = inputboxEl.querySelector('.container-input');
    this.spareSpan = this.containerInput.lastElementChild;
    this.el.appendChild(inputboxEl);
    this.el.appendChild(dom.create(`<div id="keyboardWrapper"></div>`));
    this._generateKeyboard();
  }
  /**
   * 获取键盘容器
   * @returns {Element}
   */
  get keyboardWrapper() {
    return this.el.querySelector('#keyboardWrapper');
  }
  /**
   * 上方输入框容器
   * @returns {Element}
   */
  get inputboxWrapper() {
    return this.el.querySelector('#inputboxWrapper');
  }
  /**
   * 输入框span的数组
   * @returns {HTMLCollection}
   */
  get inputSpans() {
    return this.containerInput.children;
  }
  /**
   * @returns {Element}
   */
  get containerInfo() {
    return this.inputboxWrapper.querySelector('.container-info');
  }
  /**
   * 获取禁用规则
   * @returns {string[]}
   */
  get disableRule() {
    return rule[this.currentIndex];
  }
  get disableKeyItemClassName() {
    return this._prefix('disable');
  }
  get placeholderClassName() {
    return this._prefix('placeholder');
  }
  get deleteKeyItemClassName() {
    return this._prefix('delete');
  }
  /**
   * 设置指定位置输入框active
   * @param {number} index 第几个span
   */
  setInputFocus(index = 0) {
    this.keyboardWrapper.classList.remove('hide');
    for (let i = 0; i < this.inputSpans.length; i++) {
      this.inputSpans[i].classList.remove('focus');
    }
    this.currentIndex = index;    
    this.inputSpans[index].classList.add('focus');
    this._generateKeyboard();
    this.setBtnSaveActive();
  }
  /**
   * 设置保存按钮的高亮效果
   */
  setBtnSaveActive() {
    const { classList } = this.inputboxWrapper.querySelector('#btnSave');
    if (this.getNumber().length === this.inputSpans.length) {
      classList.add('active');
    } else {
      classList.remove('active');
    }
  }
  /**
   * 生成键盘
   */
  _generateKeyboard() {
    const currentKeyboardIndex = this.currentIndex && 1;
    const currentKeyboard = layout.keyboard[currentKeyboardIndex];

    const generatekey = arr =>
      arr.map(item => {
        let classList = this.disableRule.includes(item) ? this.disableKeyItemClassName : '';
        // 占位符设置
        if (item === '') {
          classList += this.placeholderClassName;
        }
        if (item === 'delete') classList += this.deleteKeyItemClassName;
        return `<span class="${this._prefix('item') + classList}" >${item === 'delete' ? '' : item}</span>`;
      });

    const combinationRow = arr =>
      arr.map(items => {
        let row = generatekey(items).join('');
        return `<div class="${this._prefix('row')}">${row}</div>`;
      });
    this.keyboardWrapper.innerHTML = combinationRow(currentKeyboard).join('');
  }
  _prefix(str) {
    return ` keyboard-${str} `;
  }
}