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 相关文章推荐
javascript document.compatMode兼容性
Feb 23 Javascript
30个最佳jQuery Lightbox效果插件分享
Apr 11 Javascript
js模仿jquery的写法示例代码
Jun 16 Javascript
jquery slibings选取同级其他元素的实现代码
Nov 15 Javascript
JavaScript函数的调用以及参数传递
Oct 21 Javascript
使用JQuery FancyBox插件实现图片展示特效
Nov 16 Javascript
JS简单实现DIV相对于浏览器固定位置不变的方法
Jun 17 Javascript
jQuery EasyUI编辑DataGrid用combobox实现多级联动
Aug 29 Javascript
js实现无缝滚动图
Feb 22 Javascript
Vue开发Html5微信公众号的步骤
Apr 11 Javascript
JavaScript canvas仿代码流瀑布
Feb 10 Javascript
js 实现Material UI点击涟漪效果示例
Sep 23 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
PHP把空格、换行符、中文逗号等替换成英文逗号的正则表达式
2014/05/04 PHP
PHP实现返回JSON和XML的类分享
2015/01/28 PHP
Thinkphp调用Image类生成缩略图的方法
2015/03/07 PHP
php微信公众平台示例代码分析(二)
2016/12/06 PHP
PHP编译configure时常见错误的总结
2017/08/17 PHP
PHP PDOStatement::getColumnMeta讲解
2019/02/01 PHP
List the UTC Time on a Computer
2007/06/11 Javascript
浅谈Javascript事件模拟
2012/06/27 Javascript
原生JS可拖动弹窗效果实例代码
2013/11/09 Javascript
jquery使用$(element).is()来判断获取的tagName
2014/08/24 Javascript
Javascript中的方法链(Method Chaining)介绍
2015/03/15 Javascript
一看就懂:jsonp详解
2015/06/01 Javascript
js实现页面跳转的五种方法推荐
2016/03/10 Javascript
video.js使用改变ui过程
2017/03/05 Javascript
微信小程序实现用table显示数据库反馈的多条数据功能示例
2019/05/07 Javascript
JavaScript实现页面中录音功能的方法
2019/06/04 Javascript
javascript实现支付宝滑块验证码效果
2020/07/24 Javascript
python使用cookielib库示例分享
2014/03/03 Python
python在windows下实现ping操作并接收返回信息的方法
2015/03/20 Python
python实现基于两张图片生成圆角图标效果的方法
2015/03/26 Python
tensorflow TFRecords文件的生成和读取的方法
2018/02/06 Python
使用PyInstaller将python转成可执行文件exe笔记
2018/05/26 Python
OpenCV+Python识别车牌和字符分割的实现
2019/01/31 Python
使用Python3+PyQT5+Pyserial 实现简单的串口工具方法
2019/02/13 Python
Puppeteer使用示例详解
2019/06/20 Python
Django组件content-type使用方法详解
2019/07/19 Python
Python 绘制可视化折线图
2020/07/22 Python
解决html5中的video标签ios系统中无法播放使用的问题
2020/08/10 HTML / CSS
萌新HTML5 入门指南(二)
2020/11/09 HTML / CSS
水上运动奥特莱斯:Wasterports Outlet
2018/08/08 全球购物
全球最大运动品牌的男装、女装和童装官方库存商:A&A Sports
2021/01/17 全球购物
你常见到的runtime exception
2016/09/05 面试题
抗洪救灾先进集体事迹材料
2014/05/26 职场文书
人力资源管理毕业求职信
2014/08/05 职场文书
2015年学校办公室工作总结
2015/05/26 职场文书
详细谈谈JavaScript中循环之间的差异
2021/08/23 Javascript