custom select to replace select-2
Some checks failed
Build and Push Docker Image / build (push) Failing after 7m5s
Some checks failed
Build and Push Docker Image / build (push) Failing after 7m5s
it's called 'corbz-select' because I suck at naming things
This commit is contained in:
parent
198d70d072
commit
5da1012718
@ -264,6 +264,12 @@ async function loadSubModalOptions($input, url) {
|
||||
|
||||
// Re-enable input
|
||||
$input.prop("disabled", false);
|
||||
|
||||
// Re-init the component
|
||||
if ($input.next('.corbz-select-container').length) {
|
||||
$input.next('.corbz-select-container').remove();
|
||||
$input.initCorbzSelect();
|
||||
}
|
||||
}
|
||||
|
||||
// Channel options aren't loaded from an API, like other options.
|
||||
@ -288,6 +294,12 @@ async function loadChannelOptions() {
|
||||
})
|
||||
|
||||
$input.prop("disabled", false);
|
||||
|
||||
// Re-init the component
|
||||
if ($input.next('.corbz-select-container').length) {
|
||||
$input.next('.corbz-select-container').remove();
|
||||
$input.initCorbzSelect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,3 +35,125 @@
|
||||
&:disabled, &.disabled { color: var(--bs-secondary-color) }
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Custom Select Component
|
||||
|
||||
.corbz-select {
|
||||
|
||||
}
|
||||
|
||||
.corbz-select-container {
|
||||
|
||||
position: relative;
|
||||
display: block;
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
font-weight: 400;
|
||||
color: var(--bs-body-color);
|
||||
background-color: var(--bs-body-bg);
|
||||
background-clip: padding-box;
|
||||
border: var(--bs-border-width) solid var(--bs-border-color);
|
||||
border-radius: var(--bs-border-radius-sm);
|
||||
|
||||
&.active {
|
||||
border-radius: var(--bs-border-radius-sm) var(--bs-border-radius-sm) 0 0;
|
||||
}
|
||||
|
||||
.corbz-select-selected {
|
||||
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
text-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
height: 100%;
|
||||
padding: 0.375rem 0.75rem;
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
|
||||
.corbz-select-dropdown {
|
||||
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
width: calc(100% + 2.25px);
|
||||
transform: translateX(-1px);
|
||||
background-color: var(--bs-body-bg);
|
||||
border: 1px solid var(--bs-border-color);
|
||||
border-radius: 0 0 var(--bs-border-radius-sm) var(--bs-border-radius-sm);
|
||||
box-shadow: var(--bs-box-shadow);
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
|
||||
.corbz-select-search {
|
||||
|
||||
// display: none; // disabled for now
|
||||
width: 100%;
|
||||
padding: 0.375rem 0.75rem;
|
||||
background: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--bs-border-color);
|
||||
outline: none;
|
||||
|
||||
}
|
||||
|
||||
.corbz-select-option {
|
||||
|
||||
padding: 0.375rem 0.75rem;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover { background-color: var(--bs-tertiary-bg); }
|
||||
&.active {
|
||||
|
||||
color: var(--bs-white);
|
||||
background-color: var(--bs-primary);
|
||||
|
||||
}
|
||||
|
||||
// Multi-select versions
|
||||
> .corbz-option-checkbox {
|
||||
|
||||
--bs-form-check-bg-image: none;
|
||||
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
appearance: none;
|
||||
background-color: var(--bs-body-bg);
|
||||
background-image: var(--bs-form-check-bg-image);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
border: var(--bs-border-width) solid var(--bs-border-color);
|
||||
border-radius: var(--bs-border-radius-sm);
|
||||
vertical-align: middle;
|
||||
|
||||
&:checked {
|
||||
|
||||
|
||||
--bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e");
|
||||
background-color: var(--bs-primary);
|
||||
border-color: var(--bs-primary);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
> span {
|
||||
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 0.75rem;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
<div class="col-lg-6 pe-lg-4">
|
||||
<div class="mb-4">
|
||||
<label for="subMessageStyle" class="form-label">Message Style</label>
|
||||
<select name="subMessageStyle" id="subMessageStyle" class="select-2" data-field="message_style" data-default="firstOption" tabindex="3">
|
||||
<select name="subMessageStyle" id="subMessageStyle" class="corbz-select" data-field="message_style" data-default="firstOption" tabindex="3">
|
||||
</select>
|
||||
<div class="form-text">Appearance of delivered content.</div>
|
||||
</div>
|
||||
@ -44,21 +44,21 @@
|
||||
<div class="col-lg-6 pe-lg-4">
|
||||
<div class="mb-4">
|
||||
<label for="subChannels" class="form-label">Channels</label>
|
||||
<select name="subChannels" id="subChannels" class="select-2" multiple data-field="channels" tabindex="5"></select>
|
||||
<select name="subChannels" id="subChannels" class="corbz-select" multiple data-field="channels" tabindex="5"></select>
|
||||
<div class="form-text">Send content to these channels.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 ps-lg-4">
|
||||
<div class="mb-4">
|
||||
<label for="subFilters" class="form-label">Filters</label>
|
||||
<select name="subFilters" id="subFilters" class="select-2" multiple data-field="filters" tabindex="6"></select>
|
||||
<select name="subFilters" id="subFilters" class="corbz-select" multiple data-field="filters" tabindex="6"></select>
|
||||
<div class="form-text">Filter out unwanted content.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 pe-lg-4">
|
||||
<div class="mb-4 mb-lg-0">
|
||||
<label for="subUniqueRules" class="form-label">Uniqueness Rules</label>
|
||||
<select name="subUniqueRules" id="subUniqueRules" class="select-2" multiple required data-field="unique_rules" tabindex="7"></select>
|
||||
<select name="subUniqueRules" id="subUniqueRules" class="corbz-select" multiple required data-field="unique_rules" tabindex="7"></select>
|
||||
<div class="form-text">Rules on telling content apart.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -82,6 +82,10 @@ $(document).ready(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$(".corbz-select").each(function() {
|
||||
$(this).initCorbzSelect();
|
||||
});
|
||||
|
||||
$.notify.addStyle("bootstrap", {
|
||||
html:
|
||||
'<div class="toast mt-3 overflow-hidden" role="alert">' +
|
||||
@ -102,4 +106,166 @@ $(document).ready(function() {
|
||||
|
||||
// Load theme
|
||||
initThemeChoice();
|
||||
});
|
||||
});
|
||||
|
||||
// Custom Select Jquery
|
||||
(($) => {
|
||||
function initCorbzSelect() {
|
||||
const defaultSelectedHtml = " ";
|
||||
|
||||
const updateSelectedDisplay = ($select, $selected, $dropdown, settings) => {
|
||||
const values = $select.val() || [];
|
||||
const names = [];
|
||||
|
||||
// Update names based on values
|
||||
$select.find("option").each(function() {
|
||||
if (values.includes($(this).val())) {
|
||||
names.push($(this).text());
|
||||
}
|
||||
});
|
||||
|
||||
console.log(JSON.stringify(names))
|
||||
|
||||
const len = values.length;
|
||||
const total = $select.find("option").length;
|
||||
|
||||
if (len === 0) { $selected.html(defaultSelectedHtml); }
|
||||
else if (len === total) {$selected.text("All Selected")}
|
||||
else if (len > 3) { $selected.text(`${values.length} Selected`); }
|
||||
else { $selected.text(names.join(", ")); }
|
||||
|
||||
if (!settings.multiple) {
|
||||
$dropdown.find(".corbz-select-option").removeClass("active").each(function() {
|
||||
if (names.includes($(this).data("name"))) {
|
||||
$(this).addClass("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$dropdown.find(".corbz-option-checkbox").each(function() {
|
||||
$(this).prop("checked", values.includes($(this).val()));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
this.each(function() {
|
||||
// The original select element, this will be hidden and replaced
|
||||
// with the custom input 'container'
|
||||
const $select = $(this);
|
||||
|
||||
// The custom input to replace the original select
|
||||
const $container = $('<div class="corbz-select-container">');
|
||||
|
||||
// Contains text indicating the 'selected' options, acts as a
|
||||
// button to open the dropdown.
|
||||
const $selected = $('<div class="corbz-select-selected">');
|
||||
$selected.html(defaultSelectedHtml);
|
||||
|
||||
// The dropdown box when accessing the container
|
||||
const $dropdown = $('<div class="corbz-select-dropdown">');
|
||||
|
||||
// Search input to filter the dropdown results
|
||||
const $search = $('<input type="text" class="corbz-select-search" placeholder="Search ...">');
|
||||
|
||||
const settings = {
|
||||
id: $select.prop("id"),
|
||||
multiple: $select.prop("multiple"),
|
||||
required: $select.prop("required"),
|
||||
disabled: $select.prop("disabled"),
|
||||
minResultsForSearch: 5
|
||||
}
|
||||
|
||||
// Add custom elements to the DOM
|
||||
$dropdown.prepend($search);
|
||||
$container.append($selected).append($dropdown);
|
||||
$select.hide().after($container);
|
||||
|
||||
// Show/Hide the dropdown when clicking the custom input
|
||||
$selected.on("click", function(event) {
|
||||
event.stopPropagation();
|
||||
$('.corbz-select-dropdown').not($dropdown).hide();
|
||||
$dropdown.toggle();
|
||||
$container.toggleClass("active", $dropdown.is(":visible"));
|
||||
});
|
||||
|
||||
// Hide dropdown if clicking outside
|
||||
$(document).on('click', function() {
|
||||
$dropdown.hide();
|
||||
$container.removeClass("active");
|
||||
|
||||
// Reset search filtering
|
||||
$search.val("");
|
||||
$search.trigger("keyup");
|
||||
});
|
||||
|
||||
// Use or hide search
|
||||
$search.toggle($select.find("option").length > settings.minResultsForSearch);
|
||||
|
||||
// Prevent closing the dropdown when selecting the search input
|
||||
$search.on("click", function (event) { event.stopPropagation(); });
|
||||
|
||||
// Search to filter through options
|
||||
$search.on("keyup", function () {
|
||||
const searchValue = $(this).val().toLowerCase();
|
||||
$dropdown.find(".corbz-select-option").each(function() {
|
||||
const optionText = $(this).text().toLowerCase();
|
||||
$(this).toggle(optionText.includes(searchValue))
|
||||
})
|
||||
});
|
||||
|
||||
const updateSelectedDisplayWrapper = () => {
|
||||
updateSelectedDisplay($select, $selected, $dropdown, settings)
|
||||
}
|
||||
|
||||
$select.find("option").each(function() {
|
||||
const $option = $('<div class="corbz-select-option">');
|
||||
$option.data("name", $(this).text());
|
||||
$option.data("value", $(this).val());
|
||||
|
||||
if (!settings.multiple) {
|
||||
$option.text($(this).text());
|
||||
$option.on("click", function() {
|
||||
$dropdown.hide();
|
||||
$container.removeClass("active");
|
||||
$select.val($option.data("value"));
|
||||
updateSelectedDisplayWrapper();
|
||||
});
|
||||
}
|
||||
else {
|
||||
const $checkbox = $(`<input type="checkbox" name="${settings.id}" class="corbz-option-checkbox" value="${$(this).val()}">`).val($(this).val());
|
||||
const $label = $("<span>").text($(this).text());
|
||||
$option.prepend($checkbox).append($label);
|
||||
$option.on("click", function(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
// Handle if the user clicked inside the checkbox itself
|
||||
if (!$(event.target).hasClass("corbz-option-checkbox")) {
|
||||
$checkbox.prop("checked", !$checkbox.prop("checked"));
|
||||
}
|
||||
|
||||
const selectedElems = $dropdown.find(`input[type="checkbox"][name="${settings.id}"]:checked`).map(function() {
|
||||
return $(this).closest(".corbz-select-option");
|
||||
});
|
||||
|
||||
// Get and internally set the selected values
|
||||
const selectedVals = selectedElems.map(function() {
|
||||
return this.data("value");
|
||||
});
|
||||
$select.val(selectedVals).trigger("change");
|
||||
|
||||
updateSelectedDisplayWrapper();
|
||||
});
|
||||
}
|
||||
|
||||
$dropdown.append($option)
|
||||
});
|
||||
|
||||
// Initialize display, and detect future changes
|
||||
updateSelectedDisplayWrapper();
|
||||
$select.on("change", updateSelectedDisplayWrapper);
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.initCorbzSelect = initCorbzSelect;
|
||||
|
||||
})(jQuery);
|
||||
|
Loading…
x
Reference in New Issue
Block a user