zoukankan      html  css  js  c++  java
  • 基于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地址和源码

  • 相关阅读:
    PAT (Advanced Level) 1060. Are They Equal (25)
    PAT (Advanced Level) 1059. Prime Factors (25)
    PAT (Advanced Level) 1058. A+B in Hogwarts (20)
    PAT (Advanced Level) 1057. Stack (30)
    PAT (Advanced Level) 1056. Mice and Rice (25)
    PAT (Advanced Level) 1055. The World's Richest (25)
    PAT (Advanced Level) 1054. The Dominant Color (20)
    PAT (Advanced Level) 1053. Path of Equal Weight (30)
    PAT (Advanced Level) 1052. Linked List Sorting (25)
    PAT (Advanced Level) 1051. Pop Sequence (25)
  • 原文地址:https://www.cnblogs.com/typeof/p/4673445.html
Copyright © 2011-2022 走看看