Select2 with Primary selected option
Set a Select2 option as Primary, with visual feedback and a hidden form field to relay the Primary selected item with the form data.
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.css">
<label for="Troops">Troops</label>
<select name="Troops" id="Troops" multiple="" class="primary-selectable">
<option value="1">Barbarian</option>
<option value="2">Archer</option>
<option value="3">Goblin</option>
<option value="4">Giant</option>
<option value="5" selected="selected">Wall Breaker</option>
<option value="6">Balloon</option>
<option value="7" selected="selected">Wizard</option>
<option value="8">Healer</option>
<option value="9">Dragon</option>
<option value="10" selected="selected">P.E.K.K.A.</option>
<option value="11">Minion</option>
<option value="12">Hogrider</option>
<option value="13">Valkyrie</option>
<option value="14" selected="selected">Golem</option>
<option value="15" selected="selected">Witch</option>
<option value="16">Lava Hound</option>
<option value="17" selected="selected">Barbarian King</option>
<option value="18" selected="selected">Archer Queen</option>
</select>
<div style="height: 20px"></div>
<label>Primary Troop</label>
<input type="hidden" id="TroopsPrimary" name="TroopsPrimary" value="17">
<span id="TroopsPrimaryDisplay"></span>
<span id="TroopsPrimaryDisplayNone">No Primary Troop selected</span>
<div class="who">Written by <a target="_top" href="http://www.hughanderson.com">Hugh Anderson</a>
<br>View the <a target="_top" href="http://www.programico.com/smartjs-blog/click-on-a-select2-item-to-set-it-as-primary">Blog Post</a></div>
CSS
/* http://www.cssportal.com/css-gradient-generator/ */
.select2-container-multi .select2-choices .select2-search-choice.select2-primary {
background-color: green;
border-color: green;
background-image: -ms-linear-gradient(top, #5CBD73 0%, #79EF70 50%, #24E23D 51%, #1F9C49 100%);
background-image: -moz-linear-gradient(top, #5CBD73 0%, #79EF70 50%, #24E23D 51%, #1F9C49 100%);
background-image: -o-linear-gradient(top, #5CBD73 0%, #79EF70 50%, #24E23D 51%, #1F9C49 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #5CBD73), color-stop(50, #79EF70), color-stop(51, #24E23D), color-stop(100, #1F9C49));
background-image: -webkit-linear-gradient(top, #5CBD73 0%, #79EF70 50%, #24E23D 51%, #1F9C49 100%);
background-image: linear-gradient(to bottom, #5CBD73 0%, #79EF70 50%, #24E23D 51%, #1F9C49 100%);
}
/* visibility is handled by JavaScript */
#TroopsPrimaryDisplay, #TroopsPrimaryDisplayNone {
display: none;
}
#TroopsPrimaryDisplayNone {
font-style: italic;
color: #888;
}
#Troops {
width: 100%;
}
body {
font-family: sans-serif;
}
label {
font-weight: bold;
}
/* if using Bootstrap this will happen automatically, i'm just setting it to full width here */
.select2-container {
display: block;
}
.who {
margin-top:3em;
font-style:italic;
font-size:smaller;
text-align: right;
}
JavaScript
// set up a facade to handle interacting with the PrimarySelect2
function PrimarySelect2($element, s2Options) {
// reality check
if (!$element || !$element.length) return;
// implementing on more than one item is left as an exercise for the reader. suggest jQuery plugin pattern
$element = $element.first();
// pass the options straight through to Select2
$element.select2(s2Options);
// get a handle to the Select2 api
var s2Instance = $element.data('select2');
// trigger special behavior by adding this class in the markup
if ($element.hasClass('primary-selectable')) {
// using the id of the select2'd form control, we look for additional fields on the page to populate, via a Naming Convention
var formKey = $element.attr('id');
var primary = {
// a hidden field to populate with the Primary selected item's id
$hidden: $('#' + formKey + 'Primary'),
// a place to display the text of the Primary selected item
$display: $('#' + formKey + 'PrimaryDisplay'),
// a holder for a feedback message when there's no Primary selected item
$displayNone: $('#' + formKey + 'PrimaryDisplayNone'),
};
function selectPrimary($item, detect) {
// if we pass detect, we want to read the state from the UI
if (detect) {
$item = $('.select2-search-choice.select2-primary', s2Instance.container).first();
} else {
// if nothing was passed, just get the first one
$item = $item || $('.select2-search-choice', s2Instance.container).first();
if (!$item.length) return;
$item.toggleClass('select2-primary').siblings().removeClass('select2-primary');
}
var s2Data = null, newValue = null;
if ($item.hasClass('select2-primary')) {
s2Data = $item.data('select2Data');
...