最近项目中有表单提交的地方需要用户填写邮箱,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. Javascript生成随机数

    随机数在前后端都比较常用,用途也较广.这里记录一下前端的实现方法,代码比较简单,封装成函数可随时调用. 具体如下: function getRandNum(n){ return Math.floor( ...

  2. Dapper学习笔记(5)-存储过程

    一.无参存储过程 第一步:创建一个不带参数的存储过程,代码如下: CREATE PROCEDURE [dbo].[QueryRoleNoParms] AS BEGIN SELECT * FROM T_ ...

  3. HTML 5 <script> 标签

    HTML 4.01 与 HTML 5 之间的差异 async 属性是 HTML 5 中的新属性. 在 HTML 5 中,不再支持 HTML 4.01 中的一些属性. 提示和注释 注释:脚本按照如下方式 ...

  4. Servlet入门

    1.在tomcat中新建一个day01web应用,然后在web应用中新建一个web-inf/classes目录:2.在classes目录中新建一个FirstServlet.java文件:package ...

  5. 关于JavaScript和html的随笔

    最近听了一些关于JavaScript和html的讲课和读了一些书籍.因为我是给项目做网站知道的,所以要特别的注意和努力.JavaScript是一门挺好用的脚本语言,比较简单灵活,在这上面我深有体会,因 ...

  6. 学习Find函数和select

    Find函数其实就类似于在excel按下Ctrl+F出现的查找功能:在某个区域中查找你要找的字符,一旦找到就定位到第一个对应的单元格.所以Find函数的返回值是个单元格,也就是个range值.举例,s ...

  7. 使用JPype实现Python调用JAVA程序

    ''' Created on 2016年6月1日 @author: cero ''' import jpype jvmPath = jpype.getDefaultJVMPath() ext_clas ...

  8. 初学My Batis之入门

    MyBatis(百度百科): 下面我们来做第一个入门案例: 架构: jar包: 我们创建一个学生实体类 package cn.entity; /** * 学生实体类 * @author hyj * * ...

  9. linux 安装一些命令

    一.安装wget命令: debian 或者 ubuntu : sudo apt-get install wget centos : sudo yum -y install wget 二.安装rz.sz ...

  10. 聊一聊jquery文件上传(支持多文件上传)

    谈到文件上传,现在一般都用现成的组件可以使用.PC端的可以使用uploadify.针对微网站H5也有uploadifive.但是这组件并不能满足各种场景的需求,例如:预览 切图 放大缩小,取消之类的. ...