Yes, you're right. Select2 does remove the events on the dropdown container. Here's the line in the library that does that:
this.$dropdownContainer.on('mousedown', function (evt) {
evt.stopPropagation();
});
Solution:
- Get the instance of select2
- Bind events and check if the mousedown is on the status's span using jQuery closest.
Here's how:
var selectInst = $(".form-control").data('select2');
selectInst.$results.on('mousedown', function (e) {
if($(e.target).closest('.statuses span').length) {
var data = $(e.target).parents('li[aria-selected]').data('data').text || null;
alert('Clicked \"' + $(e.target).html() + '\" from the value: ' + data);
}
});
Putting together the above, here's a snippet:
$(".form-control").select2({
templateResult: formatSelect2,
});
var selectInst = $(".form-control").data('select2');
selectInst.$results.on('mousedown', function (e) {
if($(e.target).closest('.statuses span').length) {
var data = $(e.target).parents('li[aria-selected]').data('data').text || null;
alert('Clicked \"' + $(e.target).html() + '\" from the value: ' + data);
}
});
function formatSelect2 (data) {
if (!data.id) { return data.text; }
var $data = $(
'<span data-status="' + data.element.getAttribute("data-status") + '">' + data.text + '<span class="statuses"><span data-status="1">1</span><span data-status="2">2</span><span data-status="3">3</span></span></span>'
);
return $data;
}
.statuses {
margin-left: 8px;
}
.statuses span {
margin-left: 8px;
cursor: pointer;
}
.statuses span:hover {
margin-left: 8px;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.js"></script>
<select class="form-control" style="width: 300px">
<option selected="selected" data-status="1">orange</option>
<option>white</option>
<option>purple</option>
</select>
EDIT:
For multiple instances of select2, here's one approach:
Apply the same above logic to all the instances.
I've added a class render_select2 to all selects for which select2 is going to be initialized. Using that class, here's how the above can be applied for all the instances:
$(".render_select2").each(function () {
var selectInst = $(this).data('select2');
selectInst.$results.on('mousedown', function (e) {
if($(e.target).closest('.statuses span').length) {
var data = $(e.target).parents('li[aria-selected]').data('data').text || null;
alert('Clicked \"' + $(e.target).html() + '\" from the value: ' + data);
}
});
});
$(".form-control").select2({
templateResult: formatSelect2,
});
$(".render_select2").each(function () {
var selectInst = $(this).data('select2');
selectInst.$results.on('mousedown', function (e) {
if($(e.target).closest('.statuses span').length) {
var data = $(e.target).parents('li[aria-selected]').data('data').text || null;
alert('Clicked \"' + $(e.target).html() + '\" from the value: ' + data);
}
});
});
function formatSelect2 (data) {
if (!data.id) { return data.text; }
var $data = $(
'<span data-status="' + data.element.getAttribute("data-status") + '">' + data.text + '<span class="statuses"><span data-status="1">1</span><span data-status="2">2</span><span data-status="3">3</span></span></span>'
);
return $data;
}
.statuses {
margin-left: 8px;
}
.statuses span {
margin-left: 8px;
cursor: pointer;
}
.statuses span:hover {
margin-left: 8px;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.js"></script>
<select class="form-control render_select2" style="width: 300px">
<option selected="selected" data-status="1">orange</option>
<option>white</option>
<option>purple</option>
</select>
<select class="form-control render_select2" style="width: 300px">
<option selected="selected" data-status="1">orange1</option>
<option>white1</option>
<option>purple1</option>
</select>
EDIT 2: Avoiding each
and using select2:select
event:
Using the in-built event, here' the change:
$(".form-control").on('select2:select', function (evt) {
var origEvent = evt.params.originalEvent;
if($(origEvent.target).closest('.statuses span').length) {
var data = $(origEvent.target).parents('li[aria-selected]').data('data').text || null;
alert('Clicked \"' + $(origEvent.target).html() + '\" from the value: ' + data);
}
});
$(".form-control").select2({
templateResult: formatSelect2,
});
$(".form-control").on('select2:select', function (evt) {
var origEvent = evt.params.originalEvent;
if($(origEvent.target).closest('.statuses span').length) {
var data = $(origEvent.target).parents('li[aria-selected]').data('data').text || null;
alert('Clicked \"' + $(origEvent.target).html() + '\" from the value: ' + data);
}
});
function formatSelect2 (data) {
if (!data.id) { return data.text; }
var $data = $(
'<span data-status="' + data.element.getAttribute("data-status") + '">' + data.text + '<span class="statuses"><span data-status="1">1</span><span data-status="2">2</span><span data-status="3">3</span></span></span>'
);
return $data;
}
.statuses {
margin-left: 8px;
}
.statuses span {
margin-left: 8px;
cursor: pointer;
}
.statuses span:hover {
margin-left: 8px;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.js"></script>
<select class="form-control render_select2" style="width: 300px">
<option selected="selected" data-status="1">orange</option>
<option>white</option>
<option>purple</option>
</select>
<select class="form-control render_select2" style="width: 300px">
<option selected="selected" data-status="1">orange1</option>
<option>white1</option>
<option>purple1</option>
</select>
Hope this helps (and btw I've used v4.5 for this as the v4.6-rc seems like it's in beta stage)