zoukankan      html  css  js  c++  java
  • 跟风玩玩JavaScript Suggest效果

      百度、谷歌的搜索提示是一个很cool的效果,恰逢美大(@司徒正美)前几天做了一个demo,于是自己也来实现一番,实现的思路有别于美大,可以对比着研究。

      传送门——美大实现版:javascript suggest效果(mass framewrok很强大,强烈建议关注)

      @个人实现效果(没有用框架...同时懒得做IE678的兼容...的草稿版,chrome下效果尤佳),实际效果也是查询当前浏览器的对象和属性:
        ↑_怒击链接下载实例

    低调的声明:
      1.由于是用原生js写的,而且没有做兼容,IE下不要指望正常了(= = !),有兴趣的话可以按思路用框架封装(广告:推荐司徒大大的mass框架)。
      2.这里重点只表现出实现的思路。兼容性和代码组织、细节、性能优化等等忽略了。

    效果比较简单,有几点供大家思考:
      1.数据的查询方式可以通过search函数改变(如改成ajax)。
      2.按键即触发查询,按键事件是绑定在keyup而不是keypress。
      3.按上下键选择suggest条目的按键事件是绑定在keydown而不是keypress。
      4.suggest条目较多时出现滚动条,由于按上下键选择suggest条时焦点在input,所以需要修正可视区域。
      5.suggest框的显隐时机。
     

    html结构:
      输入框input,suggest框ul

    html
    <div id="warpper">
    <input type="text" id="search" autocomplete="off" />
    <ul id="suggest"></ul>
    </div>
    css
    #warpper{
    position
    :relative;
    }
    #search
    {
    width
    :400px;
    height
    :20px;
    }
    #suggest
    {
    position
    :absolute;
    top
    :30px;
    width
    :400px;
    max-height
    :400px;
    overflow
    :auto;
    display
    :none;
    border
    :1px solid #20815D;
    list-style
    :none;margin:0;padding:0;
    cursor
    :default;
    }
    .color
    {
    background-color
    :#BDF400;
    }
    li
    {
    margin
    :0;padding-left:5px;height:20px;
    }

    js部分:
    1.search的实现:
      通过该search可以实现其他的查询方式或查询其他的数据,只要把查询结果以数组形式赋给output即可。

      这里的search实现的是查找当前浏览器的对象和属性。

     1     // 查找函数,可以换成ajax请求服务器json
    2 // 这个search函数只是用来寻找当前浏览器下的全局对象和变量
    3 function search(val){
    4 // 触发查找的时候先隐藏掉suggest,里面已经不是想要的信息了
    5 ul.style.display = "none";
    6 // 清空输出数组,用来填充新数据
    7 output = [];
    8 var matchObj = val.split('.');//每一个点号都代表一次对象的属性查找
    9 if(matchObj.length>1){
    10 // 第一次搜索是从全局对象window开始
    11 var currentObj = window;
    12 for(var i = 0,len = matchObj.length; i < len; i++){
    13 //搜索window下的各级对象
    14 if(!currentObj[matchObj[i]]){
    15 break;
    16 }
    17 currentObj = currentObj[matchObj[i]];
    18 }
    19 var left = len - i;
    20 if(left===1){
    21 var rProp = new RegExp("^"+matchObj[i]);
    22 for(var prop in currentObj){
    23 if(rProp.test(prop)){
    24 matchObj[len-1] = prop;
    25 output.push(matchObj.join('.'));
    26 }
    27 }
    28 }else if(left===0){
    29 //正好匹配,其实可以不输出的。
    30 output.push(val);
    31 }
    32 }else{
    33 //搜索window下带val字符串开头的属性
    34 var rProp = new RegExp("^"+val);
    35 for(var prop in window){
    36 if(rProp.test(prop)){
    37 output.push(prop);
    38 }
    39 }
    40 }
    41 }

    2.inupt上的按键事件(查询数据,弹出suggest框,选择suggest条目,改变input值等):

     1     input.onkeyup = function(e){
    2 if(e.keyCode !== 38 && e.keyCode !==40){
    3 // 不是上下方向键,则进行搜索,这里的搜索函数可以自定义,或者写成ajax请求
    4 search(this.value);
    5 // 取得数据后就可以调用createBox()生成并显示suggest框了
    6 createBox();
    7 }
    8 }
    9 input.onkeydown = function(e){
    10 //toggleColor();切换选中项颜色
    11 //input.val = li.textcontent;
    12 // 上下方向键,进行createBox或者对选项切换颜色
    13 if(e.keyCode === 38 || e.keyCode ===40){
    14 // 如果是在suggest显示的状态下按上下方向键,那么改变高亮状态和修正位置
    15 if(ul.style.display==="block"){
    16 for(var i = 0,len = liSet.length; i<len;i++){
    17 if(liSet[i].className === 'color'){
    18 break;
    19 }
    20 }
    21 if(i===len){
    22 // 如果没有高亮状态,那么定义第一个高亮
    23 liSet[0].className = 'color';
    24 input.value = liSet[0].textContent;
    25 }else{
    26 // 取消当前高亮元素的高亮状态
    27 liSet[i].className = '';
    28
    29 if(e.keyCode === 40){//设置高亮,修正位置
    30 i = ++i%len;
    31 liSet[i].className = 'color';
    32 fixScrollPos(i);
    33 }else{//设置高亮,修正位置
    34 i = (--i+len)%len;
    35 liSet[i].className = 'color';
    36 e.preventDefault();//阻止光标默认操作,使得光标一直在右边
    37 fixScrollPos(i);
    38 }
    39 }
    40 // 按上下键的时候还没有显示suggest,那么此时显示出来,并且不设置高亮
    41 }else{
    42 if(output.length){
    43 // 删除高亮
    44 for(var i = 0,len = liSet.length; i<len;i++){
    45 liSet[i].className = '';
    46 }
    47 // 显示suggest
    48 ul.style.display = "block";
    49 }
    50 }
    51 }
    52 }

    3.绑定在ul上的事件(选中suggest条目,鼠标划过条目时高亮等)

     1     // 定义suggest的行为
    2 ul.onclick = function(e){
    3 // 单击li的时候添加对应的文字到input里
    4 if(e.target.nodeName.toLowerCase() === 'li') input.value = e.target.textContent;
    5 }
    6 ul.onmouseover = function(e){
    7 // 定义鼠标划过时suggest的高亮
    8 for(var i = 0,len = liSet.length; i<len;i++){
    9 liSet[i].className = '';
    10 }
    11 if(e.target.nodeName.toLowerCase() === 'li') e.target.className = 'color';
    12 }

    4.suggest的消失时机

    1     document.onclick = function(e){
    2 // 此处定义suggest何时消失,点击非input和ul下拉框则隐藏掉suggest
    3 if(e.target!==input&&e.target!==ul) ul.style.display = "none";
    4 }

    5.suggest条目过多显示滚动条时,对上下按键触发的滚动效果模拟(此时焦点在input需要另外对suggest可视区域位置进行修正)

     1     // 修正滚动条位置
    2 function fixScrollPos(pos){
    3 var sTop = ul.scrollTop;//先取得可视区的上边缘高
    4 var viewHeight = parseInt(document.defaultView.getComputedStyle(ul,null).height,10);//可视区的高度
    5 var sBottom = sTop + viewHeight;//可视区底部距离到ul顶部的高度
    6 var itemHeight = liSet[0].offsetHeight;//假设这里没有margin,如果有的话自己补上
    7 var liPos = pos*itemHeight;//当前li距离ul顶部的高度
    8
    9 if( liPos >= sBottom){//选中的li在可视区下
    10 ul.scrollTop = liPos - ( viewHeight - itemHeight );
    11 }else if( liPos < sTop){//选中的li在可视区上
    12 ul.scrollTop = liPos;
    13 }
    14 liSet[pos].className = 'color';
    15 input.value = liSet[pos].textContent;
    16 }

    基本介绍完了,更详细的可以看源代码:
      再次怒击链接下载实例

  • 相关阅读:
    第四次实践作业
    第三次实践作业
    第二次实践作业
    第一次实践作业
    第02组 Beta版本演示
    第02组 Beta冲刺(4/4)
    大数据应用技术课程实践--选题与实践方案
    15 手写数字识别-小数据集
    14 深度学习-卷积
    13 垃圾邮件分类2
  • 原文地址:https://www.cnblogs.com/chemandy/p/2356687.html
Copyright © 2011-2022 走看看