加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

iBase4j前端01_bootstrap-suggest json-server模拟后台数据、boo

发布时间:2020-12-17 20:50:41 所属栏目:安全 来源:网络整理
导读:? 1 准备 1.1 模拟的json数据 { "info": [ { "message": "信息","value": [ { "userName": "淳芸","shortAccount": "chunyun","userId": 20001 },{ "userName": "orion-01","userName": "orion-01","shortAccount": "orion-01","userId": 20000 },{ "userNam

?

1 准备

  1.1 模拟的json数据

{
    "info": [
        {
        "message": "信息","value": [
            {
                "userName": "淳芸","shortAccount": "chunyun","userId": 20001
            },{
                "userName": "orion-01","userName": "orion-01","shortAccount": "orion-01","userId": 20000
            },{
                "userName": "唐宏禹14","shortAccount": "TANGHONGYU","userId": 20011
            },{
                "userName": "唐宏禹13","shortAccount": "tanghongyu",{
                "userName": "穆晓晨","shortAccount": "mUXIAOCHEN","userId": 20002
            },{
                "userName": "张欢引","shortAccount": "zhanghuanyin","userId": 20003
            },{
                "userName": "吴琼","shortAccount": "wuqiong","userId": 20004
            },{
                "userName": "吴东鹏","shortAccount": "wudongpeng","userId": 20005
            },{
                "userName": "黄少铅","shortAccount": "huangshaoqian","userId": 20006
            },{
                "userName": "胡运燕","shortAccount": "yunyan","userId": 20007
            },{
                "userName": "刘幸","shortAccount": "liuxing","userId": 20008
            },{
                "userName": "陈媛媛","shortAccount": "CHENYUANYUAN","userId": 20009
            },{
                "userName": "李大鹏","shortAccount": "dapeng","userId": 20010
            },{
                "userName": "唐宏禹",{
                "userName": "旷东林","shortAccount": "kuangdonglin",{
                "userName": "唐宏禹15","shortAccount": "TANGhongyu",{
                "userName": "唐宏禹12",{
                "userName": "唐宏禹11","shortAccount": "TangHongYu",{
                "userName": "唐宏禹10",{
                "userName": "唐宏禹9",{
                "userName": "唐宏禹8",{
                "userName": "唐宏禹7",{
                "userName": "唐宏禹6",{
                "userName": "唐宏禹5",{
                "userName": "唐宏禹4",{
                "userName": "唐宏禹3",{
                "userName": "唐宏禹2",{
                "userName": "唐宏禹1","userId": 20011
            }
        ],"code": 200,"redirect": ""
    }]
}
data.json

  1.2 模拟后台服务

    利用json-server模拟后台,json-server使用详解

    进入到模拟数据所在文件夹,执行下面的语句

json-server 模拟数据文件 -p 启动端口

      例如:json-server data.json -p 8888

      启动效果如下:

    利用浏览器访问得到的响应如下:

?

2 下载相关依赖包

  2.1 jquery

    https://jquery.com/download/

?

  2.2 bootstrap

    https://v3.bootcss.com/

  2.3 bootstrap-suggest

    https://github.com/lzwme/bootstrap-suggest-plugin

?

3 编程步骤

  3.1 引入相关文件

    引入jquery、boostrap的css和js、引入bootstrap-suggest

  3.2 编写HTML代码

    技巧01:编写一个input和ul即可

    坑01:CSS类照着写,因为bootstrap-suggest依赖需要用到bootstrap相关的样式

  3.3 编写JS代码

  3.4 测试效果

  3.5 代码汇总

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Suggest使用案例</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">

<link rel="stylesheet" type="text/css" href="../css/common.css">

<!-- <link rel="stylesheet" type="text/css" href="../tool/bootstrap-3.3.7/dist/css/bootstrap-theme.min.css"> -->
<link rel="stylesheet" type="text/css" href="../tool/bootstrap-3.3.7/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="../tool/bootstrap-3.3.7/dist/css/bootstrap.css">

<script type="text/javascript" src="../tool/jquery/jquery-3.3.1.js"></script>
<script type="text/javascript" src="../tool/bootstrap-3.3.7/dist/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../tool/bootstrap-suggest-plugin/dist/bootstrap-suggest.min.js"></script>

<script type="text/javascript" src="../js/demo01_suggest.js"></script>

</head>
<body>
    <div class="panel panel-primary">
        <div class="panel-heading">测试</div>
        <div class="panel-body">
            <div class="input-group">
                <input type="text" class="form-control" id="modalTest_input" autocomplete="off">
                <div class="input-group-btn">
                    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="">
                        <span class="caret"></span>
                    </button>
                    <ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>
                </div>
            </div>
        </div>
        <div class="panel-footer">
            <span id="Timer"></span>
        </div>
    </div>
    <hr class="hr">

</body>
</html>
suggest.html

$().ready(function() {

    $("#modalTest_input").bsSuggest({
            url: " http://localhost:8888/info",allowNoKeyword: true,// 是否允许非关键字搜索【默认true】
            showHeader: true,// 是否显示表头【默认true】
            clearable: true,// 是否开启清空数据【默认false】
            showBtn: true,// 是否显示下拉按钮【默认false】
            multiWord: true,//以分隔符号分割的多关键字支持 
            separator: ",",//多关键字支持时的分隔符 
            getDataMethod: ‘url‘,// 请求url
            effectiveFields: ["userName","userId","shortAccount"],// 显示的字段
            effectiveFieldsAlias:{userName: "姓名",userId: "用户ID",shortAccount: "账号"},// 字段标题
            idField: "userId",// id字段
            keyField: "userName",// input元素中的显示字段
            fnPreprocessKeyword: function(keyword) { //请求数据前,对输入关键字作进一步处理方法。注意,应返回字符串
                // alert("搜索关键字:" + keyword);
                return keyword;
            },fnProcessData: function (result) {    // url 获取数据时,对数据的处理,作为 fnGetData 的回调函数
            var index,len,data = {value: []};
            var json = result[0];

            // 判断是否有响应数据
            if (!json || !json.value || json.value.length === 0) {
                console.log("没有数据");
                return false;
            }
            len = json.value.length;
            // 将获取到的数据放到data.value中
            for (index = 0; index < len; index++) {
                data.value.push(json.value[index]);
            }
            //字符串转化为 js 对象 【只要获取到数据】
            return data;
        }
        }).on(‘onDataRequestSuccess‘,function (e,result) {
            console.log(‘onDataRequestSuccess: ‘,result);
        }).on(‘onSetSelectValue‘,keyword,data) {
            console.log("选择一个过后:");
            console.log(‘onSetSelectValue: ‘,data);
        }).on(‘onUnsetSelectValue‘,function () {
            console.log(‘onUnsetSelectValue‘);
        }).on(‘onShowDropdown‘,data) {
            console.log(‘onShowDropdown‘,e.target.value,data);
        }).on(‘onHideDropdown‘,data) {
            console.log(‘onHideDropdown‘,data);
        });

    // 每间隔一秒刷新时间
    setInterval("gettime()",1000);

    //获取时间并设置格式
    gettime = function GetTime() {
        var mon,day,now,hour,min,ampm,time,str,tz,end,beg,sec;
        /*
        mon = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
        */
        mon = new Array("一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月");
        /*
        day = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
        */
        day = new Array("周日","周一","周二","周三","周四","周五","周六");
        now = new Date();
        hour = now.getHours();
        min = now.getMinutes();
        sec = now.getSeconds();
        if (hour < 10) {
            hour = "0" + hour;
        }
        if (min < 10) {
            min = "0" + min;
        }
        if (sec < 10) {
            sec = "0" + sec;
        }
        $("#Timer").html(
            now.getFullYear() + "年" + (now.getMonth() + 1) + "月" + now.getDate() + "日" + "  " + hour + ":" + min + ":" + sec
            );
    }
    
})
suggest.js

?

4 bootstrap-suggest进阶

  4.1 原有bug

    原来的bootstrap-suggest框架仅仅支持get请求

  4.2 需求

    需要进行put或者post请求,而且还需要向后台传值

  4.3 修改bootstrap-suggeest的源代码

    技巧01:bootstrap-suggest中有一个ajax方法,该方法接收两个参数

      参数一 -> options -> 就是我们在自定义js文件对bootstrap-suggest的一些配置信息

      参数二 -> keyword -> 就是input标签中输入的值

/**
 * Bootstrap Search Suggest
 * @desc    这是一个基于 bootstrap 按钮式下拉菜单组件的搜索建议插件,必须使用于按钮式下拉菜单组件上。
 * @author  renxia <lzwy0820#qq.com>
 * @github  https://github.com/lzwme/bootstrap-suggest-plugin.git
 * @since   2014-10-09
 *===============================================================================
 * (c) Copyright 2014-2016 http://lzw.me All Rights Reserved.
 ********************************************************************************/
(function (factory) {
    if (typeof define === "function" && define.amd) {
        define([‘jquery‘],factory);
    } else if (typeof exports === ‘object‘ && typeof module === ‘object‘) {
        factory(require(‘jquery‘));
    } else if (window.jQuery) {
        factory(window.jQuery);
    } else {
        throw new Error(‘Not found jQuery.‘);
    }
})(function($) {
    var VERSION = ‘VERSION_PLACEHOLDER‘;
    var $window = $(window);
    var isIe = ‘ActiveXObject‘ in window; // 用于对 IE 的兼容判断
    var inputLock; // 用于中文输入法输入时锁定搜索

    // ie 下和 chrome 51 以上浏览器版本,出现滚动条时不计算 padding
    var chromeVer = navigator.userAgent.match(/Chrome/(d+)/);
    if (chromeVer) {
        chromeVer = +chromeVer[1];
    }
    var notNeedCalcPadding = isIe || chromeVer > 51;

    // 一些常量
    var BSSUGGEST = ‘bsSuggest‘;
    var onDataRequestSuccess = ‘onDataRequestSuccess‘;
    var DISABLED = ‘disabled‘;
    var TRUE = true;
    var FALSE = false;

    /**
     * 错误处理
     */
    function handleError(e1,e2) {
        if (!window.console || !window.console.trace) {
            return;
        }
        console.trace(e1);
        if (e2) {
            console.trace(e2);
        }
    }
    /**
     * 获取当前 tr 列的关键字数据
     */
    function getPointKeyword($list) {
        return $list.data();
    }
    /**
     * 设置或获取输入框的 alt 值
     */
    function setOrGetAlt($input,val) {
        return val !== undefined ? $input.attr(‘alt‘,val) : $input.attr(‘alt‘);
    }
    /**
     * 设置或获取输入框的 data-id 值
     */
    function setOrGetDataId($input,val) {
        return val !== (void 0) ? $input.attr(‘data-id‘,val) : $input.attr(‘data-id‘);
    }
    /**
     * 设置选中的值
     */
    function setValue($input,keywords,options) {
        if (!keywords || !keywords.key) {
            return;
        }

        var separator = options.separator || ‘,‘,inputValList,inputIdList,dataId = setOrGetDataId($input);

        if (options && options.multiWord) {
            inputValList = $input.val().split(separator);
            inputValList[inputValList.length - 1] = keywords.key;

            //多关键字检索支持设置id --- 存在 bug,不建议使用
            if (!dataId) {
                inputIdList = [keywords.id];
            } else {
                inputIdList = dataId.split(separator);
                inputIdList.push(keywords.id);
            }

            setOrGetDataId($input,inputIdList.join(separator))
                .val(inputValList.join(separator))
                .focus();
        } else {
            setOrGetDataId($input,keywords.id || ‘‘).val(keywords.key).focus();
        }

        $input.data(‘pre-val‘,$input.val())
            .trigger(‘onSetSelectValue‘,[keywords,(options.data.value || options._lastData.value)[keywords.index]]);
    }
    /**
     * 调整选择菜单位置
     * @param {Object} $input
     * @param {Object} $dropdownMenu
     * @param {Object} options
     */
    function adjustDropMenuPos($input,$dropdownMenu,options) {
        if (!$dropdownMenu.is(‘:visible‘)) {
            return;
        }

        var $parent = $input.parent();
        var parentHeight = $parent.height();
        var parentWidth = $parent.width();

        if (options.autoDropup) {
            setTimeout(function() {
                var offsetTop = $input.offset().top;
                var winScrollTop = $window.scrollTop();
                var menuHeight = $dropdownMenu.height();

                if ( // 自动判断菜单向上展开
                    ($window.height() + winScrollTop - offsetTop) < menuHeight && // 假如向下会撑长页面
                    offsetTop > (menuHeight + winScrollTop) // 而且向上不会撑到顶部
                ) {
                    $parent.addClass(‘dropup‘);
                } else {
                    $parent.removeClass(‘dropup‘);
                }
            },10);
        }

        // 列表对齐方式
        var dmcss = {};
        if (options.listAlign === ‘left‘) {
            dmcss = {
                ‘left‘: $input.siblings(‘div‘).width() - parentWidth,‘right‘: ‘auto‘
            };
        } else if (options.listAlign === ‘right‘) {
            dmcss = {
                ‘left‘: ‘auto‘,‘right‘: 0
            };
        }

        // ie 下,不显示按钮时的 top/bottom
        if (isIe && !options.showBtn) {
            if (!$parent.hasClass(‘dropup‘)) {
                dmcss.top = parentHeight;
                dmcss.bottom = ‘auto‘;
            } else {
                dmcss.top = ‘auto‘;
                dmcss.bottom = parentHeight;
            }
        }

        // 是否自动最小宽度
        if (!options.autoMinWidth) {
            dmcss.minWidth = parentWidth;
        }
        /* else {
            dmcss[‘width‘] = ‘auto‘;
        }*/

        $dropdownMenu.css(dmcss);

        return $input;
    }
    /**
     * 设置输入框背景色
     * 当设置了 indexId,而输入框的 data-id 为空时,输入框加载警告色
     */
    function setBackground($input,options) {
        var inputbg,bg,warnbg;
        if ((options.indexId === -1 && !options.idField) || options.multiWord) {
            return $input;
        }

        bg = options.inputBgColor;
        warnbg = options.inputWarnColor;

        var curVal = $input.val();
        var preVal = $input.data(‘pre-val‘);

        if (setOrGetDataId($input) || !curVal) {
            $input.css(‘background‘,bg || ‘‘);

            if (!curVal && preVal) {
                $input.trigger(‘onUnsetSelectValue‘).data(‘pre-val‘,‘‘);
            }

            return $input;
        }

        inputbg = $input.css(‘backgroundColor‘).replace(/ /g,‘‘).split(‘,‘,3).join(‘,‘);
        // 自由输入的内容,设置背景色
        if (!~warnbg.indexOf(inputbg)) {
            $input.trigger(‘onUnsetSelectValue‘) // 触发取消data-id事件
                .data(‘pre-val‘,‘‘)
                .css(‘background‘,warnbg);
        }

        return $input;
    }
    /**
     * 调整滑动条
     */
    function adjustScroll($input,options) {
        // 控制滑动条
        var $hover = $input.parent().find(‘tbody tr.‘ + options.listHoverCSS),pos,maxHeight;

        if ($hover.length) {
            pos = ($hover.index() + 3) * $hover.height();
            maxHeight = +$dropdownMenu.css(‘maxHeight‘).replace(‘px‘,‘‘);

            if (pos > maxHeight || $dropdownMenu.scrollTop() > maxHeight) {
                pos = pos - maxHeight;
            } else {
                pos = 0;
            }

            $dropdownMenu.scrollTop(pos);
        }
    }
    /**
     * 解除所有列表 hover 样式
     */
    function unHoverAll($dropdownMenu,options) {
        $dropdownMenu.find(‘tr.‘ + options.listHoverCSS).removeClass(options.listHoverCSS);
    }
    /**
     * 验证 $input 对象是否符合条件
     *   1. 必须为 bootstrap 下拉式菜单
     *   2. 必须未初始化过
     */
    function checkInput($input,options) {
        if (
            !$dropdownMenu.length || // 过滤非 bootstrap 下拉式菜单对象
            $input.data(BSSUGGEST) // 是否已经初始化的检测
        ) {
            return FALSE;
        }

        $input.data(BSSUGGEST,{
            options: options
        });

        return TRUE;
    }
    /**
     * 数据格式检测
     * 检测 ajax 返回成功数据或 data 参数数据是否有效
     * data 格式:{"value": [{},{}...]}
     */
    function checkData(data) {
        var isEmpty = TRUE,o;

        for (o in data) {
            if (o === ‘value‘) {
                isEmpty = FALSE;
                break;
            }
        }
        if (isEmpty) {
            handleError(‘返回数据格式错误!‘);
            return FALSE;
        }
        if (!data.value.length) {
            // handleError(‘返回数据为空!‘);
            return FALSE;
        }

        return data;
    }
    /**
     * 判断字段名是否在 options.effectiveFields 配置项中
     * @param  {String} field   要判断的字段名
     * @param  {Object} options
     * @return {Boolean}        effectiveFields 为空时始终返回 true
     */
    function inEffectiveFields(field,options) {
        var effectiveFields = options.effectiveFields;

        return !(field === ‘__index‘ ||
            effectiveFields.length &&
            !~$.inArray(field,effectiveFields));
    }
    /**
     * 判断字段名是否在 options.searchFields 搜索字段配置中
     */
    function inSearchFields(field,options) {
        return ~$.inArray(field,options.searchFields);
    }
    /**
     * 通过下拉菜单显示提示文案
     */
    function showTip(tip,$input,options) {
        $dropdownMenu.html(‘<div style="padding:10px 5px 5px">‘ + tip + ‘</div>‘).show();
        adjustDropMenuPos($input,options);
    }
    /**
     * 下拉列表刷新
     * 作为 fnGetData 的 callback 函数调用
     */
    function refreshDropMenu($input,data,options) {
        var $dropdownMenu = $input.parent().find(‘ul:eq(0)‘),i,field,index = 0,tds,html = [‘<table class="table table-condensed table-sm" style="margin:0">‘],idValue,keyValue; // 作为输入框 data-id 和内容的字段值
        var dataList = data.value;

        if (!data || !dataList || !(len = dataList.length)) {
            if (options.emptyTip) {
                showTip(options.emptyTip,options);
            } else {
                $dropdownMenu.empty().hide();
            }
            return $input;
        }

        // 相同数据,不用继续渲染了
        if (
            options._lastData &&
            JSON.stringify(options._lastData) === JSON.stringify(data) &&
            $dropdownMenu.find(‘tr‘).length === len
        ) {
            $dropdownMenu.show();
            return adjustDropMenuPos($input,options);
            // return $input;
        }
        options._lastData = data;

        // 生成表头
        if (options.showHeader) {
            html.push(‘<thead><tr>‘);
            for (field in dataList[0]) {
                if (!inEffectiveFields(field,options)) {
                    continue;
                }

                html.push(‘<th>‘,(options.effectiveFieldsAlias[field] || field),index === 0 ? (‘(‘ + len + ‘)‘) : ‘‘,// 表头第一列记录总数
                    ‘</th>‘);

                index++;
            }
            html.push(‘</tr></thead>‘);
        }
        html.push(‘<tbody>‘);

        // console.log(data,len);
        // 按列加数据
        var dataI;
        for (i = 0; i < len; i++) {
            index = 0;
            tds = [];
            dataI = dataList[i];
            idValue = dataI[options.idField] || ‘‘;
            keyValue = dataI[options.keyField] || ‘‘;

            for (field in dataI) {
                // 标记作为 value 和 作为 id 的值
                if (!keyValue && options.indexKey === index) {
                    keyValue = dataI[field];
                }
                if (!idValue && options.indexId === index) {
                    idValue = dataI[field];
                }

                index++;

                // 列表中只显示有效的字段
                if (inEffectiveFields(field,options)) {
                    tds.push(‘<td data-name="‘,‘">‘,dataI[field],‘</td>‘);
                }
            }

            html.push(‘<tr data-index="‘,(dataI.__index || i),‘" data-id="‘,‘" data-key="‘,keyValue,‘">‘,tds.join(‘‘),‘</tr>‘);
        }
        html.push(‘</tbody></table>‘);

        $dropdownMenu.html(html.join(‘‘)).show();

        // scrollbar 存在时,延时到动画结束时调整 padding
        setTimeout(function() {
            if (notNeedCalcPadding) {
                return;
            }

            var $table = $dropdownMenu.find(‘table:eq(0)‘),pdr = 0,mgb = 0;

            if (
                $dropdownMenu.height() < $table.height() &&
                +$dropdownMenu.css(‘minWidth‘).replace(‘px‘,‘‘) < $dropdownMenu.width()
            ) {
                pdr = 18;
                mgb = 20;
            }

            $dropdownMenu.css(‘paddingRight‘,pdr);
            $table.css(‘marginBottom‘,mgb);
        },301);

        adjustDropMenuPos($input,options);

        return $input;
    }
    /**
     * ajax 获取数据
     * @param  {Object} options 就是自定义js文件的一些配置参数 keyword 就是搜索关键字母
     * @return {Object}   
     */
    function ajax(options,keyword) {
        keyword = keyword || ‘‘;
        // console.log(options); // 打印信息
        var preAjax = options._preAjax;

        if (preAjax && preAjax.abort && preAjax.readyState !== 4) {
            // console.log(‘abort pre ajax‘);
            preAjax.abort();
        }
        
        // 指定了非GET请求方式
        var type = options.type;
        if (type && type !=‘GET‘ && type != ‘get‘) {
            if(options.param.keyword){
                options.param.keyword = keyword;
            }else{
                options.param[‘keyword‘] = keyword;
            }
            
            var ajaxParam = {
                type: type,dataType: options.jsonp ? ‘jsonp‘ : ‘json‘,timeout: 5000,data: JSON.stringify(options.param)
            };
        } else {
            var ajaxParam = {
                type: ‘GET‘,};
        }

        // jsonp
        if (options.jsonp) {
            ajaxParam.jsonp = options.jsonp;
        }

        // 自定义 ajax 请求参数生成方法
        var adjustAjaxParam,fnAdjustAjaxParam = options.fnAdjustAjaxParam;

        if ($.isFunction(fnAdjustAjaxParam)) {
            adjustAjaxParam = fnAdjustAjaxParam(keyword,options);

            // options.fnAdjustAjaxParam 返回false,则终止 ajax 请求
            if (FALSE === adjustAjaxParam) {
                return;
            }

            $.extend(ajaxParam,adjustAjaxParam);
        }

        // url 调整
        ajaxParam.url = function() {
            if (!keyword || ajaxParam.data) {
                return ajaxParam.url || options.url;
            }

            var type = ‘?‘;
            if (/=$/.test(options.url)) {
                type = ‘‘;
            } else if (/?/.test(options.url)) {
                type = ‘&‘;
            }

            return options.url + type + encodeURIComponent(keyword);
        }();

        return options._preAjax = $.ajax(ajaxParam).done(function(result) {
            options.data = options.fnProcessData(result);
        }).fail(function(err) {
            if (options.fnAjaxFail) {
                options.fnAjaxFail(err,options);
            }
        });
    }
    /**
     * 检测 keyword 与 value 是否存在互相包含
     * @param  {String}  keyword 用户输入的关键字
     * @param  {String}  key     匹配字段的 key
     * @param  {String}  value   key 字段对应的值
     * @param  {Object}  options
     * @return {Boolean}         包含/不包含
     */
    function isInWord(keyword,key,value,options) {
        value = $.trim(value);

        if (options.ignorecase) {
            keyword = keyword.toLocaleLowerCase();
            value = value.toLocaleLowerCase();
        }

        return value &&
            (inEffectiveFields(key,options) || inSearchFields(key,options)) && // 必须在有效的搜索字段中
            (
                ~value.indexOf(keyword) || // 匹配值包含关键字
                options.twoWayMatch && ~keyword.indexOf(value) // 关键字包含匹配值
            );
    }
    /**
     * 通过 ajax 或 json 参数获取数据
     */
    function getData(keyword,callback,options) {
        var data,validData,filterData = {
                value: []
            },fnPreprocessKeyword = options.fnPreprocessKeyword;

        keyword = keyword || ‘‘;
        // 获取数据前对关键字预处理方法
        if ($.isFunction(fnPreprocessKeyword)) {
            keyword = fnPreprocessKeyword(keyword,options);
        }

        // 给了url参数,则从服务器 ajax 请求
        // console.log(options.url + keyword);
        if (options.url) {
            var timer;
            if (options.searchingTip) {
                timer = setTimeout(function() {
                    showTip(options.searchingTip,$input.parent().find(‘ul‘),options);
                },600);
            }

            ajax(options,keyword).done(function(result) {
                callback($input,options.data,options); // 为 refreshDropMenu
                $input.trigger(onDataRequestSuccess,result);
                if (options.getDataMethod === ‘firstByUrl‘) {
                    options.url = null;
                }
            }).always(function() {
                timer && clearTimeout(timer);
            });
        } else {
            // 没有给出 url 参数,则从 data 参数获取
            data = options.data;
            validData = checkData(data);
            // 本地的 data 数据,则在本地过滤
            if (validData) {
                if (keyword) {
                    // 输入不为空时则进行匹配
                    len = data.value.length;
                    for (i = 0; i < len; i++) {
                        for (key in data.value[i]) {
                            if (
                                data.value[i][key] &&
                                isInWord(keyword,data.value[i][key] + ‘‘,options)
                            ) {
                                filterData.value.push(data.value[i]);
                                filterData.value[filterData.value.length - 1].__index = i;
                                break;
                            }
                        }
                    }
                } else {
                    filterData = data;
                }
            }

            callback($input,filterData,options);
        } // else
    }
    /**
     * 数据处理
     * url 获取数据时,对数据的处理,作为 fnGetData 之后的回调处理
     */
    function processData(data) {
        return checkData(data);
    }
    /**
     * 取得 clearable 清除按钮
     */
    function getIClear($input,options) {
        var $iClear = $input.prev(‘i.clearable‘);

        // 是否可清除已输入的内容(添加清除按钮)
        if (options.clearable && !$iClear.length) {
                $iClear = $(‘<i class="clearable glyphicon glyphicon-remove"></i>‘)
                    .prependTo($input.parent());
        }

        return $iClear.css({
            position: ‘absolute‘,top: 12,// right: options.showBtn ? Math.max($input.next(‘.input-group-btn‘).width(),33) + 2 : 12,
            zIndex: 4,cursor: ‘pointer‘,fontSize: 12
        }).hide();
    }
    /**
     * 默认的配置选项
     * @type {Object}
     */
    var defaultOptions = {
        url: null,// 请求数据的 URL 地址
        jsonp: null,// 设置此参数名,将开启jsonp功能,否则使用json数据结构
        data: {
            value: []
        },// 提示所用的数据,注意格式
        indexId: 0,// 每组数据的第几个数据,作为input输入框的 data-id,设为 -1 且 idField 为空则不设置此值
        indexKey: 0,// 每组数据的第几个数据,作为input输入框的内容
        idField: ‘‘,// 每组数据的哪个字段作为 data-id,优先级高于 indexId 设置(推荐)
        keyField: ‘‘,// 每组数据的哪个字段作为输入框内容,优先级高于 indexKey 设置(推荐)

        /* 搜索相关 */
        autoSelect: TRUE,// 键盘向上/下方向键时,是否自动选择值
        allowNoKeyword: TRUE,// 是否允许无关键字时请求数据
        getDataMethod: ‘firstByUrl‘,// 获取数据的方式,url:一直从url请求;data:从 options.data 获取;firstByUrl:第一次从Url获取全部数据,之后从options.data获取
        delayUntilKeyup: FALSE,// 获取数据的方式 为 firstByUrl 时,是否延迟到有输入时才请求数据
        ignorecase: FALSE,// 前端搜索匹配时,是否忽略大小写
        effectiveFields: [],// 有效显示于列表中的字段,非有效字段都会过滤,默认全部有效。
        effectiveFieldsAlias: {},// 有效字段的别名对象,用于 header 的显示
        searchFields: [],// 有效搜索字段,从前端搜索过滤数据时使用,但不一定显示在列表中。effectiveFields 配置字段也会用于搜索过滤
        twoWayMatch: TRUE,// 是否双向匹配搜索。为 true 即输入关键字包含或包含于匹配字段均认为匹配成功,为 false 则输入关键字包含于匹配字段认为匹配成功
        multiWord: FALSE,// 以分隔符号分割的多关键字支持
        separator: ‘,// 多关键字支持时的分隔符,默认为半角逗号
        delay: 300,// 搜索触发的延时时间间隔,单位毫秒
        emptyTip: ‘‘,// 查询为空时显示的内容,可为 html
        searchingTip: ‘搜索中...‘,// ajax 搜索时显示的提示内容,当搜索时间较长时给出正在搜索的提示

        /* UI */
        autoDropup: FALSE,// 选择菜单是否自动判断向上展开。设为 true,则当下拉菜单高度超过窗体,且向上方向不会被窗体覆盖,则选择菜单向上弹出
        autoMinWidth: FALSE,// 是否自动最小宽度,设为 false 则最小宽度不小于输入框宽度
        showHeader: FALSE,// 是否显示选择列表的 header。为 true 时,有效字段大于一列则显示表头
        showBtn: TRUE,// 是否显示下拉按钮
        inputBgColor: ‘‘,// 输入框背景色,当与容器背景色不同时,可能需要该项的配置
        inputWarnColor: ‘rgba(255,.1)‘,// 输入框内容不是下拉列表选择时的警告色
        listStyle: {
            ‘padding-top‘: 0,‘max-height‘: ‘375px‘,‘max-width‘: ‘800px‘,‘overflow‘: ‘auto‘,‘width‘: ‘auto‘,‘transition‘: ‘0.3s‘,‘-webkit-transition‘: ‘0.3s‘,‘-moz-transition‘: ‘0.3s‘,‘-o-transition‘: ‘0.3s‘
        },// 列表的样式控制
        listAlign: ‘left‘,// 提示列表对齐位置,left/right/auto
        listHoverStyle: ‘background: #07d; color:#fff‘,// 提示框列表鼠标悬浮的样式
        listHoverCSS: ‘jhover‘,// 提示框列表鼠标悬浮的样式名称
        clearable: FALSE,// 是否可清除已输入的内容

        /* key */
        keyLeft: 37,// 向左方向键,不同的操作系统可能会有差别,则自行定义
        keyUp: 38,// 向上方向键
        keyRight: 39,// 向右方向键
        keyDown: 40,// 向下方向键
        keyEnter: 13,// 回车键

        /* methods */
        fnProcessData: processData,// 格式化数据的方法,返回数据格式参考 data 参数
        fnGetData: getData,// 获取数据的方法,无特殊需求一般不作设置
        fnAdjustAjaxParam: null,// 调整 ajax 请求参数方法,用于更多的请求配置需求。如对请求关键字作进一步处理、修改超时时间等
        fnPreprocessKeyword: null,// 搜索过滤数据前,对输入关键字作进一步处理方法。注意,应返回字符串
        fnAjaxFail: null,// ajax 失败时回调方法
    };

    var methods = {
        init: function(options) {
            // 参数设置
            var self = this;
            options = options || {};

            // 默认配置有效显示字段多于一个,则显示列表表头,否则不显示
            if (undefined === options.showHeader && options.effectiveFields && options.effectiveFields.length > 1) {
                options.showHeader = TRUE;
            }

            options = $.extend(TRUE,{},defaultOptions,options);

            // 旧的方法兼容
            if (options.processData) {
                options.fnProcessData = options.processData;
            }

            if (options.getData) {
                options.fnGetData = options.getData;
            }

            if (options.getDataMethod === ‘firstByUrl‘ && options.url && !options.delayUntilKeyup) {
                ajax(options).done(function(result) {
                    options.url = null;
                    self.trigger(onDataRequestSuccess,result);
                });
            }

            // 鼠标滑动到条目样式
            if (!$(‘#‘ + BSSUGGEST).length) {
                $(‘head:eq(0)‘).append(‘<style id="‘ + BSSUGGEST + ‘">.‘ + options.listHoverCSS + ‘{‘ + options.listHoverStyle + ‘}</style>‘);
            }

            return self.each(function() {
                var $input = $(this),$parent = $input.parent(),$iClear = getIClear($input,options),isMouseenterMenu,keyupTimer,// keyup 与 input 事件延时定时器
                    $dropdownMenu = $parent.find(‘ul:eq(0)‘);

                // 验证输入框对象是否符合条件
                if (!checkInput($input,options)) {
                    console.warn(‘不是一个标准的 bootstrap 下拉式菜单或已初始化:‘,$input);
                    return;
                }

                // 是否显示 button 按钮
                if (!options.showBtn) {
                    $input.css(‘borderRadius‘,4);
                    $parent.css(‘width‘,‘100%‘)
                        .find(‘.btn:eq(0)‘).hide();
                }

                // 移除 disabled 类,并禁用自动完成
                $input.removeClass(DISABLED).prop(DISABLED,FALSE).attr(‘autocomplete‘,‘off‘);
                // dropdown-menu 增加修饰
                $dropdownMenu.css(options.listStyle);

                // 默认背景色
                if (!options.inputBgColor) {
                    options.inputBgColor = $input.css(‘backgroundColor‘);
                }

                // 开始事件处理
                $input.on(‘keydown‘,function(event) {
                    var currentList,tipsKeyword; // 提示列表上被选中的关键字

                    // 当提示层显示时才对键盘事件处理
                    if (!$dropdownMenu.is(‘:visible‘)) {
                        setOrGetDataId($input,‘‘);
                        return;
                    }

                    currentList = $dropdownMenu.find(‘.‘ + options.listHoverCSS);
                    tipsKeyword = ‘‘; // 提示列表上被选中的关键字

                    unHoverAll($dropdownMenu,options);

                    if (event.keyCode === options.keyDown) { // 如果按的是向下方向键
                        if (!currentList.length) {
                            // 如果提示列表没有一个被选中,则将列表第一个选中
                            tipsKeyword = getPointKeyword($dropdownMenu.find(‘tbody tr:first‘).mouSEOver());
                        } else if (!currentList.next().length) {
                            // 如果是最后一个被选中,则取消选中,即可认为是输入框被选中,并恢复输入的值
                            if (options.autoSelect) {
                                setOrGetDataId($input,‘‘).val(setOrGetAlt($input));
                            }
                        } else {
                            // 选中下一行
                            tipsKeyword = getPointKeyword(currentList.next().mouSEOver());
                        }
                        // 控制滑动条
                        adjustScroll($input,options);

                        if (!options.autoSelect) {
                            return;
                        }
                    } else if (event.keyCode === options.keyUp) { // 如果按的是向上方向键
                        if (!currentList.length) {
                            tipsKeyword = getPointKeyword($dropdownMenu.find(‘tbody tr:last‘).mouSEOver());
                        } else if (!currentList.prev().length) {
                            if (options.autoSelect) {
                                setOrGetDataId($input,‘‘).val(setOrGetAlt($input));
                            }
                        } else {
                            // 选中前一行
                            tipsKeyword = getPointKeyword(currentList.prev().mouSEOver());
                        }

                        // 控制滑动条
                        adjustScroll($input,options);

                        if (!options.autoSelect) {
                            return;
                        }
                    } else if (event.keyCode === options.keyEnter) {
                        tipsKeyword = getPointKeyword(currentList);
                        $dropdownMenu.hide(); // .empty();
                    } else {
                        setOrGetDataId($input,‘‘);
                    }

                    // 设置值 tipsKeyword
                    // console.log(tipsKeyword);
                    setValue($input,tipsKeyword,options);
                }).on(‘compositionstart‘,function(event) {
                    // 中文输入开始,锁定
                    // console.log(‘compositionstart‘);
                    inputLock = TRUE;
                }).on(‘compositionend‘,function(event) {
                    // 中文输入结束,解除锁定
                    // console.log(‘compositionend‘);
                    inputLock = FALSE;
                }).on(‘keyup input paste‘,function(event) {
                    var word;

                    if (event.keyCode) {
                        setBackground($input,options);
                    }

                    // 如果弹起的键是回车、向上或向下方向键则返回
                    if (~$.inArray(event.keyCode,[options.keyDown,options.keyUp,options.keyEnter])) {
                        $input.val($input.val()); // 让鼠标输入跳到最后
                        return;
                    }

                    clearTimeout(keyupTimer);
                    keyupTimer = setTimeout(function() {
                        // console.log(‘input keyup‘,event);

                        // 锁定状态,返回
                        if (inputLock) {
                            return;
                        }

                        word = $input.val();

                        // 若输入框值没有改变则返回
                        if ($.trim(word) && word === setOrGetAlt($input)) {
                            return;
                        }

                        // 当按下键之前记录输入框值,以方便查看键弹起时值有没有变
                        setOrGetAlt($input,word);

                        if (options.multiWord) {
                            word = word.split(options.separator).reverse()[0];
                        }

                        // 是否允许空数据查询
                        if (!word.length && !options.allowNoKeyword) {
                            return;
                        }

                        options.fnGetData($.trim(word),refreshDropMenu,options);
                    },options.delay || 300);
                }).on(‘focus‘,function() {
                    // console.log(‘input focus‘);
                    adjustDropMenuPos($input,options);
                }).on(‘blur‘,function() {
                    if (!isMouseenterMenu) { // 不是进入下拉列表状态,则隐藏列表
                        $dropdownMenu.css(‘display‘,‘‘);
                    }
                }).on(‘click‘,function() {
                    // console.log(‘input click‘);
                    var word = $input.val();

                    if (
                        $.trim(word) &&
                        word === setOrGetAlt($input) &&
                        $dropdownMenu.find(‘table tr‘).length
                    ) {
                        return $dropdownMenu.show();
                    }

                    // if ($dropdownMenu.css(‘display‘) !== ‘none‘) {
                    if ($dropdownMenu.is(‘:visible‘)) {
                        return;
                    }

                    if (options.multiWord) {
                        word = word.split(options.separator).reverse()[0];
                    }

                    // 是否允许空数据查询
                    if (!word.length && !options.allowNoKeyword) {
                        return;
                    }

                    // console.log(‘word‘,word);
                    options.fnGetData($.trim(word),options);
                });

                // 下拉按钮点击时
                $parent.find(‘.btn:eq(0)‘).attr(‘data-toggle‘,‘‘).click(function() {
                    var display = ‘none‘;

                    // if ($dropdownMenu.is(‘:visible‘)) {
                    if ($dropdownMenu.css(‘display‘) === display) {
                        display = ‘block‘;
                        if (options.url) {
                            $input.click().focus();
                            if (!$dropdownMenu.find(‘tr‘).length) {
                                display = ‘none‘;
                            }
                        } else {
                            // 不以 keyword 作为过滤,展示所有的数据
                            refreshDropMenu($input,options);
                        }
                    }

                    $dropdownMenu.css(‘display‘,display);
                    return FALSE;
                });

                // 列表中滑动时,输入框失去焦点
                $dropdownMenu.mouseenter(function() {
                        // console.log(‘mouseenter‘)
                        isMouseenterMenu = 1;
                        $input.blur();
                    }).mouseleave(function() {
                        // console.log(‘mouseleave‘)
                        isMouseenterMenu = 0;
                        $input.focus();
                    }).on(‘mouseenter‘,‘tbody tr‘,function() {
                        // 行上的移动事件
                        unHoverAll($dropdownMenu,options);
                        $(this).addClass(options.listHoverCSS);

                        return FALSE; // 阻止冒泡
                    })
                    .on(‘mousedown‘,function() {
                        var keywords = getPointKeyword($(this));
                        setValue($input,options);
                        setOrGetAlt($input,keywords.key);
                        setBackground($input,options);
                        $dropdownMenu.hide();
                    });

                // 存在清空按钮
                if ($iClear.length) {
                    $iClear.click(function () {
                        setOrGetDataId($input,‘‘).val(‘‘);
                        setBackground($input,options);
                    });

                    $parent.mouseenter(function() {
                        if (!$input.prop(DISABLED)) {
                            $iClear.css(‘right‘,options.showBtn ? Math.max($input.next(‘.input-group-btn‘).width(),33) + 2 : 12)
                                .show();
                        }
                    }).mouseleave(function() {
                        $iClear.hide();
                    });
                }

            });
        },show: function() {
            return this.each(function() {
                $(this).click();
            });
        },hide: function() {
            return this.each(function() {
                $(this).parent().find(‘ul:eq(0)‘).css(‘display‘,‘‘);
            });
        },disable: function() {
            return this.each(function() {
                $(this).attr(DISABLED,TRUE)
                    .parent().find(‘.btn:eq(0)‘).prop(DISABLED,TRUE);
            });
        },enable: function() {
            return this.each(function() {
                $(this).attr(DISABLED,FALSE)
                    .parent().find(‘.btn:eq(0)‘).prop(DISABLED,FALSE);
            });
        },destroy: function() {
            return this.each(function() {
                $(this).off().removeData(BSSUGGEST).removeAttr(‘style‘)
                    .parent().find(‘.btn:eq(0)‘).off().show().attr(‘data-toggle‘,‘dropdown‘).prop(DISABLED,FALSE) // .addClass(DISABLED);
                    .next().css(‘display‘,‘‘).off();
            });
        },version: function() {
            return VERSION;
        }
    };

    $.fn[BSSUGGEST] = function(options) {
        // 方法判断
        if (typeof options === ‘string‘ && methods[options]) {
            var inited = TRUE;
            this.each(function() {
                if (!$(this).data(BSSUGGEST)) {
                    return inited = FALSE;
                }
            });
            // 只要有一个未初始化,则全部都不执行方法,除非是 init 或 version
            if (!inited && ‘init‘ !== options && ‘version‘ !== options) {
                return this;
            }

            // 如果是方法,则参数第一个为函数名,从第二个开始为函数参数
            return methods[options].apply(this,[].slice.call(arguments,1));
        } else {
            // 调用初始化方法
            return methods.init.apply(this,arguments);
        }
    }
});
bootstrap-suggest.js

  4.4 进行get请求

    技巧01:获取get请求的方式和原来的一样

  4.5 获取post、put请求

    技巧01:在bootstrap中的ajax方法中打印options来进行观察配置信息

    4.5.1 配置type

      技巧01:如果配置了type就必须配置param,而且里面params中不用包含一个keyword作为键的KV键值对,因为在bootstrap-suggest中会将input中输入的值作为keyword赋值给param的keyword属性【PS: 在js中为某个对象添加属性和值是直接写就行啦,不用提前声明;param.keyword=xxx,就相当于给param新增了一个keyword属性,而且将xxx赋值给这个属性】

      技巧02:第一次点击input框时,控制台打印出来的信息中没有keyword的信息,因为此时input中还没有任何数据,在input中输入数据后就有数据啦

      技巧03:在input中输入信息后就会自动向后台发送post请求,并将相关数据通过请求体发送到后台;但是这时候控制会报一个500错误,因为我们是使用json-server模拟后台数据,所以会报错;在实际应用中连接正确的后台就不会报错啦

    4.5.2 配置jsonp

      一样的配方,照着套路来就行啦

      技巧01:如果需要配置jsonp,就配置成?jsonp: "jsop" ;否则就不要做jsonp配置啦

      技巧02:控制台同样会报一个错,因为我们使用的是json-server模拟服务器

  4.6 获取选中信息

    选择一条记录后,input标签会出现关键字字段对应的值

    技巧01:可以在onSetSelectValue进行一些选中一条记录后的逻辑操作,例如,向后台发送请求等等

    技巧02:可以在onSetSelectValue方法中获取到配置的ID字段和关键字字段对应的值以及选中后的整条记录的值,例如

?

5 利用SpringBoot搭建真实的后台

  待更新...2018年8月15日22:28:59

?

6 参考信息

  本博文源码:点击前往

  https://www.npmjs.com/package/bootstrap-suggest-plugin

?

?

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读