Choose.jsプラグインを使用しています http://harvesthq.github.com/chosen/ jQueryで、ユーザーが選択から複数のオプションを選択できるようにします。ただし、まだ存在しない値createを許可できるようにしたいと考えています。
編集:SO自身のタグ選択/作成バーに似たものは、私が望んでいるものに近いでしょう
プラグインを変更または編集せずに、できれば必要に応じて変更してください。
コード: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:
$(function(){
$('select').chosen();
});
したがって、ユーザーが「3番目のオプション」と入力する場合は、リストに追加して選択するようにします。値と表示名は/であるため、心配する必要はありません
ドキュメントによると、次のようなことを試すことができます。
$('select').append('<option>test</option>');
$('select').trigger('liszt:updated');
トニーが以下のコメントで述べたように:
「トリガーが「chosen:updated」になったバージョン1.0以降。 harvesthq.github.io/chosen/#change-update-events "
私はこれに出会って同じアイデアを探しました。かなり人気のある機能リクエストのようで、いくつかのフォークがそれを実装しています。すぐにmasterブランチにマージされるようです。
魅力を発揮したこの特定のプルに対して+1: https://github.com/harvesthq/chosen/pull/166
Koenpuntのフォークはここで見ることができます: https://github.com/koenpunt/chosen
ここに私がそれをした簡単な方法があります:
$(".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');
}
});
私はちょうど同じ問題を解決しようとしていました。ソースコードを少し修正しました。これが新しい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();
}
};
これは答えではなく、別の解決策を知っています。
私はその場で追加部分を探していましたが、 http://ivaynberg.github.com/select2/#tags が選択されたものと同じこと+「タグ付け」のような他のものを提供することがわかりました。
特定の文字コードをリッスンするために、入力テキストボックスにイベントを添付することができます。その後、オプションを追加し、ドロップダウンで更新をトリガーします。
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;
}
});
3nochrootのコードをもう一度更新しました。これで、複数選択入力を見つけるためのセレクタが1つだけになりました。
$(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;
}
}
)
})
選択した後のバージョンで動作する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;
}
}
)
ここと他の場所でいくつかの解決策を試しましたが、choose.js 1.8.5(jQuery:3.3.1)で機能するものはありませんでした。 -masterブランチの最新情報:
.chosen-select
新しい値を許可するために、新しいクラスを追加しました.chosen-newValuesAllowed
。 CTRL + Iがまだ存在しない場合、新しい値を追加するこのクラスにイベントハンドラーを設定します。入力フィールドのフォーカスはその後失われません。私の例では、@ valueには実際にデータベースIDが含まれているため、innerHTMLをチェックします。したがって、新しい値(この例では後でサーバーによって処理される文字列)は@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;
}
});
別の解決策は、明示的に結果がない場合にのみ新しい値を追加する場合は、トリガー可能な関数chosen:no_resultsを呼び出すことです。
$(".chosen-select.chosen-newValuesAllowed").on("chosen:no_results", function(e, data){
var newValue = data.chosen.get_search_text();
...
});
複数選択のleogdion回答の更新( Gist )
$(".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;
}
})
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'