先来个基础的

需求

根据下面需求实现如示意图所示的邮箱输入提示功能,注意,根据要求只需实现下面功能

  • 当用户没有任何输入时,提示框消失
  • 当用户输入字符后,显示提示框,并且把用户输入的内容自动拼上邮箱后缀进行显示
  • 暂时不用考虑示意图中的红色和蓝色背景色的逻辑
  • 注意用户输入中前后空格需要去除

小优化编码

需求

如果我们输入的是 abc@1,这个时候出现的提示框内容是

  • abc@1@163.com
  • abc@1@gmail.com
  • abc@1@126.com
    ……

很明显,上面的提示框不是一个符合用户需求的提示,我们需要做一些优化:

    • 当用户输入含有 @ 符号时,我们选取用户输入的@前面的字符来和后缀拼接

需求

这下出现的提示好多了,不过用户如果已经输入了@1,说明他大概率要输入163或者126,我们需要让我们的提示更加符合用户的期望。满足以下需求:

  • 当用户输入了 @ 及部分后缀时,只从 postfixList 选取符合用户输入预期的后缀,我们以前缀匹配为要求。
  • 当用户输入不满足任何前缀匹配时,则显示全部提示

测试用例

  • 输入a@1->出现提示框,提示a@163.com, a@126.com
  • 输入a@g->出现提示框,提示a@gmail.com
  • 输入a@2->出现提示框,提示a@263.net
  • 输入a@qq->出现提示框,提示a@qq.com
  • 输入a@163.->出现提示框,提示a@163.com
  • 输入a@126.com->出现提示框,提示a@126.com
  • 输入a@qq.com (两个空格)->出现提示框,提示a@qq.com
  • 输入a@qq.comm->出现提示框,出现全部提示

代码1

 <!DOCTYPE html>
<html> <head>
<meta charset="utf-8" />
<title>邮箱后缀提示1-完成基本提示</title> </head> <body>
<div class="wrapper">
<input type="text" id="input-email">
<ul class="email-sug" id="email-sug-wrapper"> </ul>
</div>
<script>
var postfixList = ["163.com", "gmail.com", "126.com", "qq.com", "263.net"];
var txt = document.getElementById("input-email");
var sug = document.getElementById("email-sug-wrapper"); // keys.addEventListener("keyup",function(){
// console.log("event handle1");
// })
// keys.addEventListener("keypress",function(){
// console.log("event handle2");
// })
// keys.addEventListener("keydown",function(){
// console.log("event handle3");
// })
// keys.addEventListener("input",function(){
// console.log("event handle4");
// }) //经过查看各个效果,oninput效果最符合需求。
txt.oninput = function () {
console.log("event handle4");
judge();
add(); }
function getText() {
var inputText = txt.value.trim();
return inputText;
}
//判断是否生成新的数组
function postlist() {
var userinput = getText();
var newpostlist = new Array();
if (userinput.search('@') != 0) {
var len = userinput.search('@');
//用来拼接的用户输入内容 = 只使用@之后的字符串
var x = userinput.substring(len + 1, userinput.length); //取@之后的部分
for (var i = 0; i < postfixList.length; i++) {
if (postfixList[i].search(x) == 0) {
newpostlist.push(postfixList[i]);
}
}
//若@后面没有字符或者新数组newpostlist为空,就返回原来的postfixlist
if (x === '' || newpostlist == '') {
return postfixList;
}
return newpostlist;
} else {
return postfixList;
}
}
//根据输入内容和匹配来生成提示数组
function promptContent() {
var x = getText();
var tips = new Array();
if (x.indexOf("@") != -1) {
var p = x.slice(0, x.indexOf("@"));
for (i = 0; i < postlist().length; i++) {
tips[i] = p + "@" + postlist()[i];
}
} else {
for (i = 0; i < postfixList.length; i++) {
tips[i] = x + "@" + postfixList[i];
}
}
return tips;
}
//添加提示数组进入li
function add() {
var sug = document.getElementById("email-sug-wrapper");
var tips = promptContent();
while (sug.hasChildNodes()) {
sug.removeChild(sug.firstChild);
}
//将之前的列表清除掉,然后重新生成新的列表
for (i = 0; i < tips.length; i++) {
var tip_li = document.createElement("li");
tip_li.innerHTML = tips[i];
sug.appendChild(tip_li);
}
} function judge() {
//判空,是“”没有内容,不能为“ ”
if (getText() == "") {
hide();
} else {
display();
} } function hide() {
sug.style.display = "none";
} function display() {
sug.style.display = "block";
}
</script>
</body> </html>

新的需求编码

需求

上面我们只完成了提示,但提示还没有直接作用到选择中,我们现在完成以下需求:

  • 使用CSS实现:鼠标滑过提示框的某一个提示时,这个提示内容背景色变化,表示鼠标经过了这个DOM节点
  • 鼠标如果点击某个提示,则提示内容进入输入框,同时提示框消失
  • 在上个步骤结束后,在输入框中任意再输入字符或删除字符,则重新开始出现提示框

需求

尝试在输入框中输入<b>,看看提示框发生了什么

阅读

设计

我们需要在两个地方进行处理,一个是在生成提示内容那里,对于特殊字符进行转义编码,另一个是在把鼠标点击的提示框内容转回输入框时进行解码。

代码2

<!DOCTYPE html>
<html> <head>
<meta charset="utf-8" />
<title>邮箱后缀提示2-添加样式和监听鼠标点击和转码内容</title>
<style>
#input-email{
width: 300px;
height: 30px;
}
.email-sug{
width: 300px;
list-style: none;
padding: 0px;
margin: 0px;
border: 2px solid rgba(134, 132, 132,0.3);
border-top:none;
display: none;
/* 初始不显示,避免边框出现 */
}
.email-sug li{
width: 300px;
height: 30px;
background-color: #ffffff;
color: darkgrey;
line-height: 30px;
}
.email-sug li:hover{
background-color:pink;
}
</style>
</head> <body>
<div class="wrapper">
<input type="text" id="input-email">
<ul class="email-sug" id="email-sug-wrapper"> </ul>
</div>
<script>
var postfixList = ["163.com", "gmail.com", "126.com", "qq.com", "263.net"];
var txt = document.getElementById("input-email");
var sug = document.getElementById("email-sug-wrapper");
sug.addEventListener("click",function(ev){
//采用事件代理,监听父级点击事件,通过target获取当前li
var ev=ev||window.event;
var target=ev.target||ev.srcElement;
if(target.nodeName.toLowerCase()=="li"){
hide();
return txt.value=htmlDecode( target.innerHTML); //解码
//return txt.value= target.innerHTML;
} })
txt.oninput = function () {
console.log("event handle4");
judge();
add(); } function getText() {
var inputText = txt.value.trim();
return inputText;
}
//判断是否生成新的数组
function postlist() {
var userinput = getText();
var newpostlist = new Array();
if (userinput.search('@') != 0) {
var len = userinput.search('@');
//用来拼接的用户输入内容 = 只使用@之后的字符串
var x = userinput.substring(len + 1, userinput.length); //取@之后的部分
for (var i = 0; i < postfixList.length; i++) {
if (postfixList[i].search(x) == 0) {
newpostlist.push(postfixList[i]);
}
}
//若@后面没有字符或者新数组newpostlist为空,就返回原来的postfixlist
if (x === '' || newpostlist == '') {
return postfixList;
}
return newpostlist;
} else {
return postfixList;
}
}
//根据输入内容和匹配来生成提示数组
function promptContent() {
var x = htmlEncode(getText()) //转码;
// var x=getText();
var tips = new Array();
if (x.indexOf("@") != -1) {
var p = x.slice(0, x.indexOf("@"));
for (i = 0; i < postlist().length; i++) {
tips[i] = p + "@" + postlist()[i];
}
} else {
for (i = 0; i < postfixList.length; i++) {
tips[i] = x + "@" + postfixList[i];
}
}
return tips;
}
//添加提示数组进入li
function add() {
var sug = document.getElementById("email-sug-wrapper");
var tips = promptContent();
while (sug.hasChildNodes()) {
sug.removeChild(sug.firstChild);
}
//将之前的列表清除掉,然后重新生成新的列表
for (i = 0; i < tips.length; i++) {
var tip_li = document.createElement("li");
tip_li.innerHTML = tips[i];
sug.appendChild(tip_li);
}
} function judge() {
//判空,是“”没有内容,不能为“ ”
if (getText() == "") {
hide();
} else {
display();
} } function hide() {
sug.style.display = "none";
} function display() {
sug.style.display = "block";
} /*1.用浏览器内部转换器实现html转码*/
function htmlEncode(html){
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement ("div");
//2.然后将要转换的字符串设置为这个元素的innerText(ie支持)或者textContent(火狐,google支持)
(temp.textContent != undefined ) ? (temp.textContent = html) : (temp.innerText = html);
//3.最后返回这个元素的innerHTML,即得到经过HTML编码转换的字符串了
var output = temp.innerHTML;
temp = null;
return output;
}
/*2.用浏览器内部转换器实现html解码*/
function htmlDecode(text){
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement("div");
//2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)
temp.innerHTML = text;
//3.最后返回这个元素的innerText(ie支持)或者textContent(火狐,google支持),即得到经过HTML解码的字符串了。
var output = temp.innerText || temp.textContent;
temp = null;
return output;
}
</script>
</body> </html>

加上键盘

需求

我们给提示框加上3个按键的功能,分别是回车和上下键,使得可以通过键盘操作进行提示框的选择

  • 当有提示框的时候,默认第一个提示为被选择状态,用一个和鼠标滑过不一样的背景色来标识
  • 当有输入框的时候,按上键,可以向上移动选择状态,如果按键之前的被选择提示是第一个,则被选状态移到最下面一个
  • 当有输入框的时候,按下键,可以向下移动选择状态,如果按键之前的被选择提示是最后一个,则被选状态移到第一个
  • 当有输入框时,按回车键,则将当前被选中状态的提示内容,放到输入框中,并隐藏提示框
  • 当没有输入框的时候,这3个键盘按键无响应
  • 当用户输入发生改变的时候,选择状态都重新切回到第一个提示

优化体验

需求

当我们进入页面,或者当我们点击鼠标进行提示选择后,输入框的焦点就不在了,所以请你优化一下用户体验:

  • 一进入页面就将焦点放在输入框中
  • 用户点击鼠标,进行提示选择后,焦点依然在输入框中
  • 用户按ESC键的时候,对用户输入进行全选

代码3

 <!DOCTYPE html>
<html> <head>
<meta charset="utf-8" />
<title>邮箱后缀提示3-添加键盘响应及输入框焦点优化</title>
<style>
#input-email{
width: 300px;
height: 30px;
}
.email-sug{
width: 300px;
list-style: none;
padding: 0px;
margin: 0px;
border: 2px solid rgba(134, 132, 132,0.3);
border-top:none;
display: none;
/* 初始不显示,避免边框出现 */
}
.email-sug li{
width: 300px;
height: 30px;
background-color: #ffffff;
color: darkgrey;
line-height: 30px;
overflow: hidden;
padding-left: 10px;
box-sizing: border-box;
}
.email-sug li:hover{
background-color:skyblue;
}
.email-sug li.active{
background-color:pink;
}
</style>
</head> <body>
<div class="wrapper">
<input type="text" id="input-email" autofocus="autofocus">
<ul class="email-sug" id="email-sug-wrapper"> </ul>
</div>
<script>
var postfixList = ["163.com", "gmail.com", "126.com", "qq.com", "263.net"];
var txt = document.getElementById("input-email");
var sug = document.getElementById("email-sug-wrapper");
var nowSelectTipIndex = 0; //获取输入文本
txt.oninput = function (e) {
console.log("event handle4");
//按下的是内容,则重置选中状态,坐标清零,避免光标位置已经计算存入。
if (!(e.keyCode == 40 || e.keyCode == 38 || e.keyCode == 13)) {
nowSelectTipIndex = 0;
}
judge();
add();
}
//点击事件响应
sug.addEventListener("click", function (ev) {
//采用事件代理,监听父级点击事件,通过target获取当前li
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if (target.nodeName.toLowerCase() == "li") {
hide();
txt.focus(); //写在return之前,不然无效
return txt.value = htmlDecode(target.innerHTML); //解码
//return txt.value= target.innerHTML;
}
})
//键盘事件响应
document.addEventListener("keydown", function (e) {
var e = e || window.event;
var key = e.which || e.keyCode;
var list = document.getElementsByTagName("li");
//向下键
if (key == 40) {
for (i = 0; i < list.length; i++) {
list[i].setAttribute("class", "");
}
nowSelectTipIndex++;
if (nowSelectTipIndex + 1 > list.length) {
nowSelectTipIndex = 0;
}
list[nowSelectTipIndex].setAttribute("class", "active");
}
//向上键
if (key == 38) {
for (i = 0; i < list.length; i++) {
list[i].setAttribute("class", "");
}
nowSelectTipIndex--;
if (nowSelectTipIndex < 0) {
nowSelectTipIndex = list.length - 1;
}
list[nowSelectTipIndex].setAttribute("class", "active");
}
//回车键
if (key == 13) {
var x = document.getElementsByClassName("active");
txt.value = htmlDecode(x[0].innerHTML); //用textcontent会去除html标签例如<b>。。
hide();
}
if (key == 27) {
txt.setSelectionRange(0, -1); //ESC全选上文本框内容
hide();
} })
//获取输入内容,并去除首尾空格
function getText() {
var inputText = txt.value.trim();
return inputText;
}
//判断是否生成新的数组
function postlist() {
var userinput = getText();
var newpostlist = new Array();
if (userinput.search('@') != 0) {
var len = userinput.search('@');
//用来拼接的用户输入内容 = 只使用@之后的字符串
var x = userinput.substring(len + 1, userinput.length); //取@之后的部分
for (var i = 0; i < postfixList.length; i++) {
if (postfixList[i].search(x) == 0) {
newpostlist.push(postfixList[i]);
}
}
//若@后面没有字符或者新数组newpostlist为空,就返回原来的postfixlist
if (x === '' || newpostlist == '') {
return postfixList;
}
return newpostlist;
} else {
return postfixList;
}
}
//根据输入内容和匹配来生成提示数组
function promptContent() {
var x = htmlEncode(getText()); //转码;
// var x=getText();
var tips = new Array();
if (x.indexOf("@") != -1) {
var p = x.slice(0, x.indexOf("@"));
for (i = 0; i < postlist().length; i++) {
tips[i] = p + "@" + postlist()[i];
}
} else {
for (i = 0; i < postfixList.length; i++) {
tips[i] = x + "@" + postfixList[i];
}
}
return tips;
}
//添加提示数组进入li
function add() {
var sug = document.getElementById("email-sug-wrapper");
var tips = promptContent();
while (sug.hasChildNodes()) {
sug.removeChild(sug.firstChild);
}
//将之前的列表清除掉,然后重新生成新的列表
for (i = 0; i < tips.length; i++) {
var tip_li = document.createElement("li");
tip_li.innerHTML = tips[i];
sug.appendChild(tip_li);
}
//初始选择第一项为选中状态,加类名变粉色(需要生成li之后再调用)。
var list = document.getElementsByTagName("li");
list[0].setAttribute("class", "active");
} function judge() {
//判空,是“”没有内容,不能为“ ”
if (getText() == "") {
hide();
} else {
display();
} }
//控制提示列表隐藏
function hide() {
sug.style.display = "none";
}
//控制提示列表显示
function display() {
sug.style.display = "block";
} /*1.用浏览器内部转换器实现html转码*/
function htmlEncode(html) {
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement("div");
//2.然后将要转换的字符串设置为这个元素的innerText(ie支持)或者textContent(火狐,google支持)
(temp.textContent != undefined) ? (temp.textContent = html) : (temp.innerText = html);
//3.最后返回这个元素的innerHTML,即得到经过HTML编码转换的字符串了
var output = temp.innerHTML;
temp = null;
return output;
}
/*2.用浏览器内部转换器实现html解码*/
function htmlDecode(text) {
//1.首先动态创建一个容器标签元素,如DIV
var temp = document.createElement("div");
//2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)
temp.innerHTML = text;
//3.最后返回这个元素的innerText(ie支持)或者textContent(火狐,google支持),即得到经过HTML解码的字符串了。
var output = temp.innerText || temp.textContent;
temp = null;
return output;
}
</script>
</body> </html>

最终效果如图:

JavaScript实现邮箱后缀提示功能的更多相关文章

  1. [模仿微软Live.cn]JavaScript输入邮箱自动提示

    原理是:在一个输入框 中,当我输入任何字的时候 自动下拉相应的邮箱提示,在输入框输入123的时候 下拉框有所有123的邮箱 输入其他的时候 有其他文案对应的邮箱. 同理 此插件不需要任何html标签, ...

  2. JS输入框邮箱自动提示(带有demo和源码)(转载)

    今天在javascriptQQ群里面 有童鞋问到 有没有 "JS输入框邮箱自动提示"插件,即说都找遍了github上源码 都没有看到这样类似的插件,然后我想了下 "JS输 ...

  3. JS输入框邮箱自动提示(带有demo和源码)

    今天在javascriptQQ群里面 有童鞋问到 有没有 "JS输入框邮箱自动提示"插件,即说都找遍了github上源码 都没有看到这样类似的插件,然后我想了下 "JS输 ...

  4. jquery 实现邮箱输入自动提示功能

    邮箱的广泛使用得益于它的免费,因此很多网站在注册的时候都会直接使用邮箱作为账号名 为了提高用户的体验,很多网站都会实现邮箱输入的自动提示功能,所有自己也实现了一个,先看下效果吧,觉得效果还行的就拿去 ...

  5. Visual Studio 2013开启JavaScript的智能提示功能

    在前一次的发布的时候,我们共享了Visual Studio 2013中Windows Azure移动服务的集成和功能.其中包含了移动服务表脚本的编辑能力的介绍.这一次的发布,我们将描述在Visual ...

  6. jquery 实现邮箱输入自动提示功能:(二)

    上篇文章写到了一个不错的jquery实现邮箱输入自动提示功能,发现还有一个不错的自动提示插件: 先展示结果如图: html代码: <center> <h1>输入邮箱试试!< ...

  7. jquery 实现邮箱输入自动提示功能:(一)

    记得去年做某个项目的时候,用到了邮箱输入自动提示功能,于是网上搜了一下,发现了这个写得不错,现在回想起来,转载一下,方便查阅. 邮箱的广泛使用得益于它的免费,因此很多网站在注册的时候都会直接使用邮箱作 ...

  8. jQuery插件AjaxFileUpload文件上传实现Javascript多文件上传功能

     Ajax file upload plugin是一个功能强大的文件上传jQuery插件,可自定义链接.或其它元素庖代传统的file表单上传结果,可实现Ajax动态提示文件上传 过程,同时支撑多文 ...

  9. Visual Studio Code 使用 Typings 实现智能提示功能

    前言 我们知道在IDE中代码的智能提示几乎都是标配,虽然一些文本编辑器也有一些简单的提示,但这是通过代码片段提供的.功能上远不能和IDE相比.不过最近兴起的文本编辑器的新锐 Visual Studio ...

随机推荐

  1. CentOS7 安装 Docker CE步骤

    准备工作 系统要求 Docker CE 支持 64 位版本 CentOS 7,并且要求内核版本不低于 3.10. CentOS 7 满足最低内核的要求,但由于内核版本比较低,部分功能(如 overla ...

  2. 用 gdb 和 qemu 调试 grub

    因为qemu内置了gdbserver,所以我们可以用gdb调试qemu虚拟机上执行的代码,而且不受客户机系统限制. 以下内容是我调试 grub 0.97 时的一份笔记. 准备 qemu, gdb,以及 ...

  3. web 应用的部署

    一.项目管理 : zentao(国产开源),其他 project.redmine.trac 二.自动部署: jenkins:自动化配置 docker:容器,类似虚拟机,不过只是本机系统的内核的一个虚拟 ...

  4. MySql 的操作日志 历史记录

    如何查看mysql数据库操作记录日志 1.首先确认你日志是否启用了mysql>show variables like 'log_bin'. 2.如果启用了,即ON,那日志文件就在mysql的安装 ...

  5. Web开发模式

    原文链接 开发模式的介绍(完善版) 在Web开发模式中,有两个主要的开发结构,称为模式一(Mode I)和模式二(Mode II). 首先我们来理清一些概念吧: DAO(Data Access Obj ...

  6. wordcloud词云--可视化

    import jieba import wordcloud f = open("新时代中国特色社会主义.txt", "r", encoding="gb ...

  7. python全栈开发_day4_if,while和for

    一.if 1)if的用途 if常用于判断. 2)if的语法 tag=True tag2=True if tag: print("代码") elif tag2: print(&quo ...

  8. amqp模块在python2.7.6版本上报错的问题

    机器的环境是python2.7.6; 使用pip install安装了amqp.正常安装,未报错. amqp安装的版本是2.1.4. 在python中,使用import amqp,报错如下: Trac ...

  9. VUE 监听局部滚动 设置ICON的位置跟随

    效果图如下: 目的: 为了让 + 号与 - 号跟随在当前 tr 的前边 第一步: 当tr指针经过时获取tr的相对位置 HTML JS 第二步:给滚动的div元素添加滚动事件获取滚动的高度 最后:设置I ...

  10. init_config_file.lua

    --[[ 读取限流配置 --]] --获取共享内存 local limit_req_store = ngx.shared.limit_req_store --初始化拒绝 URI 列表 reject_u ...