最近项目中有表单提交的地方需要用户填写邮箱,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. [Linux-脚本]排序、统计、合并命令

    1.排序命令 - sort: sort可以帮我们进行排序,排序顺序按照LANG(语系环境变量)确定.据观察,sort排序以行为单位进行.排序以第一个不相同的字符决定先后顺序(只与第一个不相同的字符相关 ...

  2. 在VBA中调用excel函数

    以前不太会用VBA时,都是在excel中使用函数来计算一些数据.毕竟函数不如代码,效率比较低.所以,就学着怎么在VBA中引用Excel函数.平时我用得比较多的函数就是countif和sumif函数.1 ...

  3. python3下载远程代码并执行

    第一步: 先在gist之类的网站上贴上代码,目的不是高亮,而可以raw的形式获取代码,这样可以省掉处理html的时间,我这里用的是pasteraw: 远程上的代码:http://cdn.pastera ...

  4. window上利用pip安装pandas

    官网推荐的是直接使用Anoconda,它集成了pandas,可以直接使用.安装挺简单的,有windows下的安装包.如果不想安装庞大的Anoconda,那就一步一步用pip来安装pandas.下面我主 ...

  5. 一些Layout的坑。坑死我自己了

    iOS这个东西,初学感觉,还好还好,然后一年之后再来修复一下初学的时候的代码,我只是感觉头很晕- - 别扶我. AutoLayout的坑,明明以前都没有的!!!升了iOS10就突然发现了这个坑,其实也 ...

  6. 第五章 搭建S3C6410开发板的测试环境

    在PC上可以开发Linux驱动,重新编译成ARM架构的Linux驱动模块,但最后还是要在开发板上进行测试.目前最流行的是基于三星S3C6410 ARM11架构的开发板,很多厂商在其基础上进行了扩展,开 ...

  7. Spark源码学习1.7——Master.scala

    master第一步是加载系统定义的环境变量,如worker的超时时间.系统保留的Application数目等:第二步,加载worker的信 息,地址.id等:第三步,加载Application的信息, ...

  8. 操作各个版本的excel的链接写法

    有很有意思的网站:https://connectionstrings.com/ace-oledb-12-0/  很详细得介绍了各种写法 这里主要提两个: string strCon = @" ...

  9. Xml 序列化

    1 XML序列化只能序列化对象的公有属性,并且要求对象有一个无参的构造方法,否者无法反序列化. 2 [Serializable]和[NonSerialized]特性对XML序列化无效!所以使用XML序 ...

  10. 刚写完的商城erp + 这个商城前台,新鲜出炉。自己1个人写, 包括php框架和前端html页面.

    刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面. 刚写完的商城erp + 这个商城前台,新鲜出炉.自己1个人写, 包括php框架和前端html页面.