jQuery 允许使用 selected.js 多选的新值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7385246/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
allow new values with chosen.js multiple select
提问by totallyNotLizards
I'm using the chosen.js plugin http://harvesthq.github.com/chosen/with jQuery to allow the user to select multiple options from a select. However, I now want to be able to let them createvalues that aren't already present - any idea how to go about this?
我将 selected.js 插件http://harvesthq.github.com/chosen/与 jQuery 一起使用,以允许用户从一个选择中选择多个选项。但是,我现在希望能够让他们创造尚不存在的价值 - 知道如何解决这个问题吗?
EDIT: something similar to SO's own tag selection/creation bar would be close to what I'm after
编辑:类似于 SO 自己的标签选择/创建栏的东西将接近我所追求的
Preferably without changing or editing the plugin, but will do if required.
最好不要更改或编辑插件,但会在需要时进行。
The code: HTML:
代码: HTML:
<p>Select something</p>
<select name="theSelect[]" multiple="multiple">
<option value="First Option">First Option</option>
<option value="Second Option">Second Option</option>
</select>
Javascript:
Javascript:
$(function(){
$('select').chosen();
});
So if a user were to type in "Third Option", i'd like to add that to the list and have it selected. The value and display name are / will be the same so that's not a concern
因此,如果用户要输入“第三个选项”,我想将其添加到列表中并选择它。值和显示名称是 / 将是相同的,所以这不是问题
采纳答案by jeffreydev
According to the documentation you can try doing something like this:
根据文档,您可以尝试执行以下操作:
$('select').append('<option>test</option>');
$('select').trigger('liszt:updated');
As Tony stated in the comments below:
正如托尼在下面的评论中所说:
"Starting with version 1.0 which the trigger is now "chosen:updated". See harvesthq.github.io/chosen/#change-update-events"
“从 1.0 版开始,触发器现在是“选择:更新”。请参阅harvethq.github.io/chosen/#change-update-events“
回答by Galaxy
I stumbled upon this looking for the same ideas. Seems like its a pretty popular feature request, and a couple of forks have implemented it. Looks like it'll be merged into the master branch soon enough.
我偶然发现了这个寻找相同的想法。似乎它是一个非常受欢迎的功能请求,并且有几个分支已经实现了它。看起来它很快就会合并到主分支中。
+1 for this particular pull which worked a charm: https://github.com/harvesthq/chosen/pull/166
+1 对这个特别有效的拉动很有魅力:https: //github.com/harvesthq/chosen/pull/166
You can view Koenpunt's fork here: https://github.com/koenpunt/chosen
你可以在这里查看 Koenpunt 的 fork:https: //github.com/koenpunt/chosen
回答by Ultimation
Here's a simple way that I did it:
这是我做到的一个简单方法:
$(".search-field").find("input").live( "keydown", function (evt) {
var stroke;
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
if (stroke == 9) { // 9 = tab key
$('#tags').append('<option value="' + $(this).val() + '" selected="selected">' + $(this).val() + '</option>');
$('#tags').trigger('chosen:updated');
}
});
回答by Samo
I was just trying to solve the same problem. I wound up modifying the source code a bit. Here's the new keyup_checker function. Take a look at case 13:
我只是想解决同样的问题。我最终稍微修改了源代码。这是新的 keyup_checker 函数。看案例13:
AbstractChosen.prototype.keyup_checker = function(evt) {
var stroke, _ref;
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
this.search_field_scale();
switch (stroke) {
case 8:
if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
return this.keydown_backstroke();
} else if (!this.pending_backstroke) {
this.result_clear_highlight();
return this.results_search();
}
break;
case 13:
evt.preventDefault();
if (this.results_showing) {
if (!this.is_multiple || this.result_highlight) {
return this.result_select(evt);
}
$(this.form_field).append('<option>' + $(evt.target).val() + '</option>');
$(this.form_field).trigger('liszt:updated');
this.result_highlight = this.search_results.find('li.active-result').last();
return this.result_select(evt);
}
break;
case 27:
if (this.results_showing) this.results_hide();
return true;
case 9:
case 38:
case 40:
case 16:
case 91:
case 17:
break;
default:
return this.results_search();
}
};
回答by sk8terboi87 ツ
I know this not the answer, but, an alternate solution.
我知道这不是答案,而是另一种解决方案。
I was searching for the on-the-fly adding part and found that http://ivaynberg.github.com/select2/#tagsprovides the same thing as chosen + other stuffs like "Tagging".
我正在搜索动态添加部分,发现http://ivaynberg.github.com/select2/#tags提供了与selected相同的东西 + 其他东西,如“标记”。
回答by leogdion
You could just attach an event to the input text box to listen for a particular character code. After that add the option and trigger the update on the dropdown.
您可以将事件附加到输入文本框以侦听特定字符代码。之后添加选项并触发下拉列表中的更新。
var dropDown = $('select.chosen');
dropDown.parent().find('.chzn-container .chzn-search input[type=text]').keydown( function (evt) {
var stroke, _ref, target, list;
// get keycode
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
target = $(evt.target);
// get the list of current options
list = target.parents('.chzn-container').find('.chzn-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
if (stroke === 9 || stroke === 13) {
var value = $.trim(target.val());
// if the option does not exists
if ($.inArray(value,list) < 0) {
var option = $('<option>');
option.text(value).val(value).appendTo(dropDown);
option.attr('selected','selected');
// add the option and set as selected
}
// trigger the update event
dropDown.trigger("liszt:updated");
return true;
}
});
回答by EdwardB
An update to leogdion's answer which works with later versions of chosen:
leogdion 答案的更新,适用于所选的更高版本:
var dropDown = $('#select_chosen');
// Make the chosen drop-down dynamic. If a given option is not in the list, the user can still add it
dropDown.parent().find('.chosen-container .search-field input[type=text]').keydown(
function (evt) {
var stroke, _ref, target, list;
// get keycode
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
// If enter or tab key
if (stroke === 9 || stroke === 13) {
target = $(evt.target);
// get the list of current options
chosenList = target.parents('.chosen-container').find('.chosen-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
// get the list of matches from the existing drop-down
matchList = target.parents('.chosen-container').find('.chosen-results li').map(function () { return $(this).text(); }).get();
// highlighted option
highlightedList = target.parents('.chosen-container').find('.chosen-results li.highlighted').map(function () { return $(this).text(); }).get();
// Get the value which the user has typed in
var newString = $.trim(target.val());
// if the option does not exists, and the text doesn't exactly match an existing option, and there is not an option highlighted in the list
if ($.inArray(newString,matchList) < 0 && $.inArray(newString,chosenList) < 0 && highlightedList.length == 0) {
// Create a new option and add it to the list (but don't make it selected)
var newOption = '<option value="' + newString + '">' + newString + '</option>';
$("#select").prepend(newOption);
// trigger the update event
$("#select").trigger("chosen:updated");
// tell chosen to close the list box
$("#select").trigger("chosen:close");
return true;
}
// otherwise, just let the event bubble up
return true;
}
}
)
回答by Rawburner
I have updated the code from 3nochroot once more. Now I have only one selector to find the multiselect input.
我再次更新了 3nochroot 的代码。现在我只有一个选择器来查找多选输入。
$(document).ready(function() {
$(".js-choicelist").chosen({
//config comes here
}).parent().find('.chosen-container .search-field input[type=text]').keydown(
function (evt) {
var stroke, _ref, target, list;
// get keycode
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
// If enter or tab key
if (stroke === 9 || stroke === 13) {
target = $(evt.target);
// get the list of current options
chosenList = target.parents('.chosen-container').find('.chosen-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
// get the list of matches from the existing drop-down
matchList = target.parents('.chosen-container').find('.chosen-results li').map(function () { return $(this).text(); }).get();
// highlighted option
highlightedList = target.parents('.chosen-container').find('.chosen-results li.highlighted').map(function () { return $(this).text(); }).get();
// Get the value which the user has typed in
var newString = $.trim(target.val());
// if the option does not exists, and the text doesn't exactly match an existing option, and there is not an option highlighted in the list
if ($.inArray(newString,matchList) < 0 && $.inArray(newString,chosenList) < 0 && highlightedList.length == 0) {
// Create a new option and add it to the list (but don't make it selected)
var newOption = '<option value="' + newString + '">' + newString + '</option>';
var choiceSelect = target.parents('.select-multiple').find('select');
choiceSelect.prepend(newOption);
// trigger the update event
choiceSelect.trigger("chosen:updated");
// tell chosen to close the list box
choiceSelect.trigger("chosen:close");
return true;
}
// otherwise, just let the event bubble up
return true;
}
}
)
})
})
回答by srghma
Update of leogdion answer for multiple select (gist)
多选 ( gist)的 leogdion 答案更新
$(".chosen-select-with-add-new").chosen({
no_results_text: "Click Enter or Tab to add new option",
width: '100%'
}).parent().find('.chosen-container .search-field input[type=text]').keydown(function (evt) {
// get keycode
const stroke = evt.which != null ? evt.which : evt.keyCode;
// If enter or tab key
if (stroke === 9 || stroke === 13) {
const target = $(evt.target);
// get the list of current options
const chosenList = target.parents('.chosen-container').find('.chosen-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
// get the list of matches from the existing drop-down
const matchList = target.parents('.chosen-container').find('.chosen-results li').map(function () { return $(this).text(); }).get();
// highlighted option
const highlightedList = target.parents('.chosen-container').find('.chosen-results li.highlighted').map(function () { return $(this).text(); }).get();
// Get the value which the user has typed in
const newString = $.trim(target.val());
// if the option does not exists, and the text doesn't exactly match an existing option, and there is not an option highlighted in the list
if ($.inArray(newString, matchList) < 0 && $.inArray(newString,chosenList) < 0 && highlightedList.length == 0) {
// Create a new option and add it to the list (but don't make it selected)
const newOption = '<option value="' + newString + '" selected="selected">' + newString + '</option>';
const choiceSelect = target.parents('.chosen-container').siblings('.chosen-select-with-add-new');
choiceSelect.append(newOption);
// trigger the update event
choiceSelect.trigger("chosen:updated");
// tell chosen to close the list box
choiceSelect.trigger("chosen:close");
return true;
}
// otherwise, just let the event bubble up
return true;
}
})
Example usage on rails (slim)
导轨上的示例用法(超薄)
.tag-list
label.control-label.h5 Tag list
= select_tag :tag_list, options_for_select(ActsAsTaggableOn::Tag.order('taggings_count desc').pluck(:name), @publication.tags.map(&:name)), multiple: true, data: { placeholder: 'north, east, south, west' }, class: 'chosen-select-with-add-new'
回答by meistermuh
I tried several solutions given here and elsewhere, however none worked in chosen.js 1.8.5 (jQuery: 3.3.1) and so I ended up with the following since I didn't want to use a fork that might not always be up-to-date to the master branch:
我尝试了这里和其他地方给出的几种解决方案,但是没有一个在 selected.js 1.8.5 (jQuery: 3.3.1) 中起作用,所以我最终得到了以下解决方案,因为我不想使用可能并不总是可用的叉子- 最新到主分支:
For the case that I might not want any .chosen-select
to allow new values, I added a new class .chosen-newValuesAllowed
. I set an event handler on this class where CTRL + Iadds the new value if it is not yet present. The focus on the input field does not get lost afterwards. In my example, I check the innerHTML of the since @value actually contains database ids and therefore the new value, which is a string in my example that would be processed by the server later, could never be found in @value. If you want to check @value, please see the comment inside the snippet.
The code handles single and multiple selects.
对于我可能不希望任何.chosen-select
允许新值的情况,我添加了一个新类.chosen-newValuesAllowed
。我在这个类上设置了一个事件处理程序,如果它不存在,那么CTRL + I添加新值。之后输入字段的焦点不会丢失。在我的示例中,我检查了 @value 的innerHTML,因为@value 实际上包含数据库ID,因此新值(在我的示例中是稍后将由服务器处理的字符串)永远不会在@value 中找到。如果您想检查@value,请查看代码段内的注释。代码处理单选和多选。
$(document).on("keydown", ".chosen-container.chosen-newValuesAllowed input", function(e) {
if (e.ctrlKey === true && e.keyCode === 73) { // CTRL + I
e.preventDefault();
var newValue = $(this).val();
if (newValue) {
try {
// only add if there is no option having the content/text of "input" yet!
// instead of filter() for the content of <option> you can check on its @value by: find("option[val='...']")
var $selectElement = $(e.target).closest("div.chosen-container").prev(); // the previous sibling should be the <select>. If not, grab it some other way, e.g. via @id
if (!$selectElement.find("option").filter(function () { return $(this).html() === newValue; }).length) {
if (!$selectElement.attr("multiple")) { // unselect for single-select
$selectElement.val('');
}
$selectElement.append('<option val="' + newValue + '" selected>' + newValue + '</option>');
$selectElement.trigger('chosen:updated');
}
} catch(error) {
// pass
}
e.target.focus();
}
return false;
}
});
Another solution would be to call the triggerable function chosen:no_resultsif new values should only be added if there explicitly is no result:
另一种解决方案是调用可触发函数selected:no_results如果新值仅在明确没有结果时才应添加:
$(".chosen-select.chosen-newValuesAllowed").on("chosen:no_results", function(e, data){
var newValue = data.chosen.get_search_text();
...
});