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 解决表单仍然提交即使监听处理函数返回false
Mar 14 Javascript
javascript怎么禁用浏览器后退按钮
Mar 27 Javascript
JavaScript+html5 canvas绘制渐变区域完整实例
Jan 26 Javascript
jquery判断iPhone、Android设备类型
Sep 14 Javascript
Jquery Easyui选项卡组件Tab使用详解(10)
Dec 18 Javascript
Vue结合SignalR实现前后端实时消息同步
Sep 19 Javascript
基于webpack 实用配置方法总结
Sep 28 Javascript
基于vue实现分页效果
Nov 06 Javascript
AngularJS 应用模块化的使用
Apr 04 Javascript
详解swiper在vue中的应用(以3.0为例)
Sep 20 Javascript
vue+Vue Router多级侧导航切换路由(页面)的实现代码
Dec 20 Javascript
js实现图片实时时钟
Jan 15 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
DOTA2 玩家自创拉野攻略 特色英雄快速成长篇
2020/04/20 DOTA
PHP HTML代码串 截取实现代码
2009/06/29 PHP
PHP连接MSSQL2008/2005数据库(SQLSRV)配置实例
2014/10/22 PHP
php中magic_quotes_gpc对unserialize的影响分析
2014/12/16 PHP
PHP实现 APP端微信支付功能
2018/06/22 PHP
解决FireFox下[使用event很麻烦]的问题
2006/11/26 Javascript
jQuery 借助插件Lavalamp实现导航条动态美化效果
2013/09/27 Javascript
JavaScript获取当前页面上的指定对象示例代码
2014/02/28 Javascript
js 事件截取enter按键页面提交事件示例代码
2014/03/04 Javascript
javascript模拟枚举的简单实例
2014/03/06 Javascript
举例详解JavaScript中Promise的使用
2015/06/24 Javascript
使用控制台破解百小度一个月只准改一次名字
2015/08/13 Javascript
13个PHP函数超实用
2015/10/21 Javascript
JQuery.Ajax()的data参数类型实例详解
2015/11/20 Javascript
javascript的函数劫持浅析
2016/09/26 Javascript
利用NPM淘宝的node.js镜像加速nvm
2017/03/27 Javascript
详解如何在Vue2中实现组件props双向绑定
2017/03/29 Javascript
vue 中自定义指令改变data中的值
2017/06/02 Javascript
JS中mouseup事件丢失的原因与解决办法
2017/06/14 Javascript
vue 使用ref 让父组件调用子组件的方法
2018/02/08 Javascript
小程序云函数调用API接口的方法
2019/05/17 Javascript
js删除对象中的某一个字段的方法实现
2021/01/11 Javascript
《与孩子一起学编程》python自测题
2018/05/27 Python
对numpy中的transpose和swapaxes函数详解
2018/08/02 Python
python调用其他文件函数或类的示例
2019/07/16 Python
python中time库的实例使用方法
2019/10/31 Python
纯css3实现照片墙效果
2014/12/26 HTML / CSS
HTML5实现分享到微信好友朋友圈QQ好友QQ空间微博二维码功能
2018/01/03 HTML / CSS
阿波罗盒子:Apollo Box
2017/08/14 全球购物
abstract class和interface有什么区别?
2012/01/03 面试题
如何在存储过程中使用Loop
2016/01/05 面试题
前厅部经理岗位职责范文
2014/02/04 职场文书
五五普法心得体会
2014/09/04 职场文书
初中作文评语
2014/12/25 职场文书
canvas绘制折线路径动画实现
2021/05/12 Javascript
JavaScript分页组件使用方法详解
2021/07/26 Javascript