JavaScript实现邮箱后缀提示功能的示例代码


Posted in Javascript onDecember 13, 2018

先来个基础的

需求

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

小优化编码

需求

如果我们输入的是 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实现邮箱后缀提示功能的示例代码

JavaScript实现邮箱后缀提示功能的示例代码

JavaScript实现邮箱后缀提示功能的示例代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jquery扩展漂亮的CheckBox(自己编写)
Nov 19 Javascript
常用javascript表单验证汇总
Jul 20 Javascript
JavaScript的ExtJS框架中表格的编写教程
May 21 Javascript
BootStrap智能表单实战系列(三)分块表单配置详解
Jun 13 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
Nov 18 Javascript
正则 js分转元带千分符号详解
Mar 08 Javascript
鼠标经过出现气泡框的简单实例
Mar 17 Javascript
Angular.js 4.x中表单Template-Driven Forms详解
Apr 25 Javascript
JS仿QQ好友列表展开、收缩功能(第二篇)
Jul 07 Javascript
JavaScript输出所选择起始与结束日期的方法
Jul 12 Javascript
bootstrap轮播模板使用方法详解
Nov 17 Javascript
Vue.js 实现数据展示全部和收起功能
Sep 05 Javascript
深入理解js A*寻路算法原理与具体实现过程
Dec 13 #Javascript
Vue.js上传图片到阿里云OSS存储的方法示例
Dec 13 #Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
Dec 13 #Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【凹多边形的分离轴检测算法】
Dec 13 #Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【矩形情况】
Dec 13 #Javascript
详解Express笔记之动态渲染HTML(新手入坑)
Dec 13 #Javascript
js实现黑白div块画空心的图形
Dec 13 #Javascript
You might like
PHP5 的对象赋值机制介绍
2011/08/02 PHP
自制PHP框架之路由与控制器
2017/05/07 PHP
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
PHP文件类型检查及fileinfo模块安装使用详解
2019/05/09 PHP
js常用函数 不错
2006/09/08 Javascript
JavaScript 事件的一些重要说明
2009/10/25 Javascript
javascript DOM编程实例(智播客学习)
2009/11/23 Javascript
js定义对象或数组直接量时各浏览器对多余逗号的处理(json)
2011/03/05 Javascript
基于JQuery的Select选择框的华丽变身
2011/08/23 Javascript
为EasyUI的Tab标签添加右键菜单的方法
2012/07/14 Javascript
JS实现仿苹果底部任务栏菜单效果代码
2015/08/28 Javascript
JS+Canvas绘制时钟效果
2020/08/20 Javascript
js模糊查询实例分享
2016/12/26 Javascript
如何编写一个完整的Angular4 FormText 组件
2017/11/18 Javascript
浅谈vue 单文件探索
2018/09/05 Javascript
详解JS浏览器事件循环机制
2019/03/27 Javascript
vue实现前台列表数据过滤搜索、分页效果
2019/05/28 Javascript
[02:34]肉山说——泡妞篇
2014/09/16 DOTA
[57:22]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第五场
2018/04/10 DOTA
[50:54]完美世界DOTA2联赛 GXR vs IO 第三场 11.07
2020/11/10 DOTA
[04:20]DOTA2-DPC中国联赛 正赛 VG vs LBZS 选手采访 1月19日
2021/03/11 DOTA
python发送告警邮件脚本
2018/09/17 Python
Python实现连接MySql数据库及增删改查操作详解
2019/04/16 Python
jupyter notebook的安装与使用详解
2020/05/18 Python
django项目中使用云片网发送短信验证码的实现
2021/01/19 Python
Turnbull & Asser官网:英国皇室御用的顶级定制衬衫
2019/01/31 全球购物
瑞士首家网上药店折扣店:McDrogerie
2020/12/22 全球购物
企业面试题试卷附带答案
2015/12/20 面试题
宿舍打麻将检讨书
2014/01/24 职场文书
外贸员简历中的自我评价
2014/03/04 职场文书
2014两会优秀的心得体会范文
2014/03/17 职场文书
安全保卫工作竞聘材料
2014/08/25 职场文书
2015年骨干教师工作总结
2015/05/26 职场文书
大学优秀学生主要事迹材料
2015/11/04 职场文书
golang 在windows中设置环境变量的操作
2021/04/29 Golang
zabbix如何添加监控主机和自定义监控项
2022/08/14 Servers