最近項目中有表單提交的地方須要用戶填寫郵箱,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地址和源碼