解决网速慢时 js未执行完毕 用户就去点击按钮 导致下拉框异常问题
现象:
解决方案:先禁用掉按钮,js执行完毕后再取消禁用
html中加disabled="disabled" id="suggestBtn"
js中加$("#suggestBtn").attr("disabled", false);
解决后效果:
新增页面版:
<label class="col-md-2 col-sm-2 text-right" for="productName"><span class="text-danger">*</span>名称:</label>
<div class="col-md-4 col-sm-4">
<div class="input-group">
<input class="form-control" type="text" id="productName" name="productName" required="required" style="border-radius: 4px 0px 0px 4px;" th:value="${info?.productName}">
<div class="input-group-btn">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" disabled="disabled" id="suggestBtn"></button>
<ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>
</div>
</div>
</div>
//suggest下拉框
$("#productName").bsSuggest({
url: '/configProduct/findConfigProductDownPage?name=', //优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数
idField: 'productId', //每组数据的哪个字段作为 data-id,优先级高于 indexId 设置(推荐)
keyField: 'productName', //每组数据的哪个字段作为输入框内容,优先级高于 indexKey 设置(推荐)
effectiveFields: ["productName","productBarcode"], // 有效显示于列表中的字段,非有效字段都会过滤,默认全部有效。
effectiveFieldsAlias: {productName:"名称", productBarcode:"条码"}, // 有效字段的别名对象,用于 header 的显示
searchFields: [], // 有效搜索字段,从前端搜索过滤数据时使用,但不一定显示在列表中。effectiveFields 配置字段也会用于搜索过滤
autoSelect: true, // 键盘向上/下方向键时,是否自动选择值
allowNoKeyword: true, // 是否允许无关键字时请求数据
getDataMethod: 'url', // 获取数据的方式,url:一直从url请求;data:从 options.data 获取;firstByUrl:第一次从Url获取全部数据,之后从options.data获取
delayUntilKeyup: false, // 获取数据的方式 为 firstByUrl 时,是否延迟到有输入时才请求数据
ignorecase: true, // 前端搜索匹配时,是否忽略大小写
twoWayMatch: true, // 是否双向匹配搜索。为 true 即输入关键字包含或包含于匹配字段均认为匹配成功,为 false 则输入关键字包含于匹配字段认为匹配成功
multiWord: false, // 以分隔符号分割的多关键字支持
separator: ',', // 多关键字支持时的分隔符,默认为半角逗号
delay: 300, // 搜索触发的延时时间间隔,单位毫秒
emptyTip: '暂无更多', // 查询为空时显示的内容,可为 html
searchingTip: '搜索中...', // ajax 搜索时显示的提示内容,当搜索时间较长时给出正在搜索的提示
hideOnSelect: true, // 鼠标从列表单击选择了值时,是否隐藏选择列表
clearable: true, // 是否可清除已输入的内容
showBtn: true, //是否显示下拉按钮
showHeader: true, //是否显示选择列表的 header。为 true 时,有效字段大于一列则显示表头
fnProcessData: function(json){// url 获取数据时,对数据的处理,作为 fnGetData 的回调函数
var i, len, data = {value: []};
if(!json || json.length == 0) {
return false;
}
len = json.length;
for (i=0; i<len; i++) {
data.value.push(json[i]);
}
return data;
}
}).on("onSetSelectValue", function(e, keyword, data) {
//赋值
$("#productId").val(data.productId);
$("#productBarcode").val(data.productBarcode);
$("#productUnit").val(data.productUnit);
$("#productSpecification").val(data.productSpecification);
$("#costPrice").val(data.costPrice);
$("#retailPrice").val(data.retailPrice);
$("#supplierId").val(data.supplierId);
$("#supplierName").val(data.supplierName);
});
//like12 add,20220401,bug,解决网速慢时 js未执行完毕 用户就去点击按钮 导致下拉框异常问题
$("#suggestBtn").attr("disabled", false);
查询页面版:
<label for="productClassifyname">分类:</label>
<div class="input-group">
<input type="text" class="form-control input-sm" id="productClassifyname" name="productClassifyname" style="width: 120px;margin-right: -1px">
<div class="input-group-btn">
<button class="btn btn-outline-info dropdown-toggle" type="button" data-toggle="dropdown" disabled="disabled" id="suggestBtn" style="border-radius: 0 3px 3px 0;"></button>
<ul class="dropdown-menu dropdown-menu-right" role="menu"></ul>
</div>
</div>
//suggest下拉框
$("#productClassifyname").bsSuggest({
url: '/configProductClassify/findConfigProductClassifyDownPage?name=', //优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数
idField: 'productClassifyid', //每组数据的哪个字段作为 data-id,优先级高于 indexId 设置(推荐)
keyField: 'productClassifyname', //每组数据的哪个字段作为输入框内容,优先级高于 indexKey 设置(推荐)
effectiveFields: ["productClassifyname","remark"], // 有效显示于列表中的字段,非有效字段都会过滤,默认全部有效。
effectiveFieldsAlias: {productClassifyname:"名称", remark:"备注"}, // 有效字段的别名对象,用于 header 的显示
searchFields: [], // 有效搜索字段,从前端搜索过滤数据时使用,但不一定显示在列表中。effectiveFields 配置字段也会用于搜索过滤
autoSelect: true, // 键盘向上/下方向键时,是否自动选择值
allowNoKeyword: true, // 是否允许无关键字时请求数据
getDataMethod: 'url', // 获取数据的方式,url:一直从url请求;data:从 options.data 获取;firstByUrl:第一次从Url获取全部数据,之后从options.data获取
delayUntilKeyup: false, // 获取数据的方式 为 firstByUrl 时,是否延迟到有输入时才请求数据
ignorecase: true, // 前端搜索匹配时,是否忽略大小写
twoWayMatch: true, // 是否双向匹配搜索。为 true 即输入关键字包含或包含于匹配字段均认为匹配成功,为 false 则输入关键字包含于匹配字段认为匹配成功
multiWord: false, // 以分隔符号分割的多关键字支持
separator: ',', // 多关键字支持时的分隔符,默认为半角逗号
delay: 300, // 搜索触发的延时时间间隔,单位毫秒
emptyTip: '未查询到有效数据', // 查询为空时显示的内容,可为 html
searchingTip: '搜索中...', // ajax 搜索时显示的提示内容,当搜索时间较长时给出正在搜索的提示
hideOnSelect: true, // 鼠标从列表单击选择了值时,是否隐藏选择列表
clearable: false, // 是否可清除已输入的内容
showBtn: true, //是否显示下拉按钮
showHeader: true, //是否显示选择列表的 header。为 true 时,有效字段大于一列则显示表头
fnProcessData: function(json){// url 获取数据时,对数据的处理,作为 fnGetData 的回调函数
var i, len, data = {value: []};
if(!json || json.length == 0) {
return false;
}
len = json.length;
for (i=0; i<len; i++) {
data.value.push(json[i]);
}
return data;
}
});
//like12 add,20220401,bug,解决网速慢时 js未执行完毕 用户就去点击按钮 导致下拉框异常问题
$("#suggestBtn").attr("disabled", false);
日期格式化
//suggest下拉框(学员姓名)
$("#studentName").bsSuggest({
url: '/employee/findEmployeeDownPage?name=', //优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数
idField: 'employeeId', //每组数据的哪个字段作为 data-id,优先级高于 indexId 设置(推荐)
keyField: 'employeeName', //每组数据的哪个字段作为输入框内容,优先级高于 indexKey 设置(推荐)
effectiveFields: ["createdDate","employeeName","idCard","phone","departmentName"], // 有效显示于列表中的字段,非有效字段都会过滤,默认全部有效。
effectiveFieldsAlias: {createdDate:"报名日期", employeeName:"学员姓名", idCard:"身份证号", phone:"电话", departmentName:"分校"}, // 有效字段的别名对象,用于 header 的显示
searchFields: [], // 有效搜索字段,从前端搜索过滤数据时使用,但不一定显示在列表中。effectiveFields 配置字段也会用于搜索过滤
autoSelect: true, // 键盘向上/下方向键时,是否自动选择值
allowNoKeyword: true, // 是否允许无关键字时请求数据
getDataMethod: 'url', // 获取数据的方式,url:一直从url请求;data:从 options.data 获取;firstByUrl:第一次从Url获取全部数据,之后从options.data获取
delayUntilKeyup: false, // 获取数据的方式 为 firstByUrl 时,是否延迟到有输入时才请求数据
ignorecase: true, // 前端搜索匹配时,是否忽略大小写
twoWayMatch: true, // 是否双向匹配搜索。为 true 即输入关键字包含或包含于匹配字段均认为匹配成功,为 false 则输入关键字包含于匹配字段认为匹配成功
multiWord: false, // 以分隔符号分割的多关键字支持
separator: ',', // 多关键字支持时的分隔符,默认为半角逗号
delay: 300, // 搜索触发的延时时间间隔,单位毫秒
emptyTip: '暂无更多', // 查询为空时显示的内容,可为 html
searchingTip: '搜索中...', // ajax 搜索时显示的提示内容,当搜索时间较长时给出正在搜索的提示
hideOnSelect: true, // 鼠标从列表单击选择了值时,是否隐藏选择列表
clearable: true, // 是否可清除已输入的内容
showBtn: true, //是否显示下拉按钮
showHeader: true, //是否显示选择列表的 header。为 true 时,有效字段大于一列则显示表头
fnProcessData: function(json){// url 获取数据时,对数据的处理,作为 fnGetData 的回调函数
var i, len, data = {value: []};
if(!json || json.length == 0) {
return false;
}
len = json.length;
for (i=0; i<len; i++) {
json[i].createdDate = new Date(json[i].createdDate).format("yyyy-MM-dd");//日期格式化
data.value.push(json[i]);
}
return data;
}
}).on("onSetSelectValue", function(e, keyword, data) {
//赋值
$("#studentId").val(data.employeeId);
$("#studentName").val(data.employeeName);
$("#studentIdCard").val(data.idCard);
$("#studentPhone").val(data.phone);
$("#studentStatus").val(data.studentStatus);
$("#departmentId").val(data.departmentId);
$("#departmentName").val(data.departmentName);
});
js (正式2)(调整参数==动态参数==动态url)
//suggest下拉框(调整参数==动态参数==动态url)
$("#shopName").bsSuggest({
url: '/configLocation/findConfigLocationDownAll?', //优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数
idField: 'shopId', //每组数据的哪个字段作为 data-id,优先级高于 indexId 设置(推荐)
keyField: 'shopName', //每组数据的哪个字段作为输入框内容,优先级高于 indexKey 设置(推荐)
effectiveFields: ["shopName","garageAddress"], // 有效显示于列表中的字段,非有效字段都会过滤,默认全部有效。
effectiveFieldsAlias: {shopName:"名称", garageAddress:"地址"}, // 有效字段的别名对象,用于 header 的显示
searchFields: [], // 有效搜索字段,从前端搜索过滤数据时使用,但不一定显示在列表中。effectiveFields 配置字段也会用于搜索过滤
autoSelect: true, // 键盘向上/下方向键时,是否自动选择值
allowNoKeyword: true, // 是否允许无关键字时请求数据
getDataMethod: 'url', // 获取数据的方式,url:一直从url请求;data:从 options.data 获取;firstByUrl:第一次从Url获取全部数据,之后从options.data获取
delayUntilKeyup: false, // 获取数据的方式 为 firstByUrl 时,是否延迟到有输入时才请求数据
ignorecase: true, // 前端搜索匹配时,是否忽略大小写
twoWayMatch: true, // 是否双向匹配搜索。为 true 即输入关键字包含或包含于匹配字段均认为匹配成功,为 false 则输入关键字包含于匹配字段认为匹配成功
multiWord: false, // 以分隔符号分割的多关键字支持
separator: ',', // 多关键字支持时的分隔符,默认为半角逗号
delay: 300, // 搜索触发的延时时间间隔,单位毫秒
emptyTip: '未查询到有效数据', // 查询为空时显示的内容,可为 html
searchingTip: '搜索中...', // ajax 搜索时显示的提示内容,当搜索时间较长时给出正在搜索的提示
hideOnSelect: true, // 鼠标从列表单击选择了值时,是否隐藏选择列表
clearable: true, // 是否可清除已输入的内容
showBtn: true, //是否显示下拉按钮
showHeader: true, //是否显示选择列表的 header。为 true 时,有效字段大于一列则显示表头
fnProcessData: function(json){// url 获取数据时,对数据的处理,作为 fnGetData 的回调函数
var i, len, data = {value: []};
if(!json || json.length == 0) {
return false;
}
len = json.length;
for (i=0; i<len; i++) {
data.value.push(json[i]);
}
return data;
},
fnAdjustAjaxParam: function(keyword, opts) {//调整 ajax 请求参数方法,用于更多的请求配置需求。如对请求关键字作进一步处理、修改超时时间等
return {
timeout: 10000,
data: {
t: (new Date()).getTime(),
name: keyword,
id: $('#garageId').val()
}
};
}
}).on("onSetSelectValue", function(e, keyword, data) {
//赋值
$("#shopId").val(data.shopId);
});
js (完整)
//suggest下拉框
var dataBsSuggest = $("#productName").bsSuggest({
//indexId: 2, //每组数据的第几个数据,作为input输入框的 data-id,设为 -1 且 idField 为空则不设置此值
//indexKey: 1, //每组数据的第几个数据,作为input输入框的内容
idField: 'id', //每组数据的哪个字段作为 data-id,优先级高于 indexId 设置(推荐)
keyField: 'name', //每组数据的哪个字段作为输入框内容,优先级高于 indexKey 设置(推荐)
//搜索相关
autoSelect: true, // 键盘向上/下方向键时,是否自动选择值
allowNoKeyword: true, // 是否允许无关键字时请求数据
getDataMethod: 'url', // 获取数据的方式,url:一直从url请求;data:从 options.data 获取;firstByUrl:第一次从Url获取全部数据,之后从options.data获取
delayUntilKeyup: false, // 获取数据的方式 为 firstByUrl 时,是否延迟到有输入时才请求数据
ignorecase: true, // 前端搜索匹配时,是否忽略大小写
effectiveFields: ["id","name","desc"], // 有效显示于列表中的字段,非有效字段都会过滤,默认全部有效。
effectiveFieldsAlias: {id:"id", name:"名称", desc:"描述"}, // 有效字段的别名对象,用于 header 的显示
searchFields: [], // 有效搜索字段,从前端搜索过滤数据时使用,但不一定显示在列表中。effectiveFields 配置字段也会用于搜索过滤
twoWayMatch: true, // 是否双向匹配搜索。为 true 即输入关键字包含或包含于匹配字段均认为匹配成功,为 false 则输入关键字包含于匹配字段认为匹配成功
multiWord: false, // 以分隔符号分割的多关键字支持
separator: ',', // 多关键字支持时的分隔符,默认为半角逗号
delay: 300, // 搜索触发的延时时间间隔,单位毫秒
emptyTip: '暂无更多', // 查询为空时显示的内容,可为 html
searchingTip: '搜索中...', // ajax 搜索时显示的提示内容,当搜索时间较长时给出正在搜索的提示
hideOnSelect: true, // 鼠标从列表单击选择了值时,是否隐藏选择列表
//UI
clearable: true, // 是否可清除已输入的内容
showBtn: true, //是否显示下拉按钮
showHeader: true, //是否显示选择列表的 header。为 true 时,有效字段大于一列则显示表头
//autoDropup: false, //选择菜单是否自动判断向上展开。设为 true,则当下拉菜单高度超过窗体,且向上方向不会被窗体覆盖,则选择菜单向上弹出
//autoMinWidth: false, //是否自动最小宽度,设为 false 则最小宽度不小于输入框宽度
//inputBgColor: '', //输入框背景色,当与容器背景色不同时,可能需要该项的配置
//inputWarnColor: 'rgba(255,0,0,.1)', //输入框内容不是下拉列表选择时的警告色
//listStyle: {
// 'padding-top': 0,
// 'max-height': '375px',
// 'max-width': '800px',
// 'overflow': 'auto',
// 'width': 'auto',
// //'width': '300px',
// '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', //提示框列表鼠标悬浮的样式名称
//key
//keyLeft: 37, //向左方向键,不同的操作系统可能会有差别,则自行定义
//keyUp: 38, //向上方向键
//keyRight: 39, //向右方向键
//keyDown: 40, //向下方向键
//keyEnter: 13, //回车键
//methods(bug,放开后会出问题)
//fnProcessData: processData, //格式化数据的方法,返回数据格式参考 data 参数
//fnGetData: getData, //获取数据的方法,无特殊需求一般不作设置
//fnAdjustAjaxParam: null, //调整 ajax 请求参数方法,用于更多的请求配置需求。如对请求关键字作进一步处理、修改超时时间等
//fnPreprocessKeyword: null, //搜索过滤数据前,对输入关键字作进一步处理方法。注意,应返回字符串
//url获取
url: '/configProduct/findConfigProductDownPage?name=', //优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数
fnProcessData: function(json){// url 获取数据时,对数据的处理,作为 fnGetData 的回调函数
var i, len, data = {value: []};
if(!json || json.length == 0) {
return false;
}
len = json.length;
for (i=0; i<len; i++) {
data.value.push({
"id": json[i].productId,
"name": json[i].productName,
"desc": json[i].productBarcode
});
}
//console.log(data);
return data;
}
/*//淘宝搜索
url: "https://suggest.taobao.com/sug?code=utf-8&extras=1&q=", //优先从url ajax 请求 json 帮助数据,注意最后一个参数为关键字请求参数
jsonp: "callback", //如果从 url 获取数据,并且需要跨域,则该参数必须设置
fnProcessData: function(json) {// url 获取数据时,对数据的处理,作为 fnGetData 的回调函数
var i, len, data = {value: []};
if (!json || !json.result || !json.result.length) {
return false;
}
len = json.result.length;
for (i = 0; i < len; i++) {
data.value.push({
"id": i + 1,
"name": json.result[i][0],
"desc": json.result[i][1]
});
}
//console.log("淘宝搜索 API: ", data);
return data;
}*/
/*//固定数据
data: {
'value': [
{
'id': '0',
'name': 'lzw',
'desc': 'http://lzw.me'
},
{
'id': '1',
'name': 'lzwme',
'desc': 'http://w.lzw.me'
},
{
'id': '2',
'name': 'meizu',
'desc': 'http://www.meizu.com'
},
{
'id': '3',
'name': 'flyme',
'desc': 'http://flyme.meizu.com'
}
],
'defaults': 'http://lzw.me'
}*/
})/*.on("onDataRequestSuccess", function(e, result) {
//console.log("onDataRequestSuccess: ", result);
}).on("onSetSelectValue", function(e, keyword, data) {
//console.log("onSetSelectValue: ", keyword, data);
}).on("onUnsetSelectValue", function() {
//console.log("onUnsetSelectValue");
})*/;
效果