贡献个网址搜索提示框

  前段时间在找一个网址搜索提示的API,也没发现有公开的API。得,公开的没找到,找个没公开的吧。看看hao123、360等网址导航都有自定义网址,在添加网址时都有网址提示,打开浏览器调试工具,查看一下网络请求吧。

  先看hao123,假设搜索bokeyuan这几个字母,从网络监视里得到的请求url是http://nssug.baidu.com/su?cb=jQuery172002392077026888728_1403322091978 &prod=superpage &sc=hao123 &wd=bokeyuan &_=1403324515020

  把不需要的参数去掉,剩下的url是:http://nssug.baidu.com/su?wd=bokeyuan &prod=superpage。在浏览器中请求一下,返回的内容是window.baidu.sug({q:"bokeyuan", p:false, s:["博客园0{#S+_}[1928,\"http:\\/\\/www.cnblogs.com\\/\",1,1,\"\\u535a\\u5ba2\\u56ed\"]"]});。内容还是比较乱的,具体参数对应的含义也不是很清楚,用起来稳定性也不能得到保证。

  再看看360导航,搜索bokeyuan,得到的url是http://suggest.h.qhimg.com/index.php? biz=websitename &word=bokeyuan &fmt=jsonp &cnt=8 &cb=__jsonp14__ &t=2338874

  把多余的参数去掉,剩下的url是:http://suggest.h.qhimg.com/index.php? biz=websitename& word=bokeyuan& fmt=json。在浏览器中请求一下,返回的内容是["\u535a\u5ba2\u56ed,www.cnblogs.com"],这个就比hao123的简洁多了,直接返回一个json数组,每项都是被一个逗号隔开的网站名和网址,这个使用起来就方便的多了。

  从获取网站图标的方式到网址搜索提示API,可以看出hao123更注重数据的保护,请求流程及其繁琐,外人不宜用。而360导航就感觉比较直白,丝毫不对外隐藏什么,也比较适合外人使用。

  下边是用了360导航的网站搜索提示API并仿照360的网址添加样式的一个网站搜索提示框。试用一下,看看还有没有什么问题,存在bug请及时反馈给我。 

 

网站名称:
网址:

 

一. 实现过程  

  大概地介绍一下它的实现吧。html布局如下,css样式就不说了,可以自己查看一下。添加按钮和回车的事件是写在页面里的,也可以自己查看。

<div id="mysite">
        <div class="txt">网站名称:</div>
        <div class="site-input site-name">
            <input type="text" id="mysite-name-add" placeholder="如:Simple" />
        </div>
        <div class="txt txt-url">网址:</div>
        <div class="site-input site-url">
            <input type="text" id="mysite-url-add"
                placeholder="如:www.haosimple.com" />
        </div>
        <button onclick="add()" id="btn-site-add" >添加</button>
</div> 

  重点说一下提示功能,js提示的功能单独封装在了一个js文件中,注释都比较清楚,看起来比较简单。代码流程如下:

var hoverIndex = -1;
var ajaxDelay;

$(document)
        .ready(
                function() {
                    applyCSSAndEvent();
                    addSug();
                    var sugContainer = $(".mysite-suggest");

                    //监听文本框的按键抬起事件
                    $("#mysite-name-add,#mysite-url-add")
                            .keyup(
                                    function(event) {
                                        // 若上次间隔时间未到,先取消上次提交
                                        window.clearTimeout(ajaxDelay);
                                        
                                        var e = event || window.event;
                                        var keyCode = e.keyCode;
                                        // 数字字母退格删除空格
                                        if (keyCode >= 48
                                                && keyCode <= 57
                                                || (keyCode >= 65 && keyCode <= 90)
                                                || keyCode == 8
                                                || keyCode == 46
                                                || keyCode == 32) {

                                            // 获得搜索地址和搜索内容
                                            var word;
                                            var sugApiUrl;
                                            if ("mysite-name-add" == document.activeElement.id) {
                                                word = $("#mysite-name-add")
                                                        .val();
                                                sugApiUrl = "http://suggest.h.qhimg.com/index.php?biz=websitename&fmt=jsonp&word=";
                                            } else {
                                                word = $("#mysite-url-add")
                                                        .val();
                                                sugApiUrl = "http://suggest.h.qhimg.com/index.php?biz=websiteurl&fmt=jsonp&word=";
                                            }

                                            // 没有内容就没必要搜索了
                                            if (word.trim() == "") {
                                                clearSug();
                                                return;
                                            }

                                            // 500毫秒后进行搜索,500毫秒未到又触发了下次,本次搜索会被取消
                                            ajaxDelay = window.setTimeout(
                                                    'getSite("' + word + '","'
                                                            + sugApiUrl + '")',
                                                    400);
                                            return;
                                        }

                                        // 获得提示框中的项
                                        var sitelis = $(sugContainer).children(
                                                "li");
                                        // 响应向上键
                                        if (keyCode == 38 && sitelis.length > 0) {
                                            if (hoverIndex > 0) {
                                                hoverIndex--;
                                            } else {
                                                hoverIndex = sitelis.length - 1;
                                            }
                                            setContent($(sitelis)[hoverIndex]);
                                            changeHoverClass($(sitelis)[hoverIndex]);
                                        }
                                        // 响应向下键
                                        if (keyCode == 40 && sitelis.length > 0) {
                                            if (hoverIndex < sitelis.length - 1) {
                                                hoverIndex++;
                                            } else {
                                                hoverIndex = 0;
                                            }
                                            setContent($(sitelis)[hoverIndex]);
                                            changeHoverClass($(sitelis)[hoverIndex]);
                                        }
                                    });
                });

  第一步,先利用applyCSSAndEvent()函数加载css样式和绑定冒泡事件。样式主要是针对动态生成的提示框及提示项的样式,以这种方式设置css只需要加载一次即可,避免提示项改变重复设置css的做法。然后绑定mouseover事件,当鼠标扫过提示项时,要高亮显示。提示项的mousedown事件响应用户点击时将内容放置到文本框中。还绑定了文本框的键盘向上键事件,因为默认情况下在文本框中按向上键会使光标移到文字前边。如果不这样做的话,在按向上键切换提示项时,光标总会先到文本框前边然后再到文本框后边,体验不好。最后是绑定文本框失去焦点事件,清空并隐藏提示框。

function applyCSSAndEvent() {
    $(document.body)
            .append(
                    '<style type="text/css">.mysite-suggest{display:none;position:absolute;border:1px solid #707a86;background-color:#fff}.mysite-suggest li{overflow:hidden;height:30px;cursor:pointer}.mysite-suggest .sug-url,.mysite-suggest .sug-name{display:inline;overflow:hidden;float:left;padding-left:6px;font-size:14px;height:30px;line-height:30px;text-overflow:ellipsis;white-space:nowrap}.mysite-suggest .sug-url{margin-right:12px;width:206px}.mysite-suggest .sug-name{margin-right:80px;width:188px}.mysite-suggest .hover{background-color:#f2f8ff}</style>');

    $(document).on("mouseover", ".mysite-suggest li", function() {
        changeHoverClass(this);
    });
    $(document).on("mousedown", ".mysite-suggest li", function() {
        setContent(this);
    });
    $(document).on("keydown", "#mysite-name-add,#mysite-url-add", function(e) {
        if (e.keyCode == 38)// 将文本框向上键的响应取消
            return false;
    });
    // 当文本框失去焦点时隐藏提示框
    $(document).on("blur", "#mysite-name-add,#mysite-url-add", function() {
        clearSug();
    });
}
// 改变提示项的高亮属性
function changeHoverClass(li) {
    $(".mysite-suggest .hover").removeClass();
    $(li).addClass("hover");
}
// 设置网站名、网址文本框的内容
function setContent(li) {
    $("#mysite-name-add").val($(li).children(":first-child").text());
    $("#mysite-url-add").val($(li).children(":last-child").text());
}
// 清空提示框
function clearSug() {
    $(".mysite-suggest").html(" ");
    $(".mysite-suggest").hide();
}

  第二步,利用addSug()函数添加提示框,在body最后添加一个ul标签,设置其位置在文本框下边,并使其宽度覆盖两个文本框,代码如下:

function addSug() {
    var name_container = $(".site-name");
    var url_container = $(".site-url");
    var name_container_offset = name_container.offset();
    var url_container_offset = url_container.offset();
    $(document.body).append('<ul class="mysite-suggest"></ul>');
    $(".mysite-suggest").css("top",(name_container_offset.top + name_container.height())).css("left",
            name_container_offset.left).width(
            url_container_offset.left - name_container_offset.left
                    + url_container.width());
}

  最后,监听文本框的键盘键入事件,如果是数字字母空格删除退格按键,则根据在不同文本框键入的内容切换请求地址和搜索内容,因为网站名搜索和url搜索的API是不一样的。然后定义一个超时发送的ajax,超时时间为400ms。同时文本框还响应向上向下按键,根据选中的列表项替换文本框的内容。其中ajax请求的代码如下:

function getSite(word, sugApiUrl) {
    $.ajax({
        type : "get",
        url : sugApiUrl + word,
        dataType : "jsonp",// 数据类型为jsonp
        jsonp : "cb",// 服务端用于接收callback调用的function名的参数,360导航必须是cb
        jsonpCallback : "callback",// 不能采用默认的函数名,360导航对回调名称有限制
        success : function(data) {
            clearSug();// 先清除上一次的列表

            var sugContainer = $(".mysite-suggest");
            $(data).each(function() {
                sugContainer.append(generateSiteList(this));
            });
            // 当返回的数据长度大于0才显示
            if ($(sugContainer).children("li").length > 0) {
                sugContainer.show();
                hoverIndex = -1;
            }
        }
    });
}

  由于这是跨域名请求,所以需要用到jsonp请求方式,请求到内容之后,把内容加载到提示框中并显示。生成列表项的代码如下所示,构建了一个li标签,里边有两个div分别显示网站名和网址,其中css样式就是在开始时js加载过的样式。

function generateSiteList(data) {
    var name = data.split(',')[0];
    var url = data.split(',')[1];
    return '<li><div class="sug-name">' + name + '</div>    <div class="sug-url">'
            + url + '</div></li>';
}
posted @ 2014-06-21 16:41  luguo3000  阅读(1657)  评论(3编辑  收藏  举报