Refactor naming/structure of popup CSS classes

- Refactor naming/structure of popup CSS classes
- Prepare Popup utility of opening/showing dialogs
This commit is contained in:
Wolfsblvt 2024-06-09 22:02:51 +02:00
parent 10da7eb474
commit d14af1592e
21 changed files with 238 additions and 188 deletions

View File

@ -14,7 +14,7 @@ dialog {
display: flex;
flex-direction: column;
/* Overflow visible so elements (like toasts) can appear outside of the dialog. '.popup_content' is hiding overflow for the real content. */
/* Overflow visible so elements (like toasts) can appear outside of the dialog. '.popup-body' is hiding overflow for the real content. */
overflow: visible;
/* Fix weird animation issue with font-scaling during popup open */
@ -23,7 +23,7 @@ dialog {
-webkit-font-smoothing: subpixel-antialiased;
}
.popup .popup_content {
.popup .popup-body {
display: flex;
flex-direction: column;
overflow: hidden;
@ -32,23 +32,23 @@ dialog {
padding: 1px;
}
.popup .popup_text {
.popup .popup-content {
margin-top: 10px;
padding: 0 8px;
overflow: hidden;
flex-grow: 1;
}
.popup .popup_text h3:first-child {
/* No double spacing for the first heading needed, the .popup_text already has margin */
.popup .popup-content h3:first-child {
/* No double spacing for the first heading needed, the .popup-content already has margin */
margin-top: 0px;
}
.popup.vertical_scrolling_dialogue_popup .popup_text {
.popup.vertical_scrolling_dialogue_popup .popup-content {
overflow-y: auto;
}
.popup.horizontal_scrolling_dialogue_popup .popup_text {
.popup.horizontal_scrolling_dialogue_popup .popup-content {
overflow-x: auto;
}
@ -89,11 +89,11 @@ dialog {
transform: translate(-50%, -50%);
}
.popup_input {
.popup-input {
margin-top: 10px;
}
.popup_controls {
.popup-controls {
margin-top: 10px;
display: flex;
align-self: center;
@ -104,16 +104,16 @@ dialog {
box-shadow: 0 0 5px var(--white20a);
}
.menu_button.popup_ok {
.menu_button.popup-button-ok {
background-color: var(--crimson70a);
cursor: pointer;
}
.menu_button.popup_ok:hover {
.menu_button.popup-button-ok:hover {
background-color: var(--crimson-hover);
}
.menu_button.menu_button_custom {
.menu_button.popup-button-custom {
/* Custom buttons should not scale to smallest size, otherwise they will always break to multiline */
width: unset;
}

View File

@ -4843,16 +4843,16 @@
</div>
</div>
<!-- various fullscreen popups -->
<template id="popup_template" data-i18n="[popup_text_save]popup_text_save;[popup_text_yes]popup_text_yes;[popup_text_no]popup_text_no;[popup_text_cancel]popup_text_cancel;[popup_text_import]popup_text_import" popup_text_save="Save" popup_text_yes="Yes" popup_text_no="No" popup_text_cancel="Cancel" popup_text_import="Import"> <!-- localization data holder for popups -->
<template id="popup_template" data-i18n="[popup-button-save]popup-button-save;[popup-button-yes]popup-button-yes;[popup-button-no]popup-button-no;[popup-button-cancel]popup-button-cancel;[popup-button-import]popup-button-import" popup-button-save="Save" popup-button-yes="Yes" popup-button-no="No" popup-button-cancel="Cancel" popup-button-import="Import"> <!-- localization data holder for popups -->
<dialog class="popup">
<div class="popup_content">
<div class="popup_text">
<h3 class="margin0">text</h3>
<div class="popup-body">
<div class="popup-content">
<h3 class="popup-header">text</h3>
</div>
<textarea class="popup_input text_pole result_control" rows="1" data-result="1"></textarea>
<div class="popup_controls">
<div class="popup_ok menu_button result_control" data-i18n="Delete" data-result="1" tabindex="0">Delete</div>
<div class="popup_cancel menu_button result_control" data-i18n="Cancel" data-result="0" tabindex="0">Cancel</div>
<textarea class="popup-input text_pole result-control" rows="1" data-result="1"></textarea>
<div class="popup-controls">
<div class="popup-button-ok menu_button result-control" data-i18n="Delete" data-result="1" tabindex="0">Delete</div>
<div class="popup-button-cancel menu_button result-control" data-i18n="Cancel" data-result="0" tabindex="0">Cancel</div>
</div>
</div>
</dialog>
@ -4873,7 +4873,7 @@
</div>
<div id="character_popup" class="flex-container flexFlowColumn flexNoGap">
<div id="character_popup_text">
<h3 id="character_popup_text_h3" class="margin0"></h3> <span data-i18n="Advanced Defininitions">- Advanced
<h3 id="character_popup-button-h3" class="margin0"></h3> <span data-i18n="Advanced Defininitions">- Advanced
Definitions</span>
</div>
<hr class="margin-bot-10px">

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "تحرير الشخصيات جميعها",
"Bulk select all characters": "تحديد كافة الشخصيات بالجملة",
"Bulk delete characters": "حذف الشخصيات جميعها",
"popup_text_save": "يحفظ",
"popup_text_yes": "نعم",
"popup_text_no": "لا",
"popup_text_cancel": "يلغي",
"popup_text_import": "يستورد",
"popup-button-save": "يحفظ",
"popup-button-yes": "نعم",
"popup-button-no": "لا",
"popup-button-cancel": "يلغي",
"popup-button-import": "يستورد",
"Advanced Defininitions": "تعريفات متقدمة",
"Prompt Overrides": "التجاوزات السريعة",
"(For Chat Completion and Instruct Mode)": "(لاستكمال الدردشة ووضع التعليمات)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Massenbearbeitung von Charakteren",
"Bulk select all characters": "Massenauswahl aller Zeichen",
"Bulk delete characters": "Massenlöschung von Charakteren",
"popup_text_save": "Speichern",
"popup_text_yes": "Ja",
"popup_text_no": "NEIN",
"popup_text_cancel": "Stornieren",
"popup_text_import": "Importieren",
"popup-button-save": "Speichern",
"popup-button-yes": "Ja",
"popup-button-no": "NEIN",
"popup-button-cancel": "Stornieren",
"popup-button-import": "Importieren",
"Advanced Defininitions": "Erweiterte Definitionen",
"Prompt Overrides": "Eingabeaufforderungsüberschreibungen",
"(For Chat Completion and Instruct Mode)": "(Für Chat-Abschluss und Anweisungsmodus)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Editar personajes masivamente",
"Bulk select all characters": "Seleccionar de forma masiva todos los personajes",
"Bulk delete characters": "Eliminar personajes masivamente",
"popup_text_save": "Ahorrar",
"popup_text_yes": "Sí",
"popup_text_no": "No",
"popup_text_cancel": "Cancelar",
"popup_text_import": "Importar",
"popup-button-save": "Ahorrar",
"popup-button-yes": "Sí",
"popup-button-no": "No",
"popup-button-cancel": "Cancelar",
"popup-button-import": "Importar",
"Advanced Defininitions": "Definiciones avanzadas",
"Prompt Overrides": "Anulaciones rápidas",
"(For Chat Completion and Instruct Mode)": "(Para completar el chat y el modo de instrucción)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Édition en masse des personnages",
"Bulk select all characters": "Sélection groupée de tous les caractères",
"Bulk delete characters": "Suppression en masse des personnages",
"popup_text_save": "Sauvegarder",
"popup_text_yes": "Oui",
"popup_text_no": "Non",
"popup_text_cancel": "Annuler",
"popup_text_import": "Importer",
"popup-button-save": "Sauvegarder",
"popup-button-yes": "Oui",
"popup-button-no": "Non",
"popup-button-cancel": "Annuler",
"popup-button-import": "Importer",
"Advanced Defininitions": "Définitions avancées",
"Prompt Overrides": "Remplacements d'invite",
"(For Chat Completion and Instruct Mode)": "(Pour l'achèvement du chat et le mode instruction)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Breyta mörgum persónum í einu",
"Bulk select all characters": "Velja alla stafi í magni",
"Bulk delete characters": "Eyða mörgum persónum í einu",
"popup_text_save": "Vista",
"popup_text_yes": "Já",
"popup_text_no": "Nei",
"popup_text_cancel": "Hætta við",
"popup_text_import": "Flytja inn",
"popup-button-save": "Vista",
"popup-button-yes": "Já",
"popup-button-no": "Nei",
"popup-button-cancel": "Hætta við",
"popup-button-import": "Flytja inn",
"Advanced Defininitions": "Ítarleg skilgreiningar",
"Prompt Overrides": "Hnekkja hvetjandi",
"(For Chat Completion and Instruct Mode)": "(Til að ljúka spjalli og leiðbeiningarham)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Modifica personaggi in blocco",
"Bulk select all characters": "Seleziona in blocco tutti i personaggi",
"Bulk delete characters": "Elimina personaggi in blocco",
"popup_text_save": "Salva",
"popup_text_yes": "SÌ",
"popup_text_no": "NO",
"popup_text_cancel": "Annulla",
"popup_text_import": "Importare",
"popup-button-save": "Salva",
"popup-button-yes": "SÌ",
"popup-button-no": "NO",
"popup-button-cancel": "Annulla",
"popup-button-import": "Importare",
"Advanced Defininitions": "Definizioni avanzate",
"Prompt Overrides": "Sostituzioni richieste",
"(For Chat Completion and Instruct Mode)": "(Per il completamento della chat e la modalità istruzione)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "キャラクターを一括編集",
"Bulk select all characters": "すべての文字を一括選択",
"Bulk delete characters": "キャラクターを一括削除",
"popup_text_save": "保存",
"popup_text_yes": "はい",
"popup_text_no": "いいえ",
"popup_text_cancel": "キャンセル",
"popup_text_import": "輸入",
"popup-button-save": "保存",
"popup-button-yes": "はい",
"popup-button-no": "いいえ",
"popup-button-cancel": "キャンセル",
"popup-button-import": "輸入",
"Advanced Defininitions": "高度な定義",
"Prompt Overrides": "プロンプトのオーバーライド",
"(For Chat Completion and Instruct Mode)": "(チャット補完と指示モード用)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "대량 캐릭터 편집",
"Bulk select all characters": "모든 문자 일괄 선택",
"Bulk delete characters": "대량 캐릭터 삭제",
"popup_text_save": "구하다",
"popup_text_yes": "예",
"popup_text_no": "아니요",
"popup_text_cancel": "취소",
"popup_text_import": "수입",
"popup-button-save": "구하다",
"popup-button-yes": "예",
"popup-button-no": "아니요",
"popup-button-cancel": "취소",
"popup-button-import": "수입",
"Advanced Defininitions": "고급 정의",
"Prompt Overrides": "프롬프트 무시",
"(For Chat Completion and Instruct Mode)": "(채팅 완료 및 지시 모드의 경우)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Massaal bewerken personages",
"Bulk select all characters": "Selecteer alle tekens in bulk",
"Bulk delete characters": "Massaal verwijderen personages",
"popup_text_save": "Redden",
"popup_text_yes": "Ja",
"popup_text_no": "Nee",
"popup_text_cancel": "Annuleren",
"popup_text_import": "Importeren",
"popup-button-save": "Redden",
"popup-button-yes": "Ja",
"popup-button-no": "Nee",
"popup-button-cancel": "Annuleren",
"popup-button-import": "Importeren",
"Advanced Defininitions": "Geavanceerde definities",
"Prompt Overrides": "Prompt-overschrijvingen",
"(For Chat Completion and Instruct Mode)": "(Voor voltooiing van chat en instructiemodus)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Editar personagens em massa",
"Bulk select all characters": "Selecione em massa todos os caracteres",
"Bulk delete characters": "Excluir personagens em massa",
"popup_text_save": "Salvar",
"popup_text_yes": "Sim",
"popup_text_no": "Não",
"popup_text_cancel": "Cancelar",
"popup_text_import": "Importar",
"popup-button-save": "Salvar",
"popup-button-yes": "Sim",
"popup-button-no": "Não",
"popup-button-cancel": "Cancelar",
"popup-button-import": "Importar",
"Advanced Defininitions": "Definições Avançadas",
"Prompt Overrides": "Substituições de prompt",
"(For Chat Completion and Instruct Mode)": "(Para conclusão de bate-papo e modo de instrução)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Массовое редактирование персонажей",
"Bulk select all characters": "Массовый выбор всех персонажей",
"Bulk delete characters": "Массовое удаление персонажей",
"popup_text_save": "Сохранить",
"popup_text_yes": "Да",
"popup_text_no": "Нет",
"popup_text_cancel": "Отмена",
"popup_text_import": "Импортировать",
"popup-button-save": "Сохранить",
"popup-button-yes": "Да",
"popup-button-no": "Нет",
"popup-button-cancel": "Отмена",
"popup-button-import": "Импортировать",
"Advanced Defininitions": "Расширенное описание",
"Prompt Overrides": "Индивидуальные промпты",
"(For Chat Completion and Instruct Mode)": "(для Chat Completion и режима Instruct)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Масове редагування персонажів",
"Bulk select all characters": "Масове виділення всіх символів",
"Bulk delete characters": "Масове видалення персонажів",
"popup_text_save": "зберегти",
"popup_text_yes": "Так",
"popup_text_no": "Немає",
"popup_text_cancel": "Скасувати",
"popup_text_import": "Імпорт",
"popup-button-save": "зберегти",
"popup-button-yes": "Так",
"popup-button-no": "Немає",
"popup-button-cancel": "Скасувати",
"popup-button-import": "Імпорт",
"Advanced Defininitions": "Розширені визначення",
"Prompt Overrides": "Перевизначення підказок",
"(For Chat Completion and Instruct Mode)": "(Для завершення чату та режиму інструктажу)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Chỉnh sửa nhân vật theo lô",
"Bulk select all characters": "Chọn hàng loạt tất cả các ký tự",
"Bulk delete characters": "Xóa nhân vật theo lô",
"popup_text_save": "Cứu",
"popup_text_yes": "Đúng",
"popup_text_no": "KHÔNG",
"popup_text_cancel": "Hủy bỏ",
"popup_text_import": "Nhập khẩu",
"popup-button-save": "Cứu",
"popup-button-yes": "Đúng",
"popup-button-no": "KHÔNG",
"popup-button-cancel": "Hủy bỏ",
"popup-button-import": "Nhập khẩu",
"Advanced Defininitions": "Các Định nghĩa Nâng cao",
"Prompt Overrides": "Ghi đè nhắc nhở",
"(For Chat Completion and Instruct Mode)": "(Đối với chế độ hoàn thành trò chuyện và hướng dẫn)",

View File

@ -886,11 +886,11 @@
"Bulk_edit_characters": "批量编辑角色",
"Bulk select all characters": "批量选择所有角色",
"Bulk delete characters": "批量删除角色",
"popup_text_save": "保存",
"popup_text_yes": "是",
"popup_text_no": "否",
"popup_text_cancel": "取消",
"popup_text_import": "导入",
"popup-button-save": "保存",
"popup-button-yes": "是",
"popup-button-no": "否",
"popup-button-cancel": "取消",
"popup-button-import": "导入",
"Advanced Defininitions": "高级定义",
"Prompt Overrides": "提示覆盖",
"(For Chat Completion and Instruct Mode)": "(用于聊天完成和指导模式)",

View File

@ -886,11 +886,11 @@
"Bulk_edit_characters": "批量編輯角色人物\n\n點選以切換角色人物\nShift + 點選以選擇/取消選擇一範圍的角色人物\n右鍵以查看動作",
"Bulk select all characters": "全選所有角色人物",
"Bulk delete characters": "批量刪除角色人物",
"popup_text_save": "儲存",
"popup_text_yes": "是",
"popup_text_no": "否",
"popup_text_cancel": "取消",
"popup_text_import": "匯入",
"popup-button-save": "儲存",
"popup-button-yes": "是",
"popup-button-no": "否",
"popup-button-cancel": "取消",
"popup-button-import": "匯入",
"Advanced Defininitions": "- 進階定義",
"Prompt Overrides": "提示詞覆寫",
"(For Chat Completion and Instruct Mode)": "(用於聊天補充和指令模式)",

View File

@ -6837,7 +6837,7 @@ export function select_selected_character(chid) {
$('#add_avatar_button').val('');
$('#character_popup_text_h3').text(characters[chid].name);
$('#character_popup-button-h3').text(characters[chid].name);
$('#character_name_pole').val(characters[chid].name);
$('#description_textarea').val(characters[chid].description);
$('#character_world').val(characters[chid].data?.extensions?.world || '');
@ -6914,7 +6914,7 @@ function select_rm_create() {
//create text poles
$('#rm_button_back').css('display', '');
$('#character_import_button').css('display', '');
$('#character_popup_text_h3').text('Create character');
$('#character_popup-button-h3').text('Create character');
$('#character_name_pole').val(create_save.name);
$('#description_textarea').val(create_save.description);
$('#character_world').val(create_save.world);
@ -7583,7 +7583,7 @@ async function createOrEditCharacter(e) {
field.callback && field.callback(fieldValue);
});
$('#character_popup_text_h3').text('Create character');
$('#character_popup-button-h3').text('Create character');
create_save.avatar = '';
@ -10603,7 +10603,7 @@ jQuery(async function () {
const html = await renderTemplateAsync('importCharacters');
/** @type {string?} */
const input = await callGenericPopup(html, POPUP_TYPE.INPUT, '', { wider: true, okButton: $('#popup_template').attr('popup_text_import'), rows: 4 });
const input = await callGenericPopup(html, POPUP_TYPE.INPUT, '', { wider: true, okButton: $('#popup_template').attr('popup-button-import'), rows: 4 });
if (!input) {
console.debug('Custom content import cancelled');

View File

@ -220,17 +220,17 @@
align-items: baseline;
}
@media screen and (max-width: 750px) {
body .popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor {
body .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor {
flex-direction: column;
overflow: auto;
}
body .popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main {
body .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main {
flex: 0 0 auto;
}
body .popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--labels {
body .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels {
flex-direction: column;
}
body .popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder {
body .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder {
min-height: 50svh;
height: 50svh;
}
@ -238,50 +238,50 @@
.popup:has(#qr--modalEditor) {
aspect-ratio: unset;
}
.popup:has(#qr--modalEditor) .popup_text {
.popup:has(#qr--modalEditor) .popup-content {
display: flex;
flex-direction: column;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor {
flex: 1 1 auto;
display: flex;
flex-direction: row;
gap: 1em;
overflow: hidden;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main {
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: hidden;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--labels {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels {
flex: 0 0 auto;
display: flex;
flex-direction: row;
gap: 0.5em;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--labels > label {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label {
flex: 1 1 1px;
display: flex;
flex-direction: column;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--labels > label > .qr--labelText {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label > .qr--labelText {
flex: 1 1 auto;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--labels > label > .qr--labelHint {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label > .qr--labelHint {
flex: 1 1 auto;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--labels > label > input {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--labels > label > input {
flex: 0 0 auto;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer {
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: hidden;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings {
display: flex;
flex-direction: row;
gap: 1em;
@ -289,19 +289,19 @@
font-size: smaller;
align-items: baseline;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings > .checkbox_label {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings > .checkbox_label {
white-space: nowrap;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings > .checkbox_label > input {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > .qr--modal-editorSettings > .checkbox_label > input {
font-size: inherit;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder {
flex: 1 1 auto;
display: grid;
text-align: left;
overflow: hidden;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-messageSyntax {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-messageSyntax {
grid-column: 1;
grid-row: 1;
padding: 0;
@ -311,22 +311,22 @@
min-width: 100%;
width: 0;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-messageSyntax > #qr--modal-messageSyntaxInner {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-messageSyntax > #qr--modal-messageSyntaxInner {
height: 100%;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message {
grid-column: 1;
grid-row: 1;
caret-color: white;
mix-blend-mode: difference;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar,
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar-thumb {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder > #qr--modal-message::-webkit-scrollbar-thumb {
visibility: hidden;
cursor: default;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-message,
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-messageSyntaxInner {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-message,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder #qr--modal-messageSyntaxInner {
padding: 0.75em;
margin: 0;
border: none;
@ -335,11 +335,11 @@
border: 1px solid var(--SmartThemeBorderColor);
border-radius: 5px;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons {
display: flex;
gap: 1em;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons .qr--modal-executeButton {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons .qr--modal-executeButton {
border-width: 2px;
border-style: solid;
display: flex;
@ -347,42 +347,42 @@
gap: 0.5em;
padding: 0.5em 0.75em;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons .qr--modal-executeButton .qr--modal-executeComboIcon {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons .qr--modal-executeButton .qr--modal-executeComboIcon {
display: flex;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute {
transition: 200ms;
filter: grayscale(0);
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute.qr--busy {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute.qr--busy {
cursor: wait;
opacity: 0.5;
filter: grayscale(1);
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-execute {
border-color: #51a351;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons #qr--modal-pause,
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons #qr--modal-stop {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-pause,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-stop {
cursor: default;
opacity: 0.5;
filter: grayscale(1);
pointer-events: none;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons .qr--busy ~ #qr--modal-pause,
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons .qr--busy ~ #qr--modal-stop {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons .qr--busy ~ #qr--modal-pause,
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons .qr--busy ~ #qr--modal-stop {
cursor: pointer;
opacity: 1;
filter: grayscale(0);
pointer-events: all;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons #qr--modal-pause {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-pause {
border-color: #92befc;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeButtons #qr--modal-stop {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeButtons #qr--modal-stop {
border-color: #d78872;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeProgress {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeProgress {
--prog: 0;
--progColor: #92befc;
--progFlashColor: #d78872;
@ -393,7 +393,7 @@
background-color: var(--black50a);
position: relative;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeProgress:after {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeProgress:after {
content: '';
background-color: var(--progColor);
position: absolute;
@ -401,23 +401,23 @@
right: calc(100% - var(--prog) * 1%);
transition: 200ms;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeProgress.qr--paused:after {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeProgress.qr--paused:after {
animation-name: qr--progressPulse;
animation-duration: 1500ms;
animation-timing-function: ease-in-out;
animation-delay: 0s;
animation-iteration-count: infinite;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeProgress.qr--aborted:after {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeProgress.qr--aborted:after {
background-color: var(--progAbortedColor);
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeProgress.qr--success:after {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeProgress.qr--success:after {
background-color: var(--progSuccessColor);
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeProgress.qr--error:after {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeProgress.qr--error:after {
background-color: var(--progErrorColor);
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeErrors {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeErrors {
display: none;
text-align: left;
font-size: smaller;
@ -428,10 +428,10 @@
min-width: 100%;
width: 0;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeErrors.qr--hasErrors {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeErrors.qr--hasErrors {
display: block;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeResult {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeResult {
display: none;
text-align: left;
font-size: smaller;
@ -442,10 +442,10 @@
min-width: 100%;
width: 0;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeResult.qr--hasResult {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeResult.qr--hasResult {
display: block;
}
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor #qr--modal-executeResult:before {
.popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor #qr--modal-executeResult:before {
content: 'Result: ';
}
@keyframes qr--progressPulse {

View File

@ -244,7 +244,7 @@
@media screen and (max-width: 750px) {
body .popup:has(#qr--modalEditor) .popup_text>#qr--modalEditor {
body .popup:has(#qr--modalEditor) .popup-content>#qr--modalEditor {
flex-direction: column;
overflow: auto;
> #qr--main {
@ -262,7 +262,7 @@
.popup:has(#qr--modalEditor) {
aspect-ratio: unset;
.popup_text {
.popup-content {
display: flex;
flex-direction: column;

View File

@ -1,5 +1,4 @@
import { debounce_timeout } from './constants.js';
import { hasAnimation, removeFromArray, runAfterAnimation, uuidv4 } from './utils.js';
import { removeFromArray, runAfterAnimation, uuidv4 } from './utils.js';
/** @readonly */
/** @enum {Number} */
@ -10,16 +9,13 @@ export const POPUP_TYPE = {
};
/** @readonly */
/** @enum {number} */
/** @enum {number?} */
export const POPUP_RESULT = {
'AFFIRMATIVE': 1,
'NEGATIVE': 0,
'CANCELLED': undefined,
'CANCELLED': null,
};
/** @type {Popup[]} Remember all popups */
export const popups = [];
/**
* @typedef {object} PopupOptions
* @property {string|boolean?} [okButton] - Custom text for the OK button, or `true` to use the default (If set, the button will always be displayed, no matter the type of popup)
@ -43,14 +39,38 @@ export const popups = [];
* @property {boolean?} [appendAtEnd] - Whether to append the button to the end of the popup - by default it will be prepended
*/
/**
* @typedef {object} ShowPopupHelper
* Local implementation of the helper functionality to show several popups.
*
* Should be called via `Popup.show.xxxx()`.
*/
const showPopupHelper = {
/**
* Asynchronously displays an input popup with the given header and text, and returns the user's input.
*
* @param {string} header - The header text for the popup.
* @param {string} text - The main text for the popup.
* @param {string} [defaultValue=''] - The default value for the input field.
* @param {PopupOptions} [popupOptions={}] - Options for the popup.
* @return {Promise<string?>} A Promise that resolves with the user's input.
*/
input: async (header, text, defaultValue = '', popupOptions = {}) => {
const content = PopupUtils.BuildTextWithHeader(header, text);
const popup = new Popup(content, POPUP_TYPE.INPUT, defaultValue, popupOptions);
const value = await popup.show();
return value ? String(value) : null;
},
}
export class Popup {
/** @type {POPUP_TYPE} */ type;
/** @type {string} */ id;
/** @type {HTMLDialogElement} */ dlg;
/** @type {HTMLElement} */ body;
/** @type {HTMLElement} */ content;
/** @type {HTMLElement} */ text;
/** @type {HTMLTextAreaElement} */ input;
/** @type {HTMLElement} */ controls;
/** @type {HTMLElement} */ ok;
@ -67,15 +87,15 @@ export class Popup {
/** @type {(result: any) => any} */ resolver;
/**
* Constructs a new Popup object with the given text, type, inputValue, and options
* Constructs a new Popup object with the given text content, type, inputValue, and options
*
* @param {JQuery<HTMLElement>|string|Element} text - Text to display in the popup
* @param {JQuery<HTMLElement>|string|Element} content - Text content to display in the popup
* @param {POPUP_TYPE} type - The type of the popup
* @param {string} [inputValue=''] - The initial value of the input field
* @param {PopupOptions} [options={}] - Additional options for the popup
*/
constructor(text, type, inputValue = '', { okButton = null, cancelButton = null, rows = 1, wide = false, wider = false, large = false, allowHorizontalScrolling = false, allowVerticalScrolling = false, defaultResult = POPUP_RESULT.AFFIRMATIVE, customButtons = null } = {}) {
popups.push(this);
constructor(content, type, inputValue = '', { okButton = null, cancelButton = null, rows = 1, wide = false, wider = false, large = false, allowHorizontalScrolling = false, allowVerticalScrolling = false, defaultResult = POPUP_RESULT.AFFIRMATIVE, customButtons = null } = {}) {
Popup.util.popups.push(this);
// Make this popup uniquely identifiable
this.id = uuidv4();
@ -85,12 +105,12 @@ export class Popup {
const template = document.querySelector('#popup_template');
// @ts-ignore
this.dlg = template.content.cloneNode(true).querySelector('.popup');
this.content = this.dlg.querySelector('.popup_content');
this.text = this.dlg.querySelector('.popup_text');
this.input = this.dlg.querySelector('.popup_input');
this.controls = this.dlg.querySelector('.popup_controls');
this.ok = this.dlg.querySelector('.popup_ok');
this.cancel = this.dlg.querySelector('.popup_cancel');
this.body = this.dlg.querySelector('.popup-body');
this.content = this.dlg.querySelector('.popup-content');
this.input = this.dlg.querySelector('.popup-input');
this.controls = this.dlg.querySelector('.popup-controls');
this.ok = this.dlg.querySelector('.popup-button-ok');
this.cancel = this.dlg.querySelector('.popup-button-cancel');
this.dlg.setAttribute('data-id', this.id);
if (wide) this.dlg.classList.add('wide_dialogue_popup');
@ -101,7 +121,7 @@ export class Popup {
// If custom button captions are provided, we set them beforehand
this.ok.textContent = typeof okButton === 'string' ? okButton : 'OK';
this.cancel.textContent = typeof cancelButton === 'string' ? cancelButton : template.getAttribute('popup_text_cancel');
this.cancel.textContent = typeof cancelButton === 'string' ? cancelButton : template.getAttribute('popup-button-cancel');
this.defaultResult = defaultResult;
this.customButtons = customButtons;
@ -110,7 +130,7 @@ export class Popup {
const button = typeof x === 'string' ? { text: x, result: index + 2 } : x;
const buttonElement = document.createElement('div');
buttonElement.classList.add('menu_button', 'menu_button_custom', 'result_control');
buttonElement.classList.add('menu_button', 'popup-button-custom', 'result-control');
buttonElement.classList.add(...(button.classes ?? []));
buttonElement.setAttribute('data-result', String(button.result ?? undefined));
buttonElement.textContent = button.text;
@ -138,13 +158,13 @@ export class Popup {
}
case POPUP_TYPE.CONFIRM: {
this.input.style.display = 'none';
if (!okButton) this.ok.textContent = template.getAttribute('popup_text_yes');
if (!cancelButton) this.cancel.textContent = template.getAttribute('popup_text_no');
if (!okButton) this.ok.textContent = template.getAttribute('popup-button-yes');
if (!cancelButton) this.cancel.textContent = template.getAttribute('popup-button-no');
break;
}
case POPUP_TYPE.INPUT: {
this.input.style.display = 'block';
if (!okButton) this.ok.textContent = template.getAttribute('popup_text_save');
if (!okButton) this.ok.textContent = template.getAttribute('popup-button-save');
break;
}
default: {
@ -156,15 +176,15 @@ export class Popup {
this.input.value = inputValue;
this.input.rows = rows ?? 1;
this.text.innerHTML = '';
if (text instanceof jQuery) {
$(this.text).append(text);
} else if (text instanceof HTMLElement) {
this.text.append(text);
} else if (typeof text == 'string') {
this.text.innerHTML = text;
this.content.innerHTML = '';
if (content instanceof jQuery) {
$(this.content).append(content);
} else if (content instanceof HTMLElement) {
this.content.append(content);
} else if (typeof content == 'string') {
this.content.innerHTML = content;
} else {
console.warn('Unknown popup text type. Should be jQuery, HTMLElement or string.', text);
console.warn('Unknown popup text type. Should be jQuery, HTMLElement or string.', content);
}
// Already prepare the auto-focus control by adding the "autofocus" attribute, this should be respected by showModal()
@ -198,7 +218,7 @@ export class Popup {
return;
// Check if the current focus is a result control. Only should we apply the compelete action
const resultControl = document.activeElement?.closest('.result_control');
const resultControl = document.activeElement?.closest('.result-control');
if (!resultControl)
return;
@ -297,6 +317,7 @@ export class Popup {
this.value = value;
this.result = result;
Popup.util.lastResult = { value, result };
this.hide();
}
@ -320,13 +341,13 @@ export class Popup {
this.dlg.remove();
// Remove it from the popup references
removeFromArray(popups, this);
removeFromArray(Popup.util.popups, this);
// If there is any popup below this one, see if we can set the focus
if (popups.length > 0) {
if (Popup.util.popups.length > 0) {
const activeDialog = document.activeElement?.closest('.popup');
const id = activeDialog?.getAttribute('data-id');
const popup = popups.find(x => x.id == id);
const popup = Popup.util.popups.find(x => x.id == id);
if (popup) {
if (popup.lastFocus) popup.lastFocus.focus();
else popup.setAutoFocus();
@ -336,19 +357,45 @@ export class Popup {
this.resolver(this.value);
}
/**
* Show a popup with any of the given helper methods. Use `await` to make them blocking.
*/
static show = showPopupHelper;
/**
* Utility for popup and popup management.
*
* Contains the list of all currently open popups, and it'll remember the result of the last closed popup.
*/
static util = {
/** @type {Popup[]} Remember all popups */
popups: [],
/** @type {{value: any, result: POPUP_RESULT|number?}?} Last popup result */
lastResult: null,
}
}
class PopupUtils {
static BuildTextWithHeader(header, text) {
return `
<h3>${header}</h1>
${text}`;
}
}
/**
* Displays a blocking popup with a given text and type
* @param {JQuery<HTMLElement>|string|Element} text - Text to display in the popup
* Displays a blocking popup with a given content and type
* @param {JQuery<HTMLElement>|string|Element} content - Content or text to display in the popup
* @param {POPUP_TYPE} type
* @param {string} inputValue - Value to set the input to
* @param {PopupOptions} [popupOptions={}] - Options for the popup
* @returns {Promise<POPUP_RESULT|string|boolean?>} The value for this popup, which can either be the popup retult or the input value if chosen
*/
export function callGenericPopup(text, type, inputValue = '', popupOptions = {}) {
export function callGenericPopup(content, type, inputValue = '', popupOptions = {}) {
const popup = new Popup(
text,
content,
type,
inputValue,
popupOptions,
@ -356,6 +403,9 @@ export function callGenericPopup(text, type, inputValue = '', popupOptions = {})
return popup.show();
}
/**
* Fixes the issue with toastr not displaying on top of the dialog by moving the toastr container inside the dialog or back to the main body
*/
export function fixToastrForDialogs() {
// Hacky way of getting toastr to actually display on top of the popup...