jquery - not - select2 selected
Permitir nuevos valores con selected.js multiple select (10)
Estoy usando el plugin chosen.js http://harvesthq.github.com/chosen/ con jQuery para permitir al usuario seleccionar múltiples opciones de una selección. Sin embargo, ahora quiero permitirles crear valores que aún no están presentes. ¿Alguna idea de cómo hacerlo?
EDITAR: algo similar a la propia barra de selección / creación de etiquetas de SO estaría cerca de lo que busco
Preferiblemente sin cambiar o editar el complemento, pero lo hará si es necesario.
El código: 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();
});
Entonces, si un usuario escribe "Tercera opción", me gustaría agregar eso a la lista y hacer que se seleccione. El valor y el nombre de visualización son / serán los mismos, por lo que no es una preocupación
Actualización de la respuesta de leogdion para selección múltiple ( 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;
}
})
Ejemplo de uso en rieles (delgado)
.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''
Aquí hay una forma simple en que lo hice:
$(".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'');
}
});
He actualizado el código de 3nochroot una vez más. Ahora solo tengo un selector para encontrar la entrada de selección múltiple.
$(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;
}
}
)
})
Me topé con esto buscando las mismas ideas. Parece que es una solicitud de características bastante popular, y un par de bifurcaciones lo han implementado. Parece que se fusionará en la rama maestra lo suficientemente pronto.
+1 para este tirón en particular que funcionó de forma encantadora: https://github.com/harvesthq/chosen/pull/166
Puede ver el tenedor de Koenpunt aquí: https://github.com/koenpunt/chosen
Probé varias soluciones dadas aquí y en otros lugares, sin embargo, ninguna funcionó en selected.js 1.8.5 (jQuery: 3.3.1) y terminé con lo siguiente, ya que no quería usar un tenedor que podría no estar siempre arriba. hasta la fecha en la rama maestra:
Para el caso de que no quiera ningún .chosen-select
para permitir nuevos valores, agregué una nueva clase .chosen-newValuesAllowed
. Establecí un controlador de eventos en esta clase donde CTRL + I agrega el nuevo valor si aún no está presente. El enfoque en el campo de entrada no se pierde después. En mi ejemplo, verifico el innerHTML de ya que @value realmente contiene los identificadores de la base de datos y, por lo tanto, el nuevo valor, que es una cadena en mi ejemplo que sería procesado por el servidor más adelante, nunca se pudo encontrar en @value. Si desea comprobar @value, consulte el comentario dentro del fragmento. El código maneja selecciones individuales y múltiples.
$(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;
}
});
Otra solución sería llamar a la función activable elegida: no_results si solo se deben agregar nuevos valores si no hay un resultado explícito:
$(".chosen-select.chosen-newValuesAllowed").on("chosen:no_results", function(e, data){
var newValue = data.chosen.get_search_text();
...
});
Sé que esta no es la respuesta, pero, una solución alternativa.
Estaba buscando la parte agregada sobre la marcha y descubrí que http://ivaynberg.github.com/select2/#tags proporciona lo mismo que otros materiales seleccionados como "Etiquetado".
Según la documentación puedes intentar hacer algo como esto:
$(''select'').append(''<option>test</option>'');
$(''select'').trigger(''liszt:updated'');
Como Tony declaró en los comentarios a continuación:
"A partir de la versión 1.0, el activador ahora" elegido: actualizado ". Consulte harvesthq.github.io/chosen/#change-update-events "
Simplemente puede adjuntar un evento al cuadro de texto de entrada para escuchar un código de carácter particular. Después de eso, agregue la opción y active la actualización en el menú desplegable.
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;
}
});
Solo estaba tratando de resolver el mismo problema. Terminé modificando un poco el código fuente. Aquí está la nueva función keyup_checker. Eche un vistazo al caso 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();
}
};
Una actualización de la respuesta de leogdion que funciona con versiones posteriores de elegidos:
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;
}
}
)