javascript - jquery multiple custom combobox with custom -renderItem causes cross event fire
问题描述
I have a question that I have been unable to resolve. On a data entry screen I have 4 jquery-ui custom comboboxes. I had them working fine even though they each have a thousand or so options. One of them I wanted to be able to display multi-line options. I found a few examples of creating a custom _renderItem extension on the autocomplete to do this. Problem is when I have a custom _renderItem, and I click on an item in any of the custom comboboxes, the click events for ALL FOUR comboboxes will fire. If I don't have the custom _renderItem, then everything works fine and only the event for clicked combobox fires. The alert in "this._on( this.input" tells me which event (or events) fired.
After .autocomplete({ you will see the various methods I have attempted. I even tried just the default renderitem function without modifying the label or value, and it still gave me the crossfire events.
I SUSPECT that data("autocomplete") is assigning based on the classname, and custom combobox is creating 4 ul's with that classname, but I don't know how to pick the particular ul.
Any suggestions would be greatly appreciated.
Thanks in advance!
I am using jquery-1.12.4.js and ui/1.12.1/jquery-ui.js
/* create custom typeahead combobox */
$.widget( "custom.combobox", {
_create: function() {
this.wrapper = $( "<span>" )
.addClass( "custom-combobox" )
.insertAfter( this.element );
var obj = this.element.get(0); /* select object */
var objid = obj.id;
this._createULHolder(objid),
this._createInner();
this.element.hide();
this._createAutocomplete(objid);
this._createShowAllButton();
},
_createULHolder:function(objid) {
var theBody = document.getElementsByTagName('body')[0];
this.ulholder = $("<div>")
.appendTo(theBody)
.addClass("ui-input-text ui-body-inherit ui-shadow-inset " + 'divul_' + objid)
.attr('id','divul_' + objid)
.attr('style','position:absolute;left:-999em')
},
_createInner:function() {
this.inner = $("<div>")
.appendTo(this.wrapper)
.addClass("ui-input-text ui-body-inherit ui-shadow-inset custom-combobox-input-wrapper") /* my-ui-no-margin */
},
_createAutocomplete: function(objid) {
var selected = this.element.children( ":selected" ),
value = selected.val() ? selected.text() : "";
if (value.indexOf('|') > -1) {
var lines = value.split('|');
value = lines[0];
}
this.input = $( "<input>" )
.appendTo( this.inner )
.val( value )
.attr( "title", "" )
.attr( "id", "combobox_" + objid)
.addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
.tooltip({
classes: {
"ui-tooltip": "ui-state-highlight"
}
})
.autocomplete({
delay: 0,
minLength: 0,
appendTo:"#divul_" + objid,
classes: { "ui-autocomplete": "ui-autocomplete-" + objid },
source: $.proxy( this, "_source" )
});
/* this.input
.autocomplete("ui-autocomplete-" + objid)._renderItem = function( ul, item ) {
return $( "<li>" )
.append( "<div>" + item.label + "<br>" + item.desc + "</div>" )
.appendTo( ul );
};*/
/* .data("ui-autocomplete")._renderItem = function (ul, item) {
var tlabel = item.label;
if (tlabel.indexOf('|') > -1) {
var lines = tlabel.split('|');
tlabel = '<span class="ui-selectmenu-menu-item-header">' + lines[0].trim() + ' </span>';
for (var i = 1; i < lines.length; i++) {
tlabel = tlabel + '<span class="ui-selectmenu-menu-item-lines"> - ' + lines[i].trim() + '</span>';
}
}
var d = $("<div></div>")
.data("item.autocomplete", item)
.append(item.label);
return $("<li>")
.attr("data-value",item.value)
.append(d)
.appendTo(ul);
};*/
this._on( this.input, {
autocompleteselect: function( event, ui ) {
ui.item.option.selected = true;
this._trigger( "select", event, {
item: ui.item.option
});
tlabel = ui.item.option.label;
if (tlabel.indexOf('|') > -1) {
var lines = tlabel.split('|');
tlabel = lines[0];
$("#combobox_" + objid).val(tlabel);
}
alert('objid=' + objid + ' val=' + $("#combobox_" + objid).val() + ' tlabel=' + tlabel);
},
autocompletechange: "_removeIfInvalid"
});
},
_createShowAllButton: function() {
var input = this.input,
wasOpen = false;
$( "<a>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.tooltip()
.appendTo( this.wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "custom-combobox-toggle ui-corner-right" )
.on( "mousedown", function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.on( "click", function() {
input.trigger( "focus" );
// Close if already visible
if ( wasOpen ) {
return;
}
// Pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
});
},
_source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
var select_el = this.element.get(0); // get dom element
var rep = new Array(); // response array
// simple loop for the options
for (var i = 0; i < select_el.options.length; i++) {
var text = select_el.options[i].text;
if ( select_el.options[i].value && ( !request.term || matcher.test(text) ) )
// add element to result array
rep.push({
label: text, // no more bold
value: text,
option: select_el.options[i]
});
}
// send response
response( rep );
},
_removeIfInvalid: function( event, ui ) {
// Selected an item, nothing to do
if ( ui.item ) {
return;
}
// Search for a match (case-insensitive)
var value = this.input.val(),
valueLowerCase = value.toLowerCase(),
valid = false;
this.element.children( "option" ).each(function() {
if ( $( this ).text().toLowerCase() === valueLowerCase ) {
this.selected = valid = true;
return false;
}
});
// Found a match, nothing to do
if ( valid ) {
return;
}
// Remove invalid value
this.input
.val( "" )
.attr( "title", value + " didn't match any item" )
.tooltip( "open" );
this.element.val( "" );
this._delay(function() {
this.input.tooltip( "close" ).attr( "title", "" );
}, 2500 );
this.input.autocomplete( "instance" ).term = "";
},
_destroy: function() {
this.wrapper.remove();
this.element.show();
}
});
$( function() {
$("#dd1").combobox();
$("#dd2").combobox();
$("#dd3").combobox();
$("#dd4").combobox();
});
解决方案
推荐阅读
- java - 当我尝试在 xml 文件中设置布局宽度和高度时出现错误
- android - FirebaseRecyclerAdapter 无法应用
- python - R 的这种混合效果将其转换为 python 是否正确?
- java - 将 HTML 转换为 PDF 的字符问题
- cuda - CUDA 数据初始化
- android - android xml 设计在更大的屏幕设备(如 > 6.0 英寸)的屏幕底部显示更多空间,尤其是在三星 M20 中
- ios - 通过导航控制器使用自定义动画转换到 SecondViewController 后,SecondViewController 中的非活动视图
- feathersjs - Feathers auth 登录无效
- c - 通过 HTTP 请求将文件上传到 Google Drive (C)
- php - 为什么成功交易后paypal沙箱金额没有变化?