zoukankan      html  css  js  c++  java
  • JavaScript实现邮箱后缀提示功能

    先来个基础的

    需求

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

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

    小优化编码

    需求

    如果我们输入的是 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

      1 <!DOCTYPE html>
      2 <html>
      3 
      4 <head>
      5     <meta charset="utf-8" />
      6     <title>邮箱后缀提示1-完成基本提示</title>
      7     
      8 </head>
      9 
     10 <body>
     11     <div class="wrapper">
     12         <input type="text" id="input-email">
     13         <ul class="email-sug" id="email-sug-wrapper">
     14 
     15         </ul>
     16     </div>
     17     <script>
     18         var postfixList = ["163.com", "gmail.com", "126.com", "qq.com", "263.net"];
     19         var txt = document.getElementById("input-email");
     20         var sug = document.getElementById("email-sug-wrapper");
     21         
     22         // keys.addEventListener("keyup",function(){
     23         //     console.log("event handle1");
     24         // })
     25         // keys.addEventListener("keypress",function(){
     26         //     console.log("event handle2");
     27         // })
     28         // keys.addEventListener("keydown",function(){
     29         //     console.log("event handle3");
     30         // })
     31         // keys.addEventListener("input",function(){
     32         //     console.log("event handle4");
     33         // })
     34 
     35         //经过查看各个效果,oninput效果最符合需求。
     36         txt.oninput = function () {
     37             console.log("event handle4");
     38             judge();
     39             add();
     40 
     41         }
     42         function getText() {
     43             var inputText = txt.value.trim();
     44             return inputText;
     45         }
     46         //判断是否生成新的数组
     47         function postlist() {
     48             var userinput = getText();
     49             var newpostlist = new Array();
     50             if (userinput.search('@') != 0) {
     51                 var len = userinput.search('@');
     52                 //用来拼接的用户输入内容 = 只使用@之后的字符串
     53                 var x = userinput.substring(len + 1, userinput.length); //取@之后的部分
     54                 for (var i = 0; i < postfixList.length; i++) {
     55                     if (postfixList[i].search(x) == 0) {
     56                         newpostlist.push(postfixList[i]);
     57                     }
     58                 }
     59                 //若@后面没有字符或者新数组newpostlist为空,就返回原来的postfixlist
     60                 if (x === '' || newpostlist == '') {
     61                     return postfixList;
     62                 }
     63                 return newpostlist;
     64             } else {
     65                 return postfixList;
     66             }
     67         }
     68         //根据输入内容和匹配来生成提示数组
     69         function promptContent() {
     70             var x = getText();
     71             var tips = new Array();
     72             if (x.indexOf("@") != -1) {
     73                 var p = x.slice(0, x.indexOf("@"));
     74                 for (i = 0; i < postlist().length; i++) {
     75                     tips[i] = p + "@" + postlist()[i];
     76                 }
     77             } else {
     78                 for (i = 0; i < postfixList.length; i++) {
     79                     tips[i] = x + "@" + postfixList[i];
     80                 }
     81             }
     82             return tips;
     83         }
     84         //添加提示数组进入li
     85         function add() {
     86             var sug = document.getElementById("email-sug-wrapper");
     87             var tips = promptContent();
     88             while (sug.hasChildNodes()) {
     89                 sug.removeChild(sug.firstChild);
     90             }
     91             //将之前的列表清除掉,然后重新生成新的列表
     92             for (i = 0; i < tips.length; i++) {
     93                 var tip_li = document.createElement("li");
     94                 tip_li.innerHTML = tips[i];
     95                 sug.appendChild(tip_li);
     96             }
     97         }
     98 
     99         function judge() {
    100             //判空,是“”没有内容,不能为“ ”
    101             if (getText() == "") {
    102                 hide();
    103             } else {
    104                 display();
    105             }
    106 
    107         }
    108 
    109         function hide() {
    110             sug.style.display = "none";
    111         }
    112 
    113         function display() {
    114             sug.style.display = "block";
    115         }
    116     </script>
    117 </body>
    118 
    119 </html>

    新的需求编码

    需求

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

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

    需求

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

    阅读

    设计

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

    代码2

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8" />
        <title>邮箱后缀提示2-添加样式和监听鼠标点击和转码内容</title>
        <style>
        #input-email{
             300px;
            height: 30px;
        }
        .email-sug{
             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{
             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

      1 <!DOCTYPE html>
      2 <html>
      3 
      4 <head>
      5     <meta charset="utf-8" />
      6     <title>邮箱后缀提示3-添加键盘响应及输入框焦点优化</title>
      7     <style>
      8         #input-email{
      9          300px;
     10         height: 30px;
     11     }
     12     .email-sug{
     13          300px;
     14         list-style: none;
     15         padding: 0px;
     16         margin: 0px;
     17         border: 2px solid rgba(134, 132, 132,0.3);
     18         border-top:none;
     19         display: none;
     20         /* 初始不显示,避免边框出现 */
     21     }
     22     .email-sug li{
     23          300px;
     24         height: 30px;
     25         background-color: #ffffff;
     26         color: darkgrey;
     27         line-height: 30px;    
     28         overflow: hidden;
     29         padding-left: 10px;
     30         box-sizing: border-box;
     31     }
     32     .email-sug li:hover{
     33         background-color:skyblue;
     34     }
     35     .email-sug li.active{
     36         background-color:pink;
     37     }
     38     </style>
     39 </head>
     40 
     41 <body>
     42     <div class="wrapper">
     43         <input type="text" id="input-email" autofocus="autofocus">
     44         <ul class="email-sug" id="email-sug-wrapper">
     45 
     46         </ul>
     47     </div>
     48     <script>
     49         var postfixList = ["163.com", "gmail.com", "126.com", "qq.com", "263.net"];
     50         var txt = document.getElementById("input-email");
     51         var sug = document.getElementById("email-sug-wrapper");
     52         var nowSelectTipIndex = 0;
     53 
     54         //获取输入文本
     55         txt.oninput = function (e) {
     56             console.log("event handle4");
     57             //按下的是内容,则重置选中状态,坐标清零,避免光标位置已经计算存入。
     58             if (!(e.keyCode == 40 || e.keyCode == 38 || e.keyCode == 13)) {
     59                 nowSelectTipIndex = 0;
     60             }
     61             judge();
     62             add();
     63         }
     64         //点击事件响应
     65         sug.addEventListener("click", function (ev) {
     66             //采用事件代理,监听父级点击事件,通过target获取当前li
     67             var ev = ev || window.event;
     68             var target = ev.target || ev.srcElement;
     69             if (target.nodeName.toLowerCase() == "li") {
     70                 hide();
     71                 txt.focus(); //写在return之前,不然无效
     72                 return txt.value = htmlDecode(target.innerHTML); //解码
     73                 //return txt.value= target.innerHTML;      
     74             }
     75         })
     76         //键盘事件响应
     77         document.addEventListener("keydown", function (e) {
     78             var e = e || window.event;
     79             var key = e.which || e.keyCode;
     80             var list = document.getElementsByTagName("li");
     81             //向下键
     82             if (key == 40) {
     83                 for (i = 0; i < list.length; i++) {
     84                     list[i].setAttribute("class", "");
     85                 }
     86                 nowSelectTipIndex++;
     87                 if (nowSelectTipIndex + 1 > list.length) {
     88                     nowSelectTipIndex = 0;
     89                 }
     90                 list[nowSelectTipIndex].setAttribute("class", "active");
     91             }
     92             //向上键
     93             if (key == 38) {
     94                 for (i = 0; i < list.length; i++) {
     95                     list[i].setAttribute("class", "");
     96                 }
     97                 nowSelectTipIndex--;
     98                 if (nowSelectTipIndex < 0) {
     99                     nowSelectTipIndex = list.length - 1;
    100                 }
    101                 list[nowSelectTipIndex].setAttribute("class", "active");
    102             }
    103             //回车键
    104             if (key == 13) {
    105                 var x = document.getElementsByClassName("active");
    106                 txt.value = htmlDecode(x[0].innerHTML); //用textcontent会去除html标签例如<b>。。
    107                 hide();
    108             }
    109             if (key == 27) {
    110                 txt.setSelectionRange(0, -1); //ESC全选上文本框内容
    111                 hide();
    112             }
    113 
    114         })
    115         //获取输入内容,并去除首尾空格
    116         function getText() {
    117             var inputText = txt.value.trim();
    118             return inputText;
    119         }
    120         //判断是否生成新的数组
    121         function postlist() {
    122             var userinput = getText();
    123             var newpostlist = new Array();
    124             if (userinput.search('@') != 0) {
    125                 var len = userinput.search('@');
    126                 //用来拼接的用户输入内容 = 只使用@之后的字符串
    127                 var x = userinput.substring(len + 1, userinput.length); //取@之后的部分
    128                 for (var i = 0; i < postfixList.length; i++) {
    129                     if (postfixList[i].search(x) == 0) {
    130                         newpostlist.push(postfixList[i]);
    131                     }
    132                 }
    133                 //若@后面没有字符或者新数组newpostlist为空,就返回原来的postfixlist
    134                 if (x === '' || newpostlist == '') {
    135                     return postfixList;
    136                 }
    137                 return newpostlist;
    138             } else {
    139                 return postfixList;
    140             }
    141         }
    142         //根据输入内容和匹配来生成提示数组
    143         function promptContent() {
    144             var x = htmlEncode(getText()); //转码;
    145             // var x=getText();
    146             var tips = new Array();
    147             if (x.indexOf("@") != -1) {
    148                 var p = x.slice(0, x.indexOf("@"));
    149                 for (i = 0; i < postlist().length; i++) {
    150                     tips[i] = p + "@" + postlist()[i];
    151                 }
    152             } else {
    153                 for (i = 0; i < postfixList.length; i++) {
    154                     tips[i] = x + "@" + postfixList[i];
    155                 }
    156             }
    157             return tips;
    158         }
    159         //添加提示数组进入li
    160         function add() {
    161             var sug = document.getElementById("email-sug-wrapper");
    162             var tips = promptContent();
    163             while (sug.hasChildNodes()) {
    164                 sug.removeChild(sug.firstChild);
    165             }
    166             //将之前的列表清除掉,然后重新生成新的列表
    167             for (i = 0; i < tips.length; i++) {
    168                 var tip_li = document.createElement("li");
    169                 tip_li.innerHTML = tips[i];
    170                 sug.appendChild(tip_li);
    171             }
    172             //初始选择第一项为选中状态,加类名变粉色(需要生成li之后再调用)。
    173             var list = document.getElementsByTagName("li");
    174             list[0].setAttribute("class", "active");
    175         }
    176 
    177         function judge() {
    178             //判空,是“”没有内容,不能为“ ”
    179             if (getText() == "") {
    180                 hide();
    181             } else {
    182                 display();
    183             }
    184 
    185         }
    186         //控制提示列表隐藏
    187         function hide() {
    188             sug.style.display = "none";
    189         }
    190         //控制提示列表显示  
    191         function display() {
    192             sug.style.display = "block";
    193         }
    194 
    195         /*1.用浏览器内部转换器实现html转码*/
    196         function htmlEncode(html) {
    197             //1.首先动态创建一个容器标签元素,如DIV
    198             var temp = document.createElement("div");
    199             //2.然后将要转换的字符串设置为这个元素的innerText(ie支持)或者textContent(火狐,google支持)
    200             (temp.textContent != undefined) ? (temp.textContent = html) : (temp.innerText = html);
    201             //3.最后返回这个元素的innerHTML,即得到经过HTML编码转换的字符串了
    202             var output = temp.innerHTML;
    203             temp = null;
    204             return output;
    205         }
    206         /*2.用浏览器内部转换器实现html解码*/
    207         function htmlDecode(text) {
    208             //1.首先动态创建一个容器标签元素,如DIV
    209             var temp = document.createElement("div");
    210             //2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)
    211             temp.innerHTML = text;
    212             //3.最后返回这个元素的innerText(ie支持)或者textContent(火狐,google支持),即得到经过HTML解码的字符串了。
    213             var output = temp.innerText || temp.textContent;
    214             temp = null;
    215             return output;
    216         }
    217     </script>
    218 </body>
    219 
    220 </html>

    最终效果如图:

  • 相关阅读:
    BZOJ1208
    BZOJ1024
    BZOJ_day4&&DSFZ_day1
    BZOJ day2_plus
    BZOJ day2
    系统设计2:数据库设计
    设计模式8:外观模式
    系统设计1:概述
    设计模式7:模板方法模式
    九章算法班ladder题目梳理
  • 原文地址:https://www.cnblogs.com/Joe-and-Joan/p/10111099.html
Copyright © 2011-2022 走看看