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

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

 // 默认参数配置
defaults = {
sugClass: 'ema-sug',
domains: [
'sohu.com',
'163.com',
'126.com',
'139.com',
'sina.com',
'qq.com',
'gmail.com'
]
}

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

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

 function EmailSug(elem, options) {
this.$field = $(elem);
this.options = $.extend(true, {}, defaults, options);
this._defaults = defaults;
this._domains = this.options.domains;
// 当前选中元素下标
this.selectedIndex = 0; this.init();
}

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

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

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

 addEvent: function() {
var
// 当前上下文
that = this, //
value; this.$field.on('keyup.ema', function(e) {
value = $.trim(this.value); if (value) {
that.create(this, value); that.doSelect(e.keyCode);
} else {
that.hide();
}
}).on('blur.ema', function() {
setTimeout(function() {
that.hide();
}, 200);
});
}

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

 create: function(elem, value) {
var
//
that = this, arr, len, //
fragment, //
ul = [], //
offset, left, top, width, height, style, // 左右边框
borderWidth = 2; elem = $(elem);
offset = elem.offset(); width = elem.outerWidth(true) - borderWidth;
height = elem.outerHeight(true);
left = offset.left;
top = offset.top + height;
style = 'left: ' + left + 'px; top: ' + top + 'px; width: ' + width + 'px; border: 1px solid #e2e2e2; border-top: 0; display: none'; //
fragment = $('<div class="' + this.options.sugClass + '-wrapper" style="' + style + '" />');
ul.push('<ul class="' + this.options.sugClass + '-list">'); arr = this.filter(value, this._domains);
len = arr.length;
$.each(arr, function(i, domain) {
var
//
_class = that.options.sugClass + '-item'; if (that.selectedIndex > len - 1) {
if (i === 0) {
_class += ' active'; that.selectedIndex = 0;
}
} else {
if (i === that.selectedIndex) {
_class += ' active';
}
} ul.push('<li class="' + _class + '" data-index="' + i + '">' + value.replace(/@.*/, '') + '@' + domain + '</li>');
}); ul.push('</ul>');
ul = ul.join(''); if (this.$suggest) {
this.$suggest.empty();
this.$suggest.append(ul);
} else {
fragment.append(ul); // 显示到页面
$('body').append(fragment);
this.$suggest = fragment; ///
this.$suggest.on('mouseenter click', '.' + this.options.sugClass + '-item', function(e) {
var lis, li; li = $(this);
lis = li.parent().children(); if (e.type === 'mouseenter') {
li.addClass('active').siblings().removeClass('active'); that.selectedIndex = $.inArray(this, lis);
} else {
// 当前选中
that.$field.val(lis.eq(that.selectedIndex).text()); // 隐藏email sug
that.hide();
}
});
} //
this.show();
}

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

 //
filter: function(value, arr) {
var
//
start, suffix, r = []; start = value.indexOf('@');
if (start > -1) {
suffix = value.substring(start + 1); $.each(arr, function(i, str) {
if (str.indexOf(suffix) > -1) {
r.push(str);
}
});
} else {
r = arr;
} return r;
}

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

 doSelect: function(keyCode) {
var
//
elems = $('.' + this.options.sugClass + '-item', this.$suggest), //
min = 0, //
max = elems.length - 1; switch (keyCode) {
case 13:
// 回车选中当前已选项
$('li.active', this.$suggest).trigger('click'); // 下标重置
this.selectedIndex = 0; break;
// 向上
case 38:
this.selectedIndex --; if (this.selectedIndex < min) {
this.selectedIndex = max;
} elems.removeClass('active').eq(this.selectedIndex).addClass('active');
break;
// 向下
case 40:
this.selectedIndex ++; if (this.selectedIndex > max) {
this.selectedIndex = min;
} elems.removeClass('active').eq(this.selectedIndex).addClass('active');
break;
default:
break;
}
}

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

 show: function() {
if (this.$suggest) {
this.$suggest.show();
}
} hide: function() {
if (this.$suggest) {
this.$suggest.hide();
}
}

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

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

最后附上demo地址和源码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>jQuery插件email suggest - demo</title>
<link href="https://files.cnblogs.com/files/typeof/base.css" rel=stylesheet type=text/css >
<style type="text/css">
.page {
padding: 20px 10px;
}

.page .email {
width: 350px;
height: 30px;
line-height: 30px;
border: 1px solid #e2e2e2;
padding-left: 10px;
font-size: 14px;
}

.ema-sug-wrapper {
position: absolute;
background: #fff;
text-align: left;
}

.ema-sug-wrapper .ema-sug-list .ema-sug-item {
font-size: 14px;
height: 25px;
line-height: 25px;
padding-left: 10px;
color: #333;
}

.ema-sug-wrapper .ema-sug-list .ema-sug-item.active {
background: #ff4800;
cursor: pointer;
color: #fff;
}

</style>
<script src="https://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"> </script>
<script src="https://files.cnblogs.com/files/typeof/email-sug.js"> </script>
</head>
<body>
<div class="page">
<input type="text" class="email" />
</div>
<script>
$('.email').emailSug({
sugClass: 'ema-sug',
domains: [
'sohu.com',
'sogou.com',
'163.com',
'126.com',
'139.com',
'sina.com',
'qq.com',
'gmail.com'
]
});
</script>
</body>
</html>

基于jQuery的email suggest插件的更多相关文章

  1. 10 个基于 jQuery 的 Web 交互插件推荐

    英文原文:10 jQuery for Web Interaction Plugins “用户交互”在现代的 Web 设计中占据了很大比例,这是互联网产品不可或缺的关键,对 Web 设计师也提出了更高的 ...

  2. 源码来袭!!!基于jquery的ajax分页插件(demo+源码)

    前几天打开自己的博客园主页,无意间发现自己的园龄竟然有4年之久了.可是看自己的博客列表却是空空如也,其实之前也有写过,但是一直没发布(然而好像并没有什么卵用).刚开始学习编程时就接触到博客园,且在博客 ...

  3. 出位的template.js 基于jquery的模板渲染插件

    找了好几款基于jquery的模板渲染插件,无一感觉很难用(教程较少.绑定不统一),也可能我智商问题,比如jquery template.js .jtemplate.js. 然后在github上找到这一 ...

  4. 基于jquery的城市选择插件

    城市选择插件的难度不是很大,主要是对dom节点的操作.而我写的这个插件相对功能比较简答,没有加入省市联动. 上代码好了,参照代码的注释应该比较好理解. /* *基于jquery的城市选择插件 *aut ...

  5. 基于jQuery全屏相册插件zoomVisualizer

    基于jQuery全屏相册插件zoomVisualizer.这是一款基于jquery ui实现的相册插件,支持隐藏显示相册缩略图,支持左右箭头切换图片,支持放大缩及缩小图片.效果图如下: 在线预览    ...

  6. 基于jQuery的数字键盘插件

    有时,我们需要在网页上使用软键盘.今天,就给大家带来一个基于jQuery的数字键盘插件,除了jQuery,不需要依赖任何文件资源.纯数字键盘,有退格,有清除,不支持输入小数(需要的可以自己改一下,主要 ...

  7. 一款基于jQuery的QQ表情插件

    我们在QQ聊天或者发表评论.微博时,会有一个允许加入表情的功能,点击表情按钮,会弹出一系列表情小图片,选中某个表情图片即可发表的丰富的含表情的内容.今天和大家分享一款基于jQuery的QQ表情插件,您 ...

  8. 基于jQuery开发的手风琴插件 jquery.accordion.js

     1.插件代码 少说多做,基于jQuery的手风琴插件jquery.accordion.js的代码:  /* * 手风琴插件说明: * 1.treeTrunk对应树干 * 2.treeLeaf对应树叶 ...

  9. 10 款基于 jQuery 的切换效果插件推荐

    本文整理了 10 款非常好用的 jQuery 切换效果插件,包括平滑切换和重叠动画等,这些插件可以实现不同元素之间的动态切换. 1. InnerFade 这是一个基于 jQuery 的小插件,可以实现 ...

随机推荐

  1. Ubuntu下freeradius的EAP-MD5,PEAPv0/EAP-MSCHAPv2,EAP-TTLS/MD5,EAP-TTLS/MSCHAPv2方式认证(基于mysql)

    基于freeradius+mysql,今天验证下freeradius的EAP认证:1.EAP-MD5:2.EAP-PEAP 一.EAP-MD5方式认证 1.修改配置文件 (1)/usr/local/e ...

  2. Enterprise Architect 学习 之 用例图

    用例模型 用例模型用来记录系统的需求,它提供系统与用户及其他参与者的一种通信手段. 执行者 用例图显示了系统和系统外实体之间的交互.这些实体被引用为执行者.执行者代表角色,可以包括:用户,外部硬件和其 ...

  3. js 布尔值作为开关判断

    var flag = true; $("#more_info").click(function() { if( flag ){ $("#more_xl_more" ...

  4. 使用vs2010创建MFC C++ Ribbon程序

    Your First MFC C++ Ribbon Application with Visual Studio 2010 Earlier this month, I put together my ...

  5. MySQL数据库9 - 日期与时间函数

    一 日期和时间函数 函数的概念:按指定格式输入参数,返回正确结果的运算单元 1. 返回当前日期:curdate() current_date() current_date()+0可以将当前日期转换为数 ...

  6. C++关于Condition Variable

    #include <condition_variable> #include <mutex> #include <future> #include <iost ...

  7. 【转】C#多线程示例

    using System; using System.Threading; namespace ConsoleThread { class ThreadApp { static int interva ...

  8. Java输入一行数据并转存到数组中

    直接看下面的代码吧!主要是split和foreach的使用 import java.io.*; import java.util.*; public class Main{ public static ...

  9. SqlServer性能优化索引(五)

    导入表结构: select * into ProductCategory from AdventureWorksDW2014.dbo.DimProductCategory select * into ...

  10. dom扩展

    第十一章 DOM扩展 一.选择符API 1.querySelector()方法             接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null. 2. ...