基於jQuery的email suggest插件

  最近項目中有表單提交的地方須要用戶填寫郵箱,PM(產品經理)和運營都強烈要求在用戶填寫郵箱的時候出現suggest列表,簡化用戶輸入的填寫流程。我考慮了下,這個應該也是常常會用到的功能,細心的朋友可能會發現好多登陸或者其餘有表單提交的地方,好比搜狐白社會登陸,個人搜狐登陸等等都有這個功能,因此爲了方便之後使用,索性寫一個jQuery插件出來好了。css

  這裏不對具體代碼作詳解,只講述實現思路和流程。首先有一份默認配置defaultshtml

 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列表內容,若是用戶使用插件時候沒有傳遞參數就會使用默認配置jquery

插件內部有一個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     }

當建立實例時候會執行初始化函數,初始化函數調用了事件綁定方法app

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

事件綁定方法對input元素進行了keyup blur事件的綁定,分別在用戶輸入內容時候進行suggest更新和blur時候關閉suggest提示dom

 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處理會點擊不到要選擇的元素ide

  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: ' + 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方法,實現邏輯很好理解this

 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這些按鍵處理spa

 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地址和源碼

相關文章
相關標籤/搜索