I'm trying to achieve jquery multi select dropdown with checkboxes with customized apply and cancel button inside dropdown. When I select Select All
, dropdown is closing unexpectedly, even I tried to use stopPropagation
but still it is closing the dropdown.
Any help would be highly appreciated
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MultiSelect with Fixed Select All</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- MultiSelect CSS & JS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/nobleclem/jQuery-MultiSelect/jquery.multiselect.css">
<script src="https://cdn.jsdelivr.net/gh/nobleclem/jQuery-MultiSelect/jquery.multiselect.min.js"></script>
</head>
<body>
<h2>Select Options</h2>
<select id="my-select" multiple>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="cherry">Cherry</option>
<option value="date">Date</option>
</select>
</body>
</html>
$(document).ready(function () {
$('#my-select').multiselect({
placeholder: 'Select fruits',
onControlOpen: function () {
const $optionsContainer = $('.ms-options');
// Add Select All checkbox once
if ($('.select-all-container').length === 0) {
const $selectAllContainer = $(`
<div class="select-all-container">
<label><input type="checkbox" id="select-all-checkbox"> Select All</label>
</div>
`);
$optionsContainer.prepend($selectAllContainer);
// Real fix: Stop mousedown before plugin closes the dropdown
$(document).on('mousedown', function (e) {
if ($(e.target).closest('.select-all-container').length) {
e.stopPropagation();
}
});
$('#select-all-checkbox').on('change', function () {
const isChecked = $(this).is(':checked');
$('#my-select option').prop('selected', isChecked);
$('#my-select').multiselect('reload');
});
}
// Add Apply/Cancel buttons once
if ($('.custom-button-wrapper').length === 0) {
const $wrapper = $('<div class="custom-button-wrapper"></div>');
const $apply = $('<button class="custom-button">Apply</button>').on('click', function () {
const selected = $('#my-select').val();
alert('Selected: ' + (selected ? selected.join(', ') : 'None'));
});
const $cancel = $('<button class="custom-button cancel">Cancel</button>').on('click', function () {
$('#my-select').val([]).multiselect('reload');
$('.ms-parent').find('.ms-drop').hide();
});
$wrapper.append($apply).append($cancel);
$optionsContainer.append($wrapper);
}
}
});
});
.custom-button {
display: inline-block;
margin: 10px 5px 5px;
padding: 5px 10px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.custom-button.cancel {
background-color: #dc3545;
}
.custom-button-wrapper {
text-align: center;
padding-bottom: 10px;
}
.select-all-container {
padding: 5px 10px;
border-bottom: 1px solid #ccc;
background: #f9f9f9;
user-select: none;
}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MultiSelect with Fixed Select All</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- MultiSelect CSS & JS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/nobleclem/jQuery-MultiSelect/jquery.multiselect.css">
<script src="https://cdn.jsdelivr.net/gh/nobleclem/jQuery-MultiSelect/jquery.multiselect.min.js"></script>
</head>
<body>
<h2>Select Options</h2>
<select id="my-select" multiple>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="cherry">Cherry</option>
<option value="date">Date</option>
</select>
</body>
</html>
We can enable selectAll
property in the multiselect options.
$(document).ready(function () {
$('#my-select').multiselect({
selectAll: true,
...
Then use CSS to not destroy (display: none
) but just hide (visibility:none
) and make it look hidden using (position: absolute; left:-9999px
) using the below CSS.
a.ms-selectall.global {
visibility: hidden;
position: absolute;
left: -9999px;
}
Finally on button click, we find this select all
element and click it.
$('#select-all-checkbox').on('change', function(e) {
e.preventDefault();
const isChecked = $(this).is(':checked');
// $('#my-select option').prop('selected', isChecked);
$('#select-all-checkbox').parents('.select-all-container').siblings('.ms-selectall.global').click();
$('#select-all-checkbox').prop('checked', checkAllSelected(element));
});
When the options are changed, we need to manage the state of the select all checkbox, for this we use the event onOptionClick
.
onOptionClick: function(element) {
$('#select-all-checkbox').prop('checked', checkAllSelected(element));
},
function checkAllSelected(selectElement) {
var selectedOptions = $(selectElement).find('option:selected');
var allOptions = $(selectElement).find('option');
return selectedOptions.length === allOptions.length;
}
$(document).ready(function() {
$('#my-select').multiselect({
selectAll: true,
placeholder: 'Select fruits',
onOptionClick: function(element) {
$('#select-all-checkbox').prop('checked', checkAllSelected(element));
},
onControlOpen: function(element) {
const $optionsContainer = $('.ms-options');
// Add Select All checkbox once
if ($('.select-all-container').length === 0) {
const $selectAllContainer = $(`
<div class="select-all-container">
<label><input type="checkbox" id="select-all-checkbox"> Select All</label>
</div>
`);
$optionsContainer.prepend($selectAllContainer);
// Real fix: Stop mousedown before plugin closes the dropdown
$(document).on('mousedown', function(e) {
if ($(e.target).closest('.select-all-container').length) {
e.stopPropagation();
}
});
$('#select-all-checkbox').on('change', function(e) {
e.preventDefault();
const isChecked = $(this).is(':checked');
// $('#my-select option').prop('selected', isChecked);
$('#select-all-checkbox').parents('.select-all-container').siblings('.ms-selectall.global').click();
$('#select-all-checkbox').prop('checked', checkAllSelected(element));
});
}
// Add Apply/Cancel buttons once
if ($('.custom-button-wrapper').length === 0) {
const $wrapper = $('<div class="custom-button-wrapper"></div>');
const $apply = $('<button class="custom-button">Apply</button>').on('click', function() {
const selected = $('#my-select').val();
$('#my-select').next('.ms-options-wrap').removeClass('ms-active');
alert('Selected: ' + (selected ? selected.join(', ') : 'None'));
});
const $cancel = $('<button class="custom-button cancel">Cancel</button>').on('click', function() {
$('#my-select').val([]).multiselect('reload');
$('.ms-parent').find('.ms-drop').hide();
});
$wrapper.append($apply).append($cancel);
$optionsContainer.append($wrapper);
}
}
});
});
.custom-button {
display: inline-block;
margin: 10px 5px 5px;
padding: 5px 10px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.custom-button.cancel {
background-color: #dc3545;
}
.custom-button-wrapper {
text-align: center;
padding-bottom: 10px;
}
.select-all-container {
padding: 5px 10px;
border-bottom: 1px solid #ccc;
background: #f9f9f9;
user-select: none;
}
a.ms-selectall.global {
visibility: hidden;
position: absolute;
left: -9999px;
}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MultiSelect with Fixed Select All</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- MultiSelect CSS & JS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/nobleclem/jQuery-MultiSelect/jquery.multiselect.css">
<script src="https://cdn.jsdelivr.net/gh/nobleclem/jQuery-MultiSelect/jquery.multiselect.min.js"></script>
</head>
<body>
<h2>Select Options</h2>
<select id="my-select" multiple>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="cherry">Cherry</option>
<option value="date">Date</option>
</select>
</body>
</html>