I have a client that wants to give users the option to select up to 5 additional options from a list. I like the Chosen.js concept, but how can I limit the selection? I suppose one solution is to use the onChange to count the number selected and then disable the remainder, but is there a neater solution?
Chosen provides a max_selected_options to allow you to do this:
$(".chzn-select").chosen({ max_selected_options: 5 });
max_selected_options: 5 is not working in my case. So I fixed as follows.
var countSelect = 0;
$(".chosen-select").chosen().change( function (e, params) {
if(params.deselected != undefined) { countSelect--; }
if(params.selected != undefined) { countSelect++; }
if(countSelect > 3) {
$('.chosen-select option[value="'+params.selected+'"]').attr('selected', false);
$(this).trigger('chosen:updated');
countSelect--;
}
});
Try it. Its working very smooth.
Related
When using Chosen.js on a multiple select field, if there are over 500 options that the user has selected, the list just becomes ridiculously long.
Is there any way I could limit the number of show elements? For example when chosing over 3 options, the user will have (4) options are selected..., instead of them being listed.
I wonder why there's no such option in their documentation.
Thanks in advance.
You can use something like this:
$('.element').chosen().change(function() {
var totalSelected = $(this).find('option:selected').size();
var placeholder = $(this).find('option:first-child').text();
if(totalSelected > 3) {
$(this).next().find('.chosen-choices').find('li.search-choice').hide(),
$(this).next().find('.chosen-choices').find('.literal-multiple').show();
$(this).next().find('.chosen-choices').find('span.literal-multiple').text(placeholder + " ("+totalSelected+")");
}
});
The class literal-multiple is a custom element to show the totalSelected elements. You need to add it in the prototype of the chosen plugin:
file chosen.jquery.js
Chosen.prototype.set_up_html = function() {
//stuff
if(this.is_multiple) {
var selVal = this.default_text;
this.container.html('<ul class="chosen-choices"><span class="literal-multiple"></span></ul>');
}
};
SOrry I am unable to comment since I don't have enough reputation.
But to add to the previous answer, instead of adding a separate container,
why don't we just append the n users selected as a <li> item.
Something like this -
$('.element').chosen().change(function() {
var totalSelected = $(this).find('option:selected').size();
var placeholder = $(this).find('option:first-child').text();
if(totalSelected > 3) {
$(this).next().find('.chosen-choices').find('li.search-choice').hide(),
$(this).next().find('.chosen-choices')append('<li class="search-choice" <span>'+totalSelected+' users selected. </li>');
}
});
This seems to work for me.
I'm using the chosen plugin to build multiple select input fields. See an example here: http://harvesthq.github.io/chosen/#multiple-select
The default behavior disables an option if it has already been selected. In the example above, if you were to select "Afghanistan", it would be greyed out in the drop-down menu, thus disallowing you from selecting it a second time.
I need to be able to select the same option more than once. Is there any setting in the plugin or manual override I can add that will allow for this?
I created a version of chosen that allows you to select the same item multiple times, and even sends those multiple entries to the server as POST variables. Here's how you can do it (fairly easily, I think):
(Tip: Use a search function in chosen.jquery.js to find these lines)
Change:
this.is_multiple = this.form_field.multiple;
To:
this.is_multiple = this.form_field.multiple;
this.allows_duplicates = this.options.allow_duplicates;
Change:
classes.push("result-selected");
To:
if (this.allows_duplicates) {
classes.push("active-result");
} else {
classes.push("result-selected");
}
Change:
this.form_field.options[item.options_index].selected = true;
To:
if (this.allows_duplicates && this.form_field.options[item.options_index].selected == true) {
$('<input>').attr({type:'hidden',name:this.form_field.name,value:this.form_field.options[item.options_index].value}).appendTo($(this.form_field).parent());
} else {
this.form_field.options[item.options_index].selected = true;
}
Then, when calling chosen(), make sure to include the allows_duplicates option:
$("mySelect").chosen({allow_duplicates: true})
For a workaround, use the below code on each selection (in select event) or while popup opened:
$(".chosen-results .result-selected").addClass("active-result").removeClass("result-selected");
The above code removes the result-selected class and added the active-result class on the li items. So each selected item is considered as the active result, now you can select that item again.
#adam's Answer is working very well but doesn't cover the situation that someone wants to delete some options.
So to have this functionality, alongside with Adam's tweaks you need to add this code too at:
Chosen.prototype.result_deselect = function (pos) {
var result_data;
result_data = this.results_data[pos];
// If config duplicates is enabled
if (this.allows_duplicates) {
//find fields name
var $nameField = $(this.form_field).attr('name');
// search for hidden input with same name and value of the one we are trying to delete
var $duplicateVals = $('input[type="hidden"][name="' + $nameField + '"][value="' + this.form_field.options[result_data.options_index].value + '"]');
//if we find one. we delete it and stop the rest of the function
if ($duplicateVals.length > 0) {
$duplicateVals[0].remove();
return true;
}
}
....
Previously I asked how to do this and was directed to this:
<script>
jQuery.fn.filterByText = function(textbox) {
return this.each(function() {
var select = this;
var options = [];
$(select).find('option').each(function() {
options.push({value: $(this).val(), text: $(this).text()});
});
$(select).data('options', options);
$(textbox).bind('change keyup', function() {
var options = $(select).empty().scrollTop(0).data('options');
var search = $.trim($(this).val());
var regex = new RegExp(search,"gi");
$.each(options, function(i) {
var option = options[i];
if(option.text.match(regex) !== null) {
$(select).append(
$('<option>').text(option.text).val(option.value)
);
}
});
});
});
};
</script>
(http://www.lessanvaezi.com/filter-select-list-options/)
When I use this filter on the select box it filters both the unselected AND the selected. I'd like it to ONLY filter the unselected because if a user wants to ammend the selections and filters again, the previously selected items go away - unless they meet the filter criteria.
I'm not that good at JavaScript or JQuery and can't understand how I might tell the above script to ignore options that are ":selected" but filter all else.
Here's a jfiddle if it helps: http://jsfiddle.net/UmKXy/ I'd like option one and two to remain selected and in the list when user begins to type.
Thanks for help!
The solution you had would not work with selected elements because he created an array of options at the start and then matched those options against the regex(Without regards to what is actually selected). I've used spans to hide options in the past and created an example for you to see how it works. Here is the link : http://jsfiddle.net/rD6wv/
Here is the code
$(function() {
$("#filterByText").bind('keyup',function(){
var search = $.trim($(this).val());
var regex = new RegExp(search,"gi");
$("#filez").find('option').each(function(){
if(!$(this).is(':selected')){
if($(this).val().match(regex) === null) {
$(this).wrap('<span>');
}else if($(this).parent().is('span')){
$(this).parent().replaceWith($(this));
}
}
});
});
});
You simply need to loop through all the options of the select when you type in the textbox.
You then check if it is selected, if it is you do nothing, else you check if it matches the search filter, if it does you wrap it in a span, making it invisible, else it means you need to see it, so you check if it is already wrapped in a span, and in that case you replace it with the option so you can see it again.
to selected the non selected options, use this:
$('option:not[selected]') or $('#myselect > option:not[selected]')
to remove them, use this:
$('option:not[selected]').remove();
in css, :not filters for opposite of what comes in the curved brackets.
and [] is attribute selector.
so :not[selected] means: does not have an attribute whose key is "selected"
Is there a way that i can select multiple nth-childs at once like:
$("#table").find("tr > :not(td:nth-child(1,3,5))");
which doesn't work
I want to select all td in each row but not for column 1,3,5 (this can be any combination).
Is there a way to do this? I cannot assign classnames.
thanks for any help!
UPDATE:
I want to search in all rows of a table, but exclude some columns.
I have this code right now:
elem.keyup(function() {
$(options.table).find("tr").hide();
var data = this.value.split(" ");
var jo = $(options.table).find("tr > :not(td:nth-child("+cols+"))");
$.each(data, function(i, v){
jo = jo.filter(":containsIgnoreCase('"+v+"')");
});
jo.parent().show();
});
It works when I pass a single value, but i want to exclude multiple columns.
thanks
From your example, it looks like you're trying to exclude the odd numbers. Try:
$("#table").find("tr > :not(td:nth-child(odd))");
Although, it may be more efficient to just select the even ones.
$("#table").find("tr > td:nth-child(even)");
You can also use formulas in nth-child. See this link for more detail.
Okay, as per comments below/clarification on the question, here is another solution.
$("#table").find("tr > td").filter(function(index){
return index == 1 || index == 2 || index == 5;
});
I'm using jQuery isotope. Everything is ok but I have problem with filtering. I want to use multiple categories I have 5 checkboxes and I can't use them at the same time. What can I do?
$("#classic").click(function() {
if($("#classic").is(":checked")) {
$('#box').isotope({ filter: '.classic' });
} else {
$('#box').isotope({ filter: '' });
}
});
Example
my items = a,b,c,d,e,f,g,h
categories = x ( a,b,e) y (c,h) z(d,f,g)
now if I choose the x and z checkbox it only show the a,b,e,d,f,g
but I can't do that. How can I do ?
Here is a solution for checkbox filtering:
http://jsfiddle.net/3nY9V/6/
Looks like you have a js error in the code(missing single quote) and also at one place classic is used as an id and at another place as a class. Just wanted to find if thats not the issue. Try this.
function checkIsoTope(){
var ids = [];
$("#classic, #den, #wer").filter(":checked").each(function(){
ids.push("." + this.id);
});
$('#box').isotope({ filter: ids.join(',')});
}
$("#classic, #den, #wer, #allCheckboxId").click(checkIsoTope);