Is there a way to create multiple selectbox's with same values populated using Chosen plugin or Select2.
Conditions:
All the selectbox's should have same values
Single Select for each selectbox
Options cannot be selected twice in all of the selectbox's (eg:
A,B,C.. are options, where A can be selected only once)
Option to add custom values in the selectbox, which is updated to
all selectbox's
Selected values are disabled in rest of the selectbox's
So, there are a few questions within here, I'll give a separate answer for all of them. Note that I am the maintainer of Select2, so all of my answers are for Select2. Some will apply to Chosen, but I can't guarantee it.
The full code is available at the bottom of this answer, as a complete runnable Stack Snippet. Individual snippets will be included beneath the questions when available.
All the selectbox's should have same values
This is something that you should be able to do without Select2 or Chosen, as it is all a matter of cloning the contents of one <select> to the rest of them. This can be as a simple as
$("select").html($(".main-select").html());
Which will make sure that all <select> boxes have the same options as the one with the class of main-select.
Single Select for each selectbox
Both Select2 and Chosen determine if multiple selections are allowed based on whether or not you specify the multiple attribute on your <select>. So the easy solution here is to never include it, and all of the select boxes will only allow a single selection.
Options cannot be selected twice in all of the selectbox's (eg: A,B,C.. are options, where A can be selected only once)
This one is more difficult, and the implementation will all depend on how each plugin can handle disabling options on the fly. Both plugins will trigger the change event when the value of the <select> changes, so you can detect when a new option is selected and disable it in the other <select> boxes. Both plugins determine if an option can be selected by checking the disabled property on the <option>, just like a browser would, so you will want to use that.
The trick here is to detect the value of the newly selected option and disable all other <option> elements in other <select> boxes that have that same value.
$select2.find("option:not(:selected)").filter(function () {
return this.value == val;
}).prop("disabled", true);
Note that due to a current bug in Select2, you will need to call removeData("data") on those <option> elements to clear the cached data for the element.
Option to add custom values in the selectbox, which is updated to all selectbox's
Select2 allows you to enable custom values by setting tags: true when initializing Select2. Chosen does not have the ability to add custom values, so that may be a deal breaker.
Selected values are disabled in rest of the selectbox's
This is solved when solving 3.
var $select2 = $(".select2");
// Copy the options to all selects based on the first one
$("select").html($select2.first().html());
// Initialize Select2
$select2.select2({
allowClear: true,
placeholder: "Select an option",
tags: true
});
// Handle disabling already-selected options
$select2.on("change", function () {
$select2.find("option:disabled").prop("disabled", false).removeData("data");
$select2.each(function () {
var val = $(this).val();
$select2.find("option:not(:selected)").filter(function () {
return this.value == val;
}).prop("disabled", true).removeData("data");
});
});
body { margin: 0; }
.select2 { width: 200px; }
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/css/select2.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.js"></script>
<select class="select2">
<option></option>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
</select>
<select class="select2"></select>
<select class="select2"></select>
<select class="select2"></select>
Related
I have a webpage and I need to allow the user to select or de-select from predefined keywords from a list.
Something like the tags below in stackoverflow where the user can only select or de-select predefined keywords.
Also when the user returns to the site, he must be able to see his old selections and edit them at anytime.
For example maybe can have two columns like this
UNSELECT SELECTED
-------------------
A
B
C
D
E
F
G
[ --> ] select button
[ <-- ] unselect button
So there are two columns FROM and TO, then buttons allowing the user to move items back and forth between the two columns.
Doesnt have to be two columns, but any method that allows the user to only select predefined words, se-select any keyword, and can edit them later when they return to the site.
Anybody knows how to do this?
I guess you can use a library like multiSelect, and save user selection to a cookie or browser's local storage.
$('#callbacks').multiSelect({
afterSelect: function(values) {
alert("Select value: " + values);
},
afterDeselect: function(values) {
alert("Deselect value: " + values);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/multi-select/0.9.12/css/multi-select.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/multi-select/0.9.12/js/jquery.multi-select.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/multi-select/0.9.12/css/multi-select.css" rel="stylesheet" />
<select id='callbacks' multiple='multiple'>
<option value='elem_1'>elem 1</option>
<option value='elem_2'>elem 2</option>
<option value='elem_3'>elem 3</option>
<option value='elem_4'>elem 4</option>
<option value='elem_100'>elem 100</option>
</select>
jsfiddle
At a high-level, you'll basically want to maintain two lists (in JavaScript), one for everything in the first column, one for everything in the second column.
Probably a <select> with multiple will give you the UI you want. You can build this dynamically using the JavaScript you have in the lists (How to populate the options of a select element in javascript).
When they click one of the buttons to move them, with a <select> you can loop through the <option> elements it contains, see which are checked, move them to the other JavaScript list, then re-render your select elements. (How to get all selected values from <select multiple=multiple>?)
As for making them reload when users come back, there are lots of ways to do that. The most common would be to store it in a database, which would require back-end development (Node.JS, PHP, Java, etc.).
Another way would be to use either LocalStorage or cookies.
I faced with a strange behaviour of select element. So, I have a select element with several options. One of option is empty - it's required by plugin to output placeholder.
I needed functionality that would clear selected options and I wrote something like:
$(element).val('');
$(element).find("option:selected").removeAttr("selected");
The thing is that "selected" attribute is still here and it's on old option - you can see it in the code sample.
So, I have 2 questions:
1) Why .val() method of jQuery library do not update "selected" attribute in options list?
2) Why I can not update "selected" attribute in my case? If I switch these statements it's working:
$(element).find("option:selected").removeAttr("selected");
$(element).val('');
Code sample:
$(function(){
$("#unselect").click(function(){
$("#lang_type").val('');
$("#lang_type").find("option:selected").removeAttr("selected");
alert($("#lang_type").html());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<select id="lang_type">
<option value=""></option>
<option value="01">01 - Language of text</option>
<option value="02">02 - Original language of a translated text</option>
<option selected="selected" value="03">03 - Language of abstracts</option>
<option value="04">04 - Rights language</option>
<option value="05">05 - Rights-excluded language</option>
<option value="06">06 - Original language in a multilingual edition</option>
<option value="07">07 - Translated language in a multilingual edition</option>
<option value="08">08 - Language of audio track</option>
<option value="09">09 - Language of subtitles</option>
</select>
<button id="unselect">Unselect</button>
EDIT:
You can use prop(false) property like this
$(function(){
$("#unselect").click(function(){
$("#lang_type").val('');
$("#lang_type").find("option:selected").prop('selected',false);
});
});
Like #yezzz said, read this :
Note: Do not use removeProp() method to remove native properties such as checked, disabled, or selected. This will remove the property completely and, once removed, cannot be added again to element. Use .prop() to set these properties to false instead.
If I'm not mistaken, a multi-select can be initially unselected, but once any option is selected, it can not be unselected any more. RFC 1866 states in section 8.1.3:
The initial state has the first option selected, unless a SELECTED attribute is present on any of the elements.
This lets me to believe that one option MUST always be selected. Obviously, different browsers interpret this differently...
But it does not seem to be a jQuery issue, rather a browser implementation issue.
The selected attribute reflects merely the initial state of the select input. You shouldn't really care about removing it, as it affects nothing once a different option is selected (either by the user or by a script on your page).
The current state of the input can be read or modified via the selectedIndex property, where a value of -1 means no option is selected (which never is the default, as there always is an option selected initially). However, you seem to want to select a particular "empty" option.
Setting the value on a select box results in the corresponding option being selected, which, in your case, is the very first one.
The code probably does exactly what you want. So don't mind checking the HTML, as the selected attribute - again - is unrelated to the current state of the input.
The :selected selector, however, matches the elements that are currently selected. Your first snippet selects an option, thus making it :selected, then attempts to remove a non-existent attribute from it. The second snippet of yours assumes that the selection remains on the option that was initially selected, and then removes the attribute from it. What follows is the "empty" option getting selected, and no more steps need to be taken, as that's all it takes to select an option.
To summarize: you can safely drop all the code that deals with the removal of the selected attribute, as it doesn't affect the current state of the element, the state being already tied to the correct option.
How would you go about having tags already being preselected in their selectbox at the time the page loads? Here's my code so far:
HTML:
<select class="selectBox operatingSystems" multiple="multiple">
<option>Windows</option>
<option>OSX</option>
<option>Linux</option>
</select>
JS:
$(".operatingSystems").select2({tags: true, tokenSeparators: [',', ' ']});
I'm basically trying to get it to look something like it does on the select2 documentation page where they have "orange" and "purple" preselected. From: https://select2.github.io/examples.html#data-ajax
You can select an existing option by setting the selected property.
<select class="selectBox operatingSystems" multiple="multiple">
<option>Windows</option>
<option selected="selected">OSX</option>
<option>Linux</option>
</select>
Would pre-select the OSX option in the select box. This isn't specific to Select2, it's how you set a pre-selected option in general for select boxes (both single and multiple select).
You can do this using vanilla JavaScript by setting the selected property on the element.
theOption.selected = true;
Or using jQuery's .val method for setting the value.
$("select").val(["OSX"])
In order for Select2 and other plugins to pick up the change in value, you may need to trigger the change event.
$("select").trigger("change")
http://jsfiddle.net/E2AMX/ has the exact demonstration of the problem, which is:
I have multiple select boxes on the same page. All the options of the selectboxes are in the given form:
<option value="#id_num">StringVal</option>
and i have one observableArray (say idlist) of id_nums with no separation regarding selectboxes. For example,
idlist = ko.observableArray([1,2,3,4]);
and the selectboxes are as
<select name="first" data-bind="selectedOptions: idlist">
...
<option value="2">Blah</option>
<option value="3">Blah</option>
...
</select>
<select name="second" data-bind="selectedOptions: idlist">
...
<option value="1">Blah</option>
...
</select>
<select name="third" data-bind="selectedOptions: idlist">
...
<option value="4">Blah</option>
...
</select>
My problem is: when i select one option from a selectbox, other selectboxes return to their initial states. This is directly related to selectedOptions, for if i remove the selectedOptions directive, this problem does not occur.
Any suggestions will be very welcomed.
Thanks.
The selectedOptions binding is meant to be used on a single <select> tag with multi-select enabled. It will keep an array of each item in the options box selected.
The reason you are seeing the behavior you are is because when you you select a single value from one of the drop downs, the selectedOptions binding immediately fires. The logic goes something like this:
Update on target <select> fires.
Binding extracts the value from <option> and updates the underlying observable array.
Observable array fires update since values have changed.
Secondary drop downs respond to update, and update their selected value based on what is in the array.
Since no value exists in the set of <option> tags, the value is cleared.
This is why you are seeing this behavior. If you want to collect a composite from all selected options, then you will either need to write a new custom binding, or create a seperate array for each <select> you want to bind to.
I have a set of drop down lists (8 in all). All drop downs have the same set of drop down options available to them. However the business requirement is to make sure that the user cannot select the same option more than once.
Looking at the problem, at first it appears simple but it's rapidly becoming lots of code. However it seems like a relatively common problem. Does anyone know of a solution, have any tips on how to do this without writing reams of Javascript. Some sort of reusable jquery plugin might be handy for this too. Does one exist?
One issue is that when a select item is chosen, it then becomes unavailable to the other select lists. The item is removed from the other select drop downs. When it becomes available again (a drop down changes) it needs to be inserted at the correct point in the list (the drop down options have an order). This is the bit where my solution has started to get quite complex.
Personally, the way I'd implement it is to have a "master" drop down containing all possible options, simply for the purpose of caching. These options are then replicated in each of the "slave" drop downs. Whenever any slave drop down is changed, they're all re-populated again to ensure that no two drop downs can share the same selected value.
For the purpose of demonstration, I've only worked with 3 drop down lists in the code below, but it should scale up pretty easily. Just add mode drop downs and make sure they contain the attribute class="slave".
Also, if you want any of the options to be immune from being removed, so that it's possible to exist in all of your slave drop downs (such as the default option in the code below), just add the attribute class="immune" to the option tag in the master drop down.
<script type="text/javascript">
// document - on load
$(document).ready(function() {
// initially populate all the drop downs
PopulateAllDropDowns();
// populate all drop downs on each subsequent change
$('select.slave').change(function(){
PopulateAllDropDowns();
});
});
function PopulateAllDropDowns()
{
// populate all the slave drop downs
$('select.slave').each(function(index){
PopulateDropDown($(this).attr('id'));
});
}
function PopulateDropDown(id)
{
// preserve the selected value
var selectedValue = $('#'+id).val();
// clear current contents
$('#'+id).html('');
// attempt to add each option from the master drop down
$('select#ddlTemplate').children('option').each(function(index){
// scope-safe var
var masterOptionValue = $(this).val();
// check if option is in use in another slave drop down, unless it's immune
var optionInUse = false;
if (!$(this).hasClass("immune"))
{
$('select.slave option:selected').each(function(index){
if (masterOptionValue == $(this).val() )
optionInUse = true;
});
}
// if it's not in use, add it to this slave drop down
if (!optionInUse)
{
// create new option
var newOption = $('<option></option>').val($(this).val()).html($(this).text());
// ensure selected value is preserved, if applicable
if (selectedValue == $(this).val())
newOption.attr('selected', 'selected')
// add the option
$('#'+id).append(newOption);
}
});
}
</script>
<form>
<!-- master drop down -->
<select id="ddlTemplate" class="master" style="display:none">
<option value="" class="immune">Select ...</option>
<option value="a">Option A</option>
<option value="b">Option B</option>
<option value="c">Option C</option>
<option value="d">Option D</option>
<option value="e">Option E</option>
</select>
<!-- slave drop downs -->
<select id="ddlOne" class="slave"></select>
<select id="ddlTwo" class="slave"></select>
<select id="ddlThree" class="slave"></select>
</form>
Hope that helps.
The simplest way to do what you want is binding a function in the select event from dropdown list that filter content from all other dropdowns and remove or disable the options with value already selected.
To keep the order from your list, cache the options list in array, then you can remove and add in the right position, or remove all options and re-add the current possible options.
If you want re-select the cached already chosen options, and you don't lose anything.