Corban-Lee af3f019552
Some checks failed
Build and Push Docker Image / build (push) Failing after 7m14s
move filter dropdown into search group
2024-11-12 20:35:03 +00:00

284 lines
10 KiB
JavaScript

const getStoredTheme = () => localStorage.getItem("theme");
const setStoredTheme = theme => localStorage.setItem("theme", theme);
const getPreferredTheme = () => window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
$('input[name="themeToggle"]').on("change", function() {
const selectedTheme = $(this).val();
setStoredTheme(selectedTheme);
setThemeIcon(selectedTheme)
applyTheme(selectedTheme);
});
// on page load
function initThemeChoice() {
const theme = getStoredTheme() || "auto"; // If the user is new, they won't have a set theme, so default to auto
setThemeIcon(theme);
applyTheme(theme);
}
function setThemeIcon(theme) {
const iconOptions = {
light: "bi-sun",
dark: "bi-moon-stars",
auto: "bi-circle-half"
}
if (!Object.keys(iconOptions).includes(theme)) {
throw new Error(`No icon for theme: ${theme}`);
}
$(".js-themeMenuBtn > i").removeClass(Object.values(iconOptions).join(" "));
$(".js-themeMenuBtn > i").addClass(iconOptions[theme]);
}
function applyTheme(theme) {
$('input[name="themeToggle"]').siblings("label").removeClass("active");
$(`input[name="themeToggle"][value="${theme}"]`).siblings("label").addClass("active");
if (!theme || theme === "auto") {
theme = getPreferredTheme();
}
$("body").attr("data-bs-theme", theme);
}
function getCurrentDateTime() {
var now = new Date();
var year = now.getFullYear();
var month = String(now.getMonth() + 1).padStart(2, '0');
var day = String(now.getDate()).padStart(2, '0');
var hours = String(now.getHours()).padStart(2, '0');
var minutes = String(now.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day}T${hours}:${minutes}`;
}
// Sanitise a given string to remove HTML, making it DOM safe.
function sanitise(string) {
if (typeof string !== "string") {
return string;
}
const map = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
"/": '&#x2F;',
};
const reg = /[&<>"'/]/ig;
return string.replace(reg, (match) => map[match]);
}
$(document).ready(function() {
// Activate all tooltips
$('[data-bs-toggle="tooltip"]').tooltip();
// Activate select2s
$(".select-2").each(function() {
$(this).select2({
theme: "bootstrap",
minimumResultsForSearch: 10
});
});
$(".corbz-select").each(function() {
$(this).initCorbzSelect();
});
$.notify.addStyle("bootstrap", {
html:
'<div class="toast mt-3 overflow-hidden" role="alert">' +
'<div class="toast-body">' +
'<span data-notify-text></span>' +
'</div>' +
"</div>"
});
$.notify.defaults({
globalPosition: "bottom right",
animationType: "fade",
className: "success"
});
// Activate datepickers
// $(".input-group.date").datepicker({format: "yyyy-mm-dd"});
// Load theme
initThemeChoice();
});
// Custom Select Jquery
(($) => {
function initCorbzSelect() {
const defaultSelectedHtml = "&nbsp;";
const updateSelectedDisplay = ($select, $selected, $dropdown, settings) => {
let values = $select.val() || [];
let names = [];
// if (settings.id === "styleTitleMutator") { debugger; }
if (!Array.isArray(values)) { values = [values] };
// Update names based on values
$select.find("option").each(function() {
if (values.includes($(this).val())) {
names.push($(this).text());
}
});
const len = values.length;
const total = $select.find("option").length;
if (len === 0) { $selected.html(defaultSelectedHtml); }
else if (len === total && total > 3) {$selected.text("All Selected")}
else if (len > 3) { $selected.text(`${values.length} Selected`); }
else { names ? $selected.text(names.join(", ")) : $selected.html(defaultSelectedHtml); }
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" tabindex="0">');
// 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();
$(".corbz-select-container").not($container).removeClass("active");
$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)
}
const onOptionSelect = $option => {
$dropdown.hide();
$container.removeClass("active");
$select.val($option.data("value"));
updateSelectedDisplayWrapper();
}
$select.find("option").each(function() {
const $option = $('<div class="corbz-select-option" tabindex="0">');
$option.data("name", $(this).text());
$option.data("value", $(this).val());
if (!settings.multiple) {
$option.text($(this).text());
$option.on("click", () => onOptionSelect($option));
}
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)
});
// For no options, display a message
if (!$select.find("option").length) {
const $noOptions = $('<div class="corbz-select-text">');
$noOptions.text("No options available");
$dropdown.append($noOptions);
}
// Initialize display, and detect future changes
updateSelectedDisplayWrapper();
$select.on("change", updateSelectedDisplayWrapper);
});
}
$.fn.initCorbzSelect = initCorbzSelect;
})(jQuery);