• 基于jQuery的email suggest插件


      最近项目中有表单提交的地方需要用户填写邮箱,PM(产品经理)和运营都强烈要求在用户填写邮箱的时候出现suggest列表,简化用户输入的填写流程。我考虑了下,这个应该也是经常会用到的功能,细心的朋友可能会发现好多登录或者其他有表单提交的地方,比如搜狐白社会登录,我的搜狐登录等等都有这个功能,所以为了方便以后使用,索性写一个jQuery插件出来好了。

      这里不对具体代码做详解,只讲述实现思路和流程。首先有一份默认配置defaults

     1 // 默认参数配置
     2         defaults = {
     3             sugClass: 'ema-sug',
     4             domains: [
     5                 'sohu.com',
     6                 '163.com',
     7                 '126.com',
     8                 '139.com',
     9                 'sina.com',
    10                 'qq.com',
    11                 'gmail.com'
    12             ]
    13         }

    sugClass是用户为suggest添加样式和作为插件内容js钩子使用的,domains是suggest列表内容,如果用户使用插件时候没有传递参数就会使用默认配置

    插件内部有一个EmailSug构造函数,每次调用插件时候都会新创建一个EmailSug的实例,每个实例有自己的属性和配置

     1 function EmailSug(elem, options) {
     2         this.$field = $(elem); 
     3         this.options = $.extend(true, {}, defaults, options);
     4         this._defaults = defaults;
     5         this._domains = this.options.domains;
     6         // 当前选中元素下标
     7         this.selectedIndex = 0;
     8 
     9         this.init();
    10     }

    当创建实例时候会执行初始化函数,初始化函数调用了事件绑定方法

    init: function() {
        this.addEvent();      
    }

    事件绑定方法对input元素进行了keyup blur事件的绑定,分别在用户输入内容时候进行suggest更新和blur时候关闭suggest提示

     1 addEvent: function() {
     2             var 
     3                 // 当前上下文
     4                 that = this,
     5 
     6                 // 
     7                 value;
     8 
     9             this.$field.on('keyup.ema', function(e) {
    10                 value = $.trim(this.value);
    11 
    12                 if (value) {
    13                     that.create(this, value);
    14 
    15                     that.doSelect(e.keyCode);
    16                 } else {
    17                     that.hide();
    18                 }
    19             }).on('blur.ema', function() {
    20                 setTimeout(function() {
    21                     that.hide(); 
    22                 }, 200);
    23             });
    24         }

    blur事件处理必须要使用setTimeout处理下,因为在用户通过鼠标点击suggest的某一个元素时候会触发input的blur事件,如果不做setTimeout处理会点击不到要选择的元素

      1 create: function(elem, value) {
      2             var 
      3                 // 
      4                 that = this,
      5 
      6                 arr,
      7 
      8                 len,
      9 
     10                 // 
     11                 fragment,
     12 
     13                 //  
     14                 ul = [],
     15                 
     16                 // 
     17                 offset,
     18 
     19                 left,
     20                 
     21                 top,
     22                 
     23                 width,
     24 
     25                 height,
     26 
     27                 style,
     28                 
     29                 // 左右边框 
     30                 borderWidth = 2;
     31 
     32             elem = $(elem);
     33             offset = elem.offset();
     34 
     35             width = elem.outerWidth(true) - borderWidth;
     36             height = elem.outerHeight(true);
     37             left = offset.left; 
     38             top = offset.top + height;
     39             style = 'left: ' + left + 'px; top: ' + top + 'px;  ' + width + 'px; border: 1px solid #e2e2e2; border-top: 0; display: none';
     40 
     41             // 
     42             fragment = $('<div class="' + this.options.sugClass + '-wrapper" style="' + style + '" />');
     43             ul.push('<ul class="' + this.options.sugClass + '-list">');
     44 
     45             arr = this.filter(value, this._domains);
     46             len = arr.length;
     47             $.each(arr, function(i, domain) {
     48                 var 
     49                     //  
     50                     _class = that.options.sugClass + '-item';
     51 
     52                 if (that.selectedIndex > len - 1) {
     53                     if (i === 0) {
     54                         _class += ' active';
     55 
     56                         that.selectedIndex = 0;
     57                     }
     58                 } else {
     59                     if (i === that.selectedIndex) {
     60                         _class += ' active';
     61                     } 
     62                 } 
     63 
     64                 ul.push('<li class="' + _class + '" data-index="' + i + '">' + value.replace(/@.*/, '') + '@' + domain  + '</li>'); 
     65             });
     66 
     67             ul.push('</ul>');
     68             ul = ul.join('');
     69 
     70             if (this.$suggest) {
     71                 this.$suggest.empty();
     72                 this.$suggest.append(ul);
     73             } else {
     74                 fragment.append(ul);
     75 
     76                 // 显示到页面
     77                 $('body').append(fragment);
     78                 this.$suggest = fragment;
     79 
     80                 /// 
     81                 this.$suggest.on('mouseenter click', '.' + this.options.sugClass + '-item', function(e) {
     82                     var lis,
     83                     
     84                         li;
     85 
     86                     li = $(this);
     87                     lis = li.parent().children();
     88 
     89                     if (e.type === 'mouseenter') {
     90                         li.addClass('active').siblings().removeClass('active');   
     91 
     92                         that.selectedIndex = $.inArray(this, lis);
     93                     } else {
     94                         // 当前选中
     95                         that.$field.val(lis.eq(that.selectedIndex).text());
     96 
     97                         // 隐藏email sug
     98                         that.hide();
     99                     }
    100                 });
    101             }
    102 
    103             // 
    104             this.show();
    105         }

    create方法调用了filter方法根据用户输入的内容对配置参数domains进行过滤筛选,返回跟用户输入匹配的数组,然后创建suggest列表并选中某一个元素,根据input元素的位置对suggest进行定位,最后渲染到页面并显示。每个实例只会创建一个suggest元素,每次根据用户输入的内容更新列表

     1 // 
     2         filter: function(value, arr) {
     3             var 
     4                 // 
     5                 start,
     6             
     7                 suffix,
     8                 
     9                 r = [];
    10 
    11             start = value.indexOf('@');
    12             if (start > -1) {
    13                 suffix = value.substring(start + 1);
    14 
    15                 $.each(arr, function(i, str) {
    16                     if (str.indexOf(suffix) > -1) {
    17                         r.push(str); 
    18                     }
    19                 });
    20             } else {
    21                 r = arr;
    22             }
    23 
    24             return r;
    25         }

    filter方法,实现逻辑很好理解

     1 doSelect: function(keyCode) {
     2             var 
     3                 //
     4                 elems = $('.' + this.options.sugClass + '-item', this.$suggest),
     5 
     6                 //  
     7                 min = 0,
     8 
     9                 // 
    10                 max = elems.length - 1; 
    11                 
    12             switch (keyCode) {
    13                 case 13:
    14                     // 回车选中当前已选项
    15                     $('li.active', this.$suggest).trigger('click');
    16 
    17                     // 下标重置
    18                     this.selectedIndex = 0;
    19 
    20                     break;
    21                     // 向上
    22                 case 38:
    23                     this.selectedIndex --;
    24 
    25                     if (this.selectedIndex < min) {
    26                         this.selectedIndex = max;
    27                     } 
    28 
    29                     elems.removeClass('active').eq(this.selectedIndex).addClass('active'); 
    30                     break;
    31                     // 向下 
    32                 case 40:
    33                     this.selectedIndex ++;
    34 
    35                     if (this.selectedIndex > max) {
    36                         this.selectedIndex = min;
    37                     }
    38 
    39                     elems.removeClass('active').eq(this.selectedIndex).addClass('active'); 
    40                     break;
    41                 default:
    42                     break;
    43             }       
    44         }

    doSelect方法用户处理用户的键盘操作,Up Down Enter Esc这些按键处理

     1 show: function() {
     2             if (this.$suggest) {
     3                 this.$suggest.show(); 
     4             }
     5         }
     6 
     7 hide: function() {
     8             if (this.$suggest) {
     9                 this.$suggest.hide(); 
    10             }
    11         }

    show和hide方法就是简单的最suggest进行显示和隐藏操作

    实现很简单吧,源码不超过300行。可能实现有不合理或者不完善的地方欢迎指正~

    最后附上demo地址和源码

  • 相关阅读:
    多线程与线程池
    hdu1506 Largest Rectangle in a Histogram
    安装mathtype出问题卸载后 office2016打开mathtype弹错误窗口
    最小总代价 状压DP
    Sumsets 递推
    不容易系列之(4)——考新郎 递推
    超级楼梯 递推
    阿牛的EOF牛肉串(递推)
    子串查询(二维前缀数组) 2018"百度之星"程序设计大赛
    cf#513 B. Maximum Sum of Digits
  • 原文地址:https://www.cnblogs.com/typeof/p/4673445.html
Copyright © 2020-2023  润新知