/**
 * colorpicker
 * 颜色选择组件
 */

layui.define(['i18n', 'component'], function (exports) {
  'use strict';

  var $ = layui.$;
  var lay = layui.lay;
  var i18n = layui.i18n;
  var device = layui.device();
  var clickOrMousedown = device.mobile ? 'click' : 'mousedown';

  // 创建组件
  var component = layui.component({
    name: 'colorpicker',

    // 默认配置
    config: {
      color: '', // 默认颜色，默认没有
      size: null, // 选择器大小
      alpha: false, // 是否开启透明度
      format: 'hex', // 颜色显示/输入格式，可选 rgb,hex
      predefine: false, // 预定义颜色是否开启
      colors: [
        // 默认预定义颜色列表
        '#16baaa',
        '#16b777',
        '#1E9FFF',
        '#FF5722',
        '#FFB800',
        '#01AAED',
        '#999',
        '#c00',
        '#ff8c00',
        '#ffd700',
        '#90ee90',
        '#00ced1',
        '#1e90ff',
        '#c71585',
        '#393D49',
        'rgb(0, 186, 189)',
        'rgb(255, 120, 0)',
        'rgb(250, 212, 0)',
        'rgba(0,0,0,.5)',
        'rgba(255, 69, 0, 0.68)',
        'rgba(144, 240, 144, 0.5)',
        'rgba(31, 147, 255, 0.73)'
      ]
    },

    CONST: {
      ELEM: 'layui-colorpicker',
      ELEM_MAIN: '.layui-colorpicker-main',
      ICON_PICKER_DOWN: 'layui-icon-down',
      ICON_PICKER_CLOSE: 'layui-icon-close',
      PICKER_TRIG_SPAN: 'layui-colorpicker-trigger-span',
      PICKER_TRIG_I: 'layui-colorpicker-trigger-i',
      PICKER_SIDE: 'layui-colorpicker-side',
      PICKER_SIDE_SLIDER: 'layui-colorpicker-side-slider',
      PICKER_BASIS: 'layui-colorpicker-basis',
      PICKER_ALPHA_BG: 'layui-colorpicker-alpha-bgcolor',
      PICKER_ALPHA_SLIDER: 'layui-colorpicker-alpha-slider',
      PICKER_BASIS_CUR: 'layui-colorpicker-basis-cursor',
      PICKER_INPUT: 'layui-colorpicker-main-input'
    },

    // 初始化之前
    beforeInit: function () {
      var that = this;
      that.stopClickOutsideEvent = $.noop;
      that.stopResizeEvent = $.noop;
      CONST.PICKER_OPENED = CONST.MOD_ID + '-opened';
    },

    // 渲染之前
    beforeRender: function () {
      var that = this;
      var options = that.config;
      options.target = $('body'); // 后续考虑开放 target 元素
    },

    // 渲染
    render: function () {
      var that = this;
      var options = that.config;

      // 颜色选择框对象
      var elemColorBox = $(that.buildColorBoxTemplate(options));

      // 初始化颜色选择框尺寸
      var elem = options.elem;
      options.size &&
        elemColorBox.addClass('layui-colorpicker-' + options.size);

      // 插入颜色选择框
      elem.addClass('layui-inline').html((that.elemColorBox = elemColorBox));

      // 获取背景色值
      that.color = that.elemColorBox.find(
        '.' + CONST.PICKER_TRIG_SPAN
      )[0].style.background;
    }
  });

  // RGB 转 HSB
  var RGBToHSB = function (rgb) {
    var hsb = { h: 0, s: 0, b: 0 };
    var min = Math.min(rgb.r, rgb.g, rgb.b);
    var max = Math.max(rgb.r, rgb.g, rgb.b);
    var delta = max - min;
    hsb.b = max;
    hsb.s = max !== 0 ? (255 * delta) / max : 0;
    if (hsb.s !== 0) {
      if (rgb.r == max) {
        // 因 rgb 中返回的数字为 string 类型
        hsb.h = (rgb.g - rgb.b) / delta;
      } else if (rgb.g == max) {
        hsb.h = 2 + (rgb.b - rgb.r) / delta;
      } else {
        hsb.h = 4 + (rgb.r - rgb.g) / delta;
      }
    } else {
      hsb.h = -1;
    }
    if (max === min) {
      hsb.h = 0;
    }
    hsb.h *= 60;
    if (hsb.h < 0) {
      hsb.h += 360;
    }
    hsb.s *= 100 / 255;
    hsb.b *= 100 / 255;
    return hsb;
  };

  // HEX 转 HSB
  var HEXToHSB = function (hex) {
    hex = hex.indexOf('#') > -1 ? hex.substring(1) : hex;
    if (hex.length === 3) {
      var num = hex.split('');
      hex = num[0] + num[0] + num[1] + num[1] + num[2] + num[2];
    }
    hex = parseInt(hex, 16);
    var rgb = { r: hex >> 16, g: (hex & 0x00ff00) >> 8, b: hex & 0x0000ff };
    return RGBToHSB(rgb);
  };

  // HSB 转 RGB
  var HSBToRGB = function (hsb) {
    var rgb = {};
    var h = hsb.h;
    var s = (hsb.s * 255) / 100;
    var b = (hsb.b * 255) / 100;

    if (s === 0) {
      rgb.r = rgb.g = rgb.b = b;
    } else {
      var t1 = b;
      var t2 = ((255 - s) * b) / 255;
      var t3 = ((t1 - t2) * (h % 60)) / 60;
      if (h === 360) h = 0;
      if (h < 60) {
        rgb.r = t1;
        rgb.b = t2;
        rgb.g = t2 + t3;
      } else if (h < 120) {
        rgb.g = t1;
        rgb.b = t2;
        rgb.r = t1 - t3;
      } else if (h < 180) {
        rgb.g = t1;
        rgb.r = t2;
        rgb.b = t2 + t3;
      } else if (h < 240) {
        rgb.b = t1;
        rgb.r = t2;
        rgb.g = t1 - t3;
      } else if (h < 300) {
        rgb.b = t1;
        rgb.g = t2;
        rgb.r = t2 + t3;
      } else if (h < 360) {
        rgb.r = t1;
        rgb.g = t2;
        rgb.b = t1 - t3;
      } else {
        rgb.r = 0;
        rgb.g = 0;
        rgb.b = 0;
      }
    }
    return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) };
  };

  // HSB 转 HEX
  var HSBToHEX = function (hsb) {
    var rgb = HSBToRGB(hsb);
    var hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16)];
    $.each(hex, function (nr, val) {
      if (val.length === 1) {
        hex[nr] = '0' + val;
      }
    });
    return hex.join('');
  };

  // 转化成所需 rgb 格式
  var RGBSTo = function (rgbs) {
    var regexp = /[0-9]{1,3}/g;
    var re = rgbs.match(regexp) || [];
    return { r: re[0], g: re[1], b: re[2] };
  };

  var $win = $(window);
  // var $doc = $(document);

  var CONST = component.CONST;

  /**
   * 扩展组件原型方法
   */

  var Class = component.Class;

  // 构建颜色选择框模板
  Class.prototype.buildColorBoxTemplate = function (options) {
    var getBackgroundStyle = function () {
      var bgstr = '';
      if (options.color) {
        bgstr = options.color;

        if ((options.color.match(/[0-9]{1,3}/g) || []).length > 3) {
          //需要优化
          if (!(options.alpha && options.format == 'rgb')) {
            bgstr = '#' + HSBToHEX(RGBToHSB(RGBSTo(options.color)));
          }
        }

        return 'background: ' + bgstr;
      }

      return bgstr;
    };

    return [
      '<div class="layui-unselect layui-colorpicker">',
      '  <span ' +
        (options.format == 'rgb' && options.alpha
          ? 'class="layui-colorpicker-trigger-bgcolor"'
          : '') +
        '>',
      '    <span class="layui-colorpicker-trigger-span"',
      '          lay-type="' +
        (options.format == 'rgb' ? (options.alpha ? 'rgba' : 'torgb') : '') +
        '"',
      '          style="' + getBackgroundStyle() + '">',
      '      <i class="layui-icon layui-colorpicker-trigger-i ' +
        (options.color ? CONST.ICON_PICKER_DOWN : CONST.ICON_PICKER_CLOSE) +
        '"></i>',
      '    </span>',
      '  </span>',
      '</div>'
    ].join('');
  };

  // 构建颜色选择器模板
  Class.prototype.buildColorPickerTemplate = function (options, that) {
    var buildPredefineColors = function () {
      if (options.predefine) {
        var list = ['<div class="layui-colorpicker-main-pre">'];
        layui.each(options.colors, function (i, v) {
          list.push(
            [
              '<div class="layui-colorpicker-pre' +
                ((v.match(/[0-9]{1,3}/g) || []).length > 3
                  ? ' layui-colorpicker-pre-isalpha'
                  : '') +
                '">',
              '  <div style="background:' + v + '"></div>',
              '</div>'
            ].join('')
          );
        });
        list.push('</div>');
        return list.join('');
      } else {
        return '';
      }
    };

    return [
      '<div id="layui-colorpicker' +
        that.index +
        '" data-index="' +
        that.index +
        '" class="layui-anim layui-anim-downbit layui-colorpicker-main">',
      '  <div class="layui-colorpicker-main-wrapper">',
      '    <div class="layui-colorpicker-basis">',
      '      <div class="layui-colorpicker-basis-white"></div>',
      '      <div class="layui-colorpicker-basis-black"></div>',
      '      <div class="layui-colorpicker-basis-cursor"></div>',
      '    </div>',
      '    <div class="layui-colorpicker-side">',
      '      <div class="layui-colorpicker-side-slider"></div>',
      '    </div>',
      '  </div>',
      '  <div class="layui-colorpicker-main-alpha ' +
        (options.alpha ? CONST.CLASS_SHOW : '') +
        '">',
      '    <div class="layui-colorpicker-alpha-bgcolor">',
      '      <div class="layui-colorpicker-alpha-slider"></div>',
      '    </div>',
      '  </div>',
      buildPredefineColors(),
      '  <div class="layui-colorpicker-main-input">',
      '    <div class="layui-inline">',
      '      <input type="text" class="layui-input">',
      '    </div>',
      '    <div class="layui-btn-group">',
      '      <button style="border-radius: 0" class="layui-btn layui-btn-primary layui-btn-sm" colorpicker-events="clear">' +
        i18n.$t('colorpicker.clear') +
        '</button>',
      '      <button style="border-radius: 0; border-left: 0" class="layui-btn layui-btn-primary layui-btn-sm" colorpicker-events="confirm">' +
        i18n.$t('colorpicker.confirm') +
        '</button>',
      '    </div>',
      '  </div>',
      '</div>'
    ].join('');
  };

  // 渲染颜色选择器
  Class.prototype.renderPicker = function () {
    var that = this;
    var options = that.config;

    // 颜色选择器对象
    var elemPicker = (that.elemPicker = $(
      that.buildColorPickerTemplate(options, that)
    ));

    that.removePicker(options.id); // 若已存在则先移除
    options.target.append(elemPicker);
    options.elem.data(CONST.PICKER_OPENED, true); // 面板已打开的标记

    that.position();
    that.pickerEvents();
    that.onClickOutside();
    that.autoUpdatePosition();
  };

  // 颜色选择器移除
  Class.prototype.removePicker = function (index) {
    var that = this;
    var options = that.config;
    var elem = $('#layui-colorpicker' + (index || that.index));

    that.stopClickOutsideEvent();
    that.stopResizeEvent();

    if (elem[0]) {
      elem.remove();
      options.elem.removeData(CONST.PICKER_OPENED);

      // 面板关闭后的回调
      typeof options.close === 'function' && options.close(that.color);
    }

    return that;
  };

  // 面板定位
  Class.prototype.position = function () {
    var that = this;
    var options = that.config;
    lay.position(that.bindElem || that.elemColorBox[0], that.elemPicker[0], {
      position: options.position,
      align: 'center'
    });
    return that;
  };

  // 颜色选择器赋值
  Class.prototype.val = function () {
    var that = this,
      // , options = that.config

      elemColorBox = that.elemColorBox.find('.' + CONST.PICKER_TRIG_SPAN),
      elemPickerInput = that.elemPicker.find('.' + CONST.PICKER_INPUT),
      e = elemColorBox[0],
      bgcolor = e.style.backgroundColor;

    // 判断是否有背景颜色
    if (bgcolor) {
      // 转化成 hsb 格式
      var hsb = RGBToHSB(RGBSTo(bgcolor));
      var type = elemColorBox.attr('lay-type');

      // 同步滑块的位置及颜色选择器的选择
      that.select(hsb.h, hsb.s, hsb.b);

      // 若格式要求为rgb
      if (type === 'torgb') {
        elemPickerInput.find('input').val(bgcolor);
      } else if (type === 'rgba') {
        // 若格式要求为 rgba
        var rgb = RGBSTo(bgcolor);

        // 若开启透明度而没有设置，则给默认值
        if ((bgcolor.match(/[0-9]{1,3}/g) || []).length === 3) {
          elemPickerInput
            .find('input')
            .val('rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', 1)');
          that.elemPicker
            .find('.' + CONST.PICKER_ALPHA_SLIDER)
            .css('left', 280);
        } else {
          elemPickerInput.find('input').val(bgcolor);
          var left =
            bgcolor.slice(bgcolor.lastIndexOf(',') + 1, bgcolor.length - 1) *
            280;
          that.elemPicker
            .find('.' + CONST.PICKER_ALPHA_SLIDER)
            .css('left', left);
        }

        // 设置 span 背景色
        that.elemPicker.find('.' + CONST.PICKER_ALPHA_BG)[0].style.background =
          'linear-gradient(to right, rgba(' +
          rgb.r +
          ', ' +
          rgb.g +
          ', ' +
          rgb.b +
          ', 0), rgb(' +
          rgb.r +
          ', ' +
          rgb.g +
          ', ' +
          rgb.b +
          '))';
      } else {
        elemPickerInput.find('input').val('#' + HSBToHEX(hsb));
      }
    } else {
      // 若没有背景颜色则默认到最初始的状态
      that.select(0, 100, 100);
      elemPickerInput.find('input').val('');
      that.elemPicker.find('.' + CONST.PICKER_ALPHA_BG)[0].style.background =
        '';
      that.elemPicker.find('.' + CONST.PICKER_ALPHA_SLIDER).css('left', 280);
    }
  };

  // 颜色选择器滑动 / 点击
  Class.prototype.side = function () {
    var that = this,
      options = that.config,
      span = that.elemColorBox.find('.' + CONST.PICKER_TRIG_SPAN),
      type = span.attr('lay-type'),
      side = that.elemPicker.find('.' + CONST.PICKER_SIDE),
      slider = that.elemPicker.find('.' + CONST.PICKER_SIDE_SLIDER),
      basis = that.elemPicker.find('.' + CONST.PICKER_BASIS),
      choose = that.elemPicker.find('.' + CONST.PICKER_BASIS_CUR),
      alphacolor = that.elemPicker.find('.' + CONST.PICKER_ALPHA_BG),
      alphaslider = that.elemPicker.find('.' + CONST.PICKER_ALPHA_SLIDER),
      _h = (slider[0].offsetTop / 180) * 360,
      _b = 100 - (choose[0].offsetTop / 180) * 100,
      _s = (choose[0].offsetLeft / 260) * 100,
      _a = Math.round((alphaslider[0].offsetLeft / 280) * 100) / 100,
      i = that.elemColorBox.find('.' + CONST.PICKER_TRIG_I),
      pre = that.elemPicker.find('.layui-colorpicker-pre').children('div'),
      change = function (x, y, z, a) {
        that.select(x, y, z);
        var rgb = HSBToRGB({ h: x, s: y, b: z });
        var color = HSBToHEX({ h: x, s: y, b: z });
        var elemInput = that.elemPicker
          .find('.' + CONST.PICKER_INPUT)
          .find('input');

        i.addClass(CONST.ICON_PICKER_DOWN).removeClass(CONST.ICON_PICKER_CLOSE);
        span[0].style.background =
          'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')';

        if (type === 'torgb') {
          elemInput.val('rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')');
        } else if (type === 'rgba') {
          var left = a * 280;
          alphaslider.css('left', left);
          elemInput.val(
            'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + a + ')'
          );
          span[0].style.background =
            'rgba(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ', ' + a + ')';
          alphacolor[0].style.background =
            'linear-gradient(to right, rgba(' +
            rgb.r +
            ', ' +
            rgb.g +
            ', ' +
            rgb.b +
            ', 0), rgb(' +
            rgb.r +
            ', ' +
            rgb.g +
            ', ' +
            rgb.b +
            '))';
        } else {
          elemInput.val('#' + color);
        }

        //回调更改的颜色
        options.change &&
          options.change(
            $.trim(
              that.elemPicker
                .find('.' + CONST.PICKER_INPUT)
                .find('input')
                .val()
            )
          );
      },
      //拖拽元素
      elemMove = $(
        '<div class="layui-auxiliar-moving" id="LAY-colorpicker-moving"></div>'
      ),
      createMoveElem = function (call) {
        $('#LAY-colorpicker-moving')[0] || $('body').append(elemMove);
        elemMove.on('mousemove', call);
        elemMove
          .on('mouseup', function () {
            elemMove.remove();
          })
          .on('mouseleave', function () {
            elemMove.remove();
          });
      };
    // 移动端滑动模拟事件中
    // 1. 不触发游标上绑定的事件，以提高性能，使滑动更流畅
    // 2. 游标上的事件需要冒泡到颜色拾取区域，用来模拟拖动游标的效果
    var needTrigger = true;
    var needStopPropagation = true;

    //右侧主色选择
    slider.on('mousedown', function (e, triggerEvent) {
      var oldtop = this.offsetTop;
      var oldy = e.clientY === undefined ? triggerEvent.clientY : e.clientY;
      var move = function (e) {
        var top = oldtop + (e.clientY - oldy),
          maxh = side[0].offsetHeight;
        if (top < 0) top = 0;
        if (top > maxh) top = maxh;
        var h = (top / 180) * 360;
        _h = h;
        change(h, _s, _b, _a);
        e.preventDefault();
      };
      needStopPropagation && layui.stope(e);
      createMoveElem(move);
      e.preventDefault();
    });

    side.on('mousedown', function (e) {
      var top = e.clientY - $(this).offset().top + $win.scrollTop();
      if (top < 0) top = 0;
      if (top > this.offsetHeight) top = this.offsetHeight;
      var h = (top / 180) * 360;
      _h = h;
      change(h, _s, _b, _a);
      e.preventDefault();
      needTrigger && slider.trigger('mousedown', e);
    });

    //中间小圆点颜色选择
    choose.on('mousedown', function (e, triggerEvent) {
      var oldtop = this.offsetTop;
      var oldleft = this.offsetLeft;
      var oldy = e.clientY === undefined ? triggerEvent.clientY : e.clientY;
      var oldx = e.clientX === undefined ? triggerEvent.clientX : e.clientX;
      var move = function (e) {
        var top = oldtop + (e.clientY - oldy),
          left = oldleft + (e.clientX - oldx),
          maxh = basis[0].offsetHeight,
          maxw = basis[0].offsetWidth;
        if (top < 0) top = 0;
        if (top > maxh) top = maxh;
        if (left < 0) left = 0;
        if (left > maxw) left = maxw;
        var s = (left / 260) * 100,
          b = 100 - (top / 180) * 100;
        _b = b;
        _s = s;
        change(_h, s, b, _a);
        e.preventDefault();
      };
      needStopPropagation && layui.stope(e);
      createMoveElem(move);
      e.preventDefault();
    });

    basis.on('mousedown', function (e) {
      var top = e.clientY - $(this).offset().top + $win.scrollTop(),
        left = e.clientX - $(this).offset().left + $win.scrollLeft();
      if (top < 0) top = 0;
      if (top > this.offsetHeight) top = this.offsetHeight;
      if (left < 0) left = 0;
      if (left > this.offsetWidth) left = this.offsetWidth;
      var s = (left / 260) * 100,
        b = 100 - (top / 180) * 100;
      _b = b;
      _s = s;
      change(_h, s, b, _a);
      layui.stope(e);
      e.preventDefault();
      needTrigger && choose.trigger('mousedown', e);
    });

    //底部透明度选择
    alphaslider.on('mousedown', function (e, triggerEvent) {
      var oldleft = this.offsetLeft;
      var oldx = e.clientX === undefined ? triggerEvent.clientX : e.clientX;
      var move = function (e) {
        var left = oldleft + (e.clientX - oldx),
          maxw = alphacolor[0].offsetWidth;
        if (left < 0) left = 0;
        if (left > maxw) left = maxw;
        var a = Math.round((left / 280) * 100) / 100;
        _a = a;
        change(_h, _s, _b, a);
        e.preventDefault();
      };

      needStopPropagation && layui.stope(e);
      createMoveElem(move);
      e.preventDefault();
    });
    alphacolor.on('mousedown', function (e) {
      var left = e.clientX - $(this).offset().left;
      if (left < 0) left = 0;
      if (left > this.offsetWidth) left = this.offsetWidth;
      var a = Math.round((left / 280) * 100) / 100;
      _a = a;
      change(_h, _s, _b, a);
      e.preventDefault();
      needTrigger && alphaslider.trigger('mousedown', e);
    });

    // 预定义颜色选择
    pre.each(function () {
      $(this).on('click', function () {
        $(this)
          .parent('.layui-colorpicker-pre')
          .addClass('selected')
          .siblings()
          .removeClass('selected');
        var color = this.style.backgroundColor,
          hsb = RGBToHSB(RGBSTo(color)),
          a = color.slice(color.lastIndexOf(',') + 1, color.length - 1);
        // var left;
        _h = hsb.h;
        _s = hsb.s;
        _b = hsb.b;
        if ((color.match(/[0-9]{1,3}/g) || []).length === 3) a = 1;
        _a = a;
        // left = a * 280;
        change(hsb.h, hsb.s, hsb.b, a);
      });
    });

    if (!lay.touchEventsSupported()) return;
    // 触摸事件模拟
    layui.each(
      [
        { elem: side, eventType: 'mousedown' },
        { elem: alphacolor, eventType: 'mousedown' },
        { elem: basis, eventType: 'mousedown' }
      ],
      function (i, obj) {
        lay.touchSwipe(obj.elem, {
          onTouchStart: function () {
            needTrigger = false;
            needStopPropagation = false;
          },
          onTouchMove: function (e) {
            touchHandler(e, obj.eventType);
          },
          onTouchEnd: function () {
            elemMove.remove();
            needTrigger = true;
            needStopPropagation = true;
          }
        });
      }
    );

    function touchHandler(event, eventType) {
      var pointer = event.touches[0];
      var simulatedEvent = document.createEvent('MouseEvent');

      simulatedEvent.initMouseEvent(
        eventType,
        true,
        true,
        window,
        1,
        pointer.screenX,
        pointer.screenY,
        pointer.clientX,
        pointer.clientY,
        false,
        false,
        false,
        false,
        0,
        null
      );
      pointer.target.dispatchEvent(simulatedEvent);
    }
  };

  // 颜色选择器hsb转换
  Class.prototype.select = function (h, s, b, type) {
    var that = this;
    // var options = that.config;
    var hex = HSBToHEX({ h: h, s: 100, b: 100 });
    // var color = HSBToHEX({h:h, s:s, b:b});
    var sidetop = (h / 360) * 180;
    var top = 180 - (b / 100) * 180;
    var left = (s / 100) * 260;
    var basisElem = that.elemPicker.find('.' + CONST.PICKER_BASIS)[0];

    that.elemPicker.find('.' + CONST.PICKER_SIDE_SLIDER).css('top', sidetop); //滑块的top
    basisElem.style.background = '#' + hex; //颜色选择器的背景

    //选择器的top left
    that.elemPicker.find('.' + CONST.PICKER_BASIS_CUR).css({
      top: (top / basisElem.offsetHeight) * 100 + '%',
      left: (left / basisElem.offsetWidth) * 100 + '%'
    });

    // if(type === 'change') return;

    // 选中的颜色
    // that.elemPicker.find('.' + CONST.PICKER_INPUT).find('input').val('#'+ color);
  };

  Class.prototype.pickerEvents = function () {
    var that = this;
    var options = that.config;

    var elemColorBoxSpan = that.elemColorBox.find('.' + CONST.PICKER_TRIG_SPAN); //颜色盒子
    var elemPickerInput = that.elemPicker.find(
      '.' + CONST.PICKER_INPUT + ' input'
    ); //颜色选择器表单

    var pickerEvents = {
      // 清空
      clear: function (othis) {
        elemColorBoxSpan[0].style.background = '';
        that.elemColorBox
          .find('.' + CONST.PICKER_TRIG_I)
          .removeClass(CONST.ICON_PICKER_DOWN)
          .addClass(CONST.ICON_PICKER_CLOSE);
        that.color = '';

        options.done && options.done('');
        that.removePicker();
      },

      //确认
      confirm: function (othis, change) {
        var value = $.trim(elemPickerInput.val()),
          colorValue,
          hsb;

        if (value.indexOf(',') > -1) {
          hsb = RGBToHSB(RGBSTo(value));
          that.select(hsb.h, hsb.s, hsb.b);
          elemColorBoxSpan[0].style.background = colorValue =
            '#' + HSBToHEX(hsb);

          if (
            (value.match(/[0-9]{1,3}/g) || []).length > 3 &&
            elemColorBoxSpan.attr('lay-type') === 'rgba'
          ) {
            var left =
              value.slice(value.lastIndexOf(',') + 1, value.length - 1) * 280;
            that.elemPicker
              .find('.' + CONST.PICKER_ALPHA_SLIDER)
              .css('left', left);
            elemColorBoxSpan[0].style.background = value;
            colorValue = value;
          }
        } else {
          hsb = HEXToHSB(value);
          elemColorBoxSpan[0].style.background = colorValue =
            '#' + HSBToHEX(hsb);
          that.elemColorBox
            .find('.' + CONST.PICKER_TRIG_I)
            .removeClass(CONST.ICON_PICKER_CLOSE)
            .addClass(CONST.ICON_PICKER_DOWN);
        }

        if (change === 'change') {
          that.select(hsb.h, hsb.s, hsb.b, change);
          options.change && options.change(colorValue);
          return;
        }
        that.color = value;

        options.done && options.done(value);
        that.removePicker();
      }
    };

    // 选择器面板点击事件
    that.elemPicker.on('click', '*[colorpicker-events]', function () {
      var othis = $(this),
        attrEvent = othis.attr('colorpicker-events');
      pickerEvents[attrEvent] && pickerEvents[attrEvent].call(this, othis);
    });

    // 输入框事件
    elemPickerInput.on('keyup', function (e) {
      var othis = $(this);
      pickerEvents.confirm.call(
        this,
        othis,
        e.keyCode === 13 ? null : 'change'
      );
    });
  };

  // 事件
  Class.prototype.events = function () {
    var that = this;
    var options = that.config;

    // 弹出颜色选择器
    that.elemColorBox.on('click', function () {
      // 主面板是否已打开
      var opened = options.elem.data(CONST.PICKER_OPENED);

      // 根据主面板状态，自动切换打开与关闭
      if (opened) {
        that.removePicker();
      } else {
        that.renderPicker();
        that.val();
        that.side();
      }
    });
  };

  /**
   * 点击面板外部时的事件
   */
  Class.prototype.onClickOutside = function () {
    var that = this;
    var options = that.config;

    that.stopClickOutsideEvent();

    var stop = lay.onClickOutside(
      that.elemPicker[0],
      function (e) {
        var elemColorBoxSpan = that.elemColorBox.find(
          '.' + CONST.PICKER_TRIG_SPAN
        );

        if (that.color) {
          var hsb = RGBToHSB(RGBSTo(that.color));
          that.select(hsb.h, hsb.s, hsb.b);
        } else {
          that.elemColorBox
            .find('.' + CONST.PICKER_TRIG_I)
            .removeClass(CONST.ICON_PICKER_DOWN)
            .addClass(CONST.ICON_PICKER_CLOSE);
        }

        elemColorBoxSpan[0].style.background = that.color || '';

        // 取消选择的回调
        typeof options.cancel === 'function' && options.cancel(that.color);

        // 移除面板
        that.removePicker();
      },
      {
        ignore: [options.elem[0]],
        event: clickOrMousedown,
        capture: false
      }
    );

    that.stopClickOutsideEvent = function () {
      stop();
      that.stopClickOutsideEvent = $.noop;
    };
  };

  /**
   * 窗口大小变化时自动更新位置
   */
  Class.prototype.autoUpdatePosition = function () {
    var that = this;
    // var options = that.config;
    var RESIZE_EVENT_NAME = 'resize.lay_colorpicker_resize';

    that.stopResizeEvent();

    var windowResizeHandler = function () {
      that.position();
    };

    $win.on(RESIZE_EVENT_NAME, windowResizeHandler);

    that.stopResizeEvent = function () {
      $win.off(RESIZE_EVENT_NAME, windowResizeHandler);
      that.stopResizeEvent = $.noop;
    };
  };

  exports(CONST.MOD_NAME, component);
});
