eesyphp/static/js/app.js
Benjamin Renard 4f2259f118
Add some useful UI helpers
- Add alertify lib and provide its default configuration
- Add copy_to_clipboard() function and the CSS copyable class
- Enable Bootstrap tooltips
- Add CSS share-links class helper: link's URL is copied to clipboard
- Add Bootstrap 5 like 3-states switches
- Add show_form_modal(), validate_form() and handle_ajax_return() helper functions
2024-12-02 20:01:51 +01:00

231 lines
6.8 KiB
JavaScript

$(document).ready(function () {
// Enable share links
$(".share-links").each(function (idx, link) {
link = $(link);
link.attr("data-bs-toggle", "tooltip");
if (!link.attr("data-bs-placement")) link.attr("data-bs-placement", "left");
if (!link.attr("title"))
link.attr("title", _("Copy the share URL of this page."));
$(link).click(function (event) {
event.preventDefault();
copy_to_clipboard($(link).attr("href"));
});
});
// Enable tooltip
$('[data-bs-toggle="tooltip"]').tooltip();
$(".copyable")
.click(function (event) {
copy_to_clipboard($(event.target).html().trim());
})
.css("cursor", "copy");
// Enable 3-states switches
$("input.form-3s-switch").each(function (idx, input) {
input = $(input);
input.click(function (event) {
event.preventDefault();
let value = input.attr("value");
if (value == "1") value = null;
else if (value == "0") value = "1";
else value = "0";
input.val(value);
input.prop("checked", value !== null);
input.trigger("change");
});
});
});
/**
* Copy a value to clipboard
* @param {string} value The value to copy to clipboard
*/
function copy_to_clipboard(value) {
var txt = $("<textarea>");
txt.html(value);
$(document.body).append(txt);
txt.select();
document.execCommand("copy");
txt.remove();
alertify.notify(_("Copied!"), "success", 5);
}
/**
* Load and show a form in a modal
* @param {object} opts Options:
* {
* form_url: [URL of the form content],
* title: [modal title],
* validate_url: [The url to send the form data to],
* method: [send method (optional, default: POST)],
* json: [
* if true, send form data as JSON in the body of the request, otherwise,
* send them as x-www-form-urlencoded data
* ],
* loading_message: [loading message (optional)],
* validate_error: [default error to display on form validation error, optional],
* size: [modal size, see BootstrapDialog.SIZE_* (optional)],
* validate_form_method: [method to used to validate & serialize form data (optional)],
* onshown: [a callback to call on modal shown (optional)],
* done: [a callback to call on form submission success (optional)],
* done_url: [The url to redirect the user to after a successful form submission (optional)],
* }
*/
function show_form_modal(opts) {
const loading = alertify.notify(
opts.loading_message || _("Loading form, please wait...", "success")
);
$.get(opts.form_url, null, function (modal_content) {
loading.dismiss();
BootstrapDialog.show({
title: opts.title,
size: opts.size || BootstrapDialog.SIZE_LARGE,
message: $(modal_content),
onshown: opts.onshown,
buttons: [
{
label: _("Validate"),
cssClass: "btn-primary",
action: function (dialog) {
var form = dialog.getModalBody().find("form");
var data = (opts.validate_form_method || validate_form)(form);
if (data == false) return;
if (form.find("input.is-invalid").length != 0) return false;
$.ajax({
url: opts.validate_url,
type: opts.method || "POST",
data: opts.json ? JSON.stringify(data) : data,
contentType: `${
opts.json
? "application/json"
: "application/x-www-form-urlencoded"
}; charset=utf-8`,
dataType: "json",
}).always(function (data) {
if (
handle_ajax_return(
data,
(default_error =
opts.validate_error ||
_(
"An unknown error occurred. If problem persist, please contact support."
))
)
)
if (opts.done_url) window.location = opts.done_url;
if (typeof opts.done == "function") opts.done(data);
});
},
},
],
});
});
}
/**
* Validate and serialize form's data
* @param {jQuery} form The form element to validate and serialize
* @returns object|false The serialized form's data on success or false
*/
function validate_form(form) {
form.find(".is-invalid").removeClass("is-invalid");
if (!form[0].checkValidity()) {
$(form[0].elements).each(function (idx, element) {
if (!element.checkValidity()) $(element).addClass("is-invalid");
});
return false;
}
var data = {};
jQuery.each(form.serializeArray(), function (idx, item) {
item.value = item.value.trim();
if (item.value) data[item.name] = item.value;
});
console.log(data);
return data;
}
/**
* Handle AJAX return to display errors/messages and return true or false in case of success or error
*
* Note: this function is designed to be called from jqXHR.always() by passing its data parameter.
*
* @param {object} data Data as received by jQuery jqXHR.always() method as first parameter
* @param {string|null} default_error Default error message on failure without error message in return
* @param {string|null} success_message Optional message to display on success
* @returns bool
*/
function handle_ajax_return(
data,
default_error = null,
success_message = null
) {
data =
"done" in data && "fail" in data && "always" in data
? data.responseJSON ?? {}
: data;
if (data.errors)
$(data.errors).each(function (idx, error) {
alertify.notify(error, "error");
});
if (data.messages)
$(data.messages).each(function (idx, message) {
alertify.notify(message, "success", 5);
});
if (data && data.success) {
if (success_message) alertify.notify(success_message, "success");
return true;
}
if (!data.errors)
alertify.notify(
default_error ??
_(
"An unknown error occurred. If problem persist, please contact support."
),
"error"
);
return false;
}
// AlertifyJS default settings
alertify.defaults = {
// dialogs defaults
modal: true,
movable: true,
resizable: true,
closable: true,
maximizable: true,
pinnable: true,
pinned: true,
padding: true,
overflow: true,
maintainFocus: true,
transition: "fade",
// notifier defaults
notifier: {
// auto-dismiss wait time (in seconds)
delay: 0,
// default position
position: "top-right",
},
// language resources
glossary: {
// ok button text
ok: _("OK"),
// cancel button text
cancel: _("Cancel"),
},
theme: {
// class name attached to prompt dialog input textbox.
input: "ajs-input form-control",
// class name attached to ok button
ok: "ajs-ok btn btn-primary",
// class name attached to cancel button
cancel: "ajs-cancel btn btn-default",
},
};