<!--
 * @Author: 梁平贤
 * @Description: 区间输入
 * @Date: 2020-05-11 17:25:18
 * @LastEditors: czm
 * @LastEditTime: 2020-12-07 09:47:19
 * @FilePath: /en-components/packages/components/en-input-range/src/index.vue
 -->
<template>
  <div
    class="en-input-range"
    :class="[inputDisabled ? 'is-disabled' : '', inputting ? 'is-active' : '']"
    @click="handleRangeClick"
    @mouseenter="handleMouseEnter"
    @mouseleave="showClose = false"
    @keydown="handleKeydown"
    ref="reference"
    v-clickoutside="handleClose"
  >
    <!-- <i :class="['el-input__icon', 'el-range__icon', triggerClass]"></i> -->
    <en-input-number
      autocomplete="off"
      :disabled="inputDisabled"
      :placeholder="startPlaceholder"
      v-model="inputValue[0]"
      :readonly="!editable || readonly"
      :name="name && name[0]"
      @change="handleStartChange"
      @focus="handleFocus"
      :max="inputValue[1]"
      :min="min"
      :precision="precision"
      :thousandFormat="thousandFormat"
    ></en-input-number>
    <slot name="range-separator">
      <span class="el-range-separator">{{ rangeSeparator }}</span>
    </slot>
    <en-input-number
      autocomplete="off"
      :placeholder="endPlaceholder"
      :value="inputValue[1]"
      :disabled="inputDisabled"
      :readonly="!editable || readonly"
      :name="name && name[1]"
      @change="handleEndChange"
      @focus="handleFocus"
      :max="max"
      :min="inputValue[0]"
      :precision="precision"
      :thousandFormat="thousandFormat"
    ></en-input-number>
    <!-- <i
      @click="handleClickIcon"
      :class="[showClose ? '' + clearIcon : '']"
      class="el-input__icon el-range__close-icon"
    >
    </i> -->
  </div>
</template>

<script>
import Clickoutside from "element-ui/src/utils/clickoutside";
import Emitter from "element-ui/src/mixins/emitter";
const isString = function(val) {
  return typeof val === "string" || val instanceof String;
};

const validator = function(val) {
  // either: String, Array of String, null / undefined
  return (
    val === null ||
    val === undefined ||
    isString(val) ||
    (Array.isArray(val) && val.length === 2 && val.every(isString))
  );
};

export default {
  name: "EnInputRange",
  model: {
    prop: "value",
    event: "input"
  },
  inject: {
    elForm: {
      default: ""
    },
    elFormItem: {
      default: ""
    }
  },
  mixins: [Emitter],
  props: {
    readonly: Boolean,
    placeholder: String,
    startPlaceholder: String,
    endPlaceholder: String,
    prefixIcon: String,
    clearIcon: {
      type: String,
      default: "el-icon-circle-close"
    },
    name: {
      default: "",
      validator
    },
    disabled: Boolean,
    clearable: {
      type: Boolean,
      default: true
    },
    editable: {
      type: Boolean,
      default: true
    },
    value: {
      type: Array,
      default: function() {
        return [0, 0];
      }
    },
    rangeSeparator: {
      default: "-"
    },
    validateEvent: {
      type: Boolean,
      default: true
    },
    // 小数位数
    precision: {
      type: Number,
      validator(val) {
        return val >= 0 && val === parseInt(val, 10);
      }
    },
    // 支持千分位展示
    thousandFormat: {
      type: Boolean,
      default: false
    },
    // 支持的最大值
    max: {
      type: Number,
      default: Infinity
    },
    // 最小值
    min: {
      type: Number,
      default: -Infinity
    }
  },

  directives: { Clickoutside },

  data() {
    return {
      inputting: false,
      showClose: false,
      // value 直接绑定props会报错
      inputValue: this.value,
      valueOnOpen: null // 初始化的值,用来对比是否emit change
    };
  },

  watch: {
    value(newVal) {
      this.inputValue = [...newVal]
    },
    inputting(val) {
      if (this.readonly) return;
      if (val) {
        this.valueOnOpen = Array.isArray(this.inputValue)
          ? [...this.inputValue]
          : this.inputValue;
      } else {
        this.emitChange(this.inputValue);
        if (this.validateEvent) {
          this.dispatch("ElFormItem", "el.form.blur");
        }
        this.$emit("blur", this);
        this.blur();
      }
    },
    inputValue(val, oldVal) {
      if (val !== oldVal && this.validateEvent) {
        this.dispatch("ElFormItem", "el.form.change", val);
      }
    }
  },

  computed: {
    // 包含两个输入框的ref
    reference() {
      const reference = this.$refs.reference;
      return reference.$el || reference;
    },
    // 这里只能用input,因为文档的activeElement取到的是input,用以对比,是不是组件是focus的
    refInput() {
      if (this.reference) {
        return [].slice.call(this.reference.querySelectorAll("input"));
      }
      return [];
    },
    triggerClass() {
      return this.prefixIcon;
    },
    inputDisabled() {
      return this.disabled || (this.elForm || {}).disabled;
    }
  },

  created() {
    this.$on("fieldReset", this.handleFieldReset);
  },

  methods: {
    focus() {
      this.handleFocus();
    },
    blur() {
      this.refInput.forEach(input => input.blur());
    },
    handleMouseEnter() {
      if (this.readonly || this.inputDisabled) return;
      if (this.clearable) {
        this.showClose = true;
      }
    },
    // 其实控件输入已经做了限制了不会超出范围
    handleStartChange(val) {
      if (val > this.inputValue[1]) {
        val = this.inputValue[1];
      }
      this.inputValue[0] = val;
    },
    // 其实控件输入已经做了限制了不会超出范围
    handleEndChange(val) {
      if (val < this.inputValue[0]) {
        val = this.inputValue[0];
      }
      // this.value[1] = val;
      this.inputValue.splice(1, 1, val);
    },

    // handleClickIcon(event) {
    //   if (this.readonly || this.inputDisabled) return;
    //   if (this.showClose) {
    //     this.valueOnOpen = this.value;
    //     event.stopPropagation();
    //     this.emitInput(null);
    //     this.emitChange(null);
    //     this.showClose = false;
    //   } else {
    //     this.inputting = !this.inputting;
    //   }
    // },

    handleClose() {
      if (!this.inputting) return;
      this.inputting = false;
    },

    handleFieldReset(initialValue) {
      this.inputValue = initialValue === "" ? null : initialValue;
    },
    // focus事件
    handleFocus() {
      this.inputting = true;
      this.$emit("focus", this);
    },
    // 按钮事件
    handleKeydown(event) {
      const keyCode = event.keyCode;

      // ESC
      if (keyCode === 27) {
        this.inputting = false;
        event.stopPropagation();
        return;
      }

      // Tab
      if (keyCode === 9) {
        // user may change focus between two input
        setTimeout(() => {
          if (this.refInput.indexOf(document.activeElement) === -1) {
            this.inputting = false;
            this.blur();
            event.stopPropagation();
          }
        }, 0);
        return;
      }

      // Enter
      if (keyCode === 13) {
        this.inputting = false;
        this.blur();
        event.stopPropagation();
      }
    },
    handleRangeClick() {
      this.$emit("focus", this);
    },
    emitChange(val) {
      // 需要copy
      const emitVal = [...val];
      this.inputValue = emitVal;
      this.$emit("change", emitVal);
      this.$emit("input", emitVal);
      this.valueOnOpen = val;
      if (this.validateEvent) {
        this.dispatch("ElFormItem", "el.form.change", emitVal);
      }
    }
  }
};
</script>
<style lang="scss" scoped>
.en-input-range {
  display: inline-block;
  box-sizing: border-box;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #dcdfe6;
  box-sizing: border-box;
  color: #606266;
  display: inline-block;
  font-size: inherit;
  outline: 0;
  overflow: hidden;
  .en-input-number /deep/ .el-input {
    height: 32px;
    line-height: 32px;
  }
  .en-input-number {
    appearance: none;
    border: none;
    outline: none;
    display: inline-block;
    height: 100%;
    margin: 0;
    padding: 0;
    width: 47.5%;
    font-size: 12px;
  }
  .en-input-number /deep/ .el-input__inner {
    appearance: none;
    border: none;
    outline: none;
    font-size: 12px;
  }
  .el-range__icon {
    font-size: 14px;
    margin-left: -5px;
    float: left;
    line-height: 32px;
  }

  .el-range-separator {
    display: inline-block;
    height: 100%;
    padding: 0 5px;
    margin: 0;
    text-align: left;
    line-height: 32px;
    font-size: 12px;
    width: 5%;
    color: #a9b5c6;
  }
}

.en-input-range:hover {
  border: 1px solid #a2cdf7;
}
.en-input-range.is-active {
  border: 1px solid #4694df;
}
.en-input-range.is-disabled {
  border: 1px solid #e8ecf2;
  background-color: #f5f7fa;
}
</style>
