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

View File

@ -4843,16 +4843,16 @@
</div> </div>
</div> </div>
<!-- various fullscreen popups --> <!-- 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"> <dialog class="popup">
<div class="popup_content"> <div class="popup-body">
<div class="popup_text"> <div class="popup-content">
<h3 class="margin0">text</h3> <h3 class="popup-header">text</h3>
</div> </div>
<textarea class="popup_input text_pole result_control" rows="1" data-result="1"></textarea> <textarea class="popup-input text_pole result-control" rows="1" data-result="1"></textarea>
<div class="popup_controls"> <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-button-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> <div class="popup-button-cancel menu_button result-control" data-i18n="Cancel" data-result="0" tabindex="0">Cancel</div>
</div> </div>
</div> </div>
</dialog> </dialog>
@ -4873,7 +4873,7 @@
</div> </div>
<div id="character_popup" class="flex-container flexFlowColumn flexNoGap"> <div id="character_popup" class="flex-container flexFlowColumn flexNoGap">
<div id="character_popup_text"> <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> Definitions</span>
</div> </div>
<hr class="margin-bot-10px"> <hr class="margin-bot-10px">

View File

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

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Massenbearbeitung von Charakteren", "Bulk_edit_characters": "Massenbearbeitung von Charakteren",
"Bulk select all characters": "Massenauswahl aller Zeichen", "Bulk select all characters": "Massenauswahl aller Zeichen",
"Bulk delete characters": "Massenlöschung von Charakteren", "Bulk delete characters": "Massenlöschung von Charakteren",
"popup_text_save": "Speichern", "popup-button-save": "Speichern",
"popup_text_yes": "Ja", "popup-button-yes": "Ja",
"popup_text_no": "NEIN", "popup-button-no": "NEIN",
"popup_text_cancel": "Stornieren", "popup-button-cancel": "Stornieren",
"popup_text_import": "Importieren", "popup-button-import": "Importieren",
"Advanced Defininitions": "Erweiterte Definitionen", "Advanced Defininitions": "Erweiterte Definitionen",
"Prompt Overrides": "Eingabeaufforderungsüberschreibungen", "Prompt Overrides": "Eingabeaufforderungsüberschreibungen",
"(For Chat Completion and Instruct Mode)": "(Für Chat-Abschluss und Anweisungsmodus)", "(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_edit_characters": "Editar personajes masivamente",
"Bulk select all characters": "Seleccionar de forma masiva todos los personajes", "Bulk select all characters": "Seleccionar de forma masiva todos los personajes",
"Bulk delete characters": "Eliminar personajes masivamente", "Bulk delete characters": "Eliminar personajes masivamente",
"popup_text_save": "Ahorrar", "popup-button-save": "Ahorrar",
"popup_text_yes": "Sí", "popup-button-yes": "Sí",
"popup_text_no": "No", "popup-button-no": "No",
"popup_text_cancel": "Cancelar", "popup-button-cancel": "Cancelar",
"popup_text_import": "Importar", "popup-button-import": "Importar",
"Advanced Defininitions": "Definiciones avanzadas", "Advanced Defininitions": "Definiciones avanzadas",
"Prompt Overrides": "Anulaciones rápidas", "Prompt Overrides": "Anulaciones rápidas",
"(For Chat Completion and Instruct Mode)": "(Para completar el chat y el modo de instrucción)", "(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_edit_characters": "Édition en masse des personnages",
"Bulk select all characters": "Sélection groupée de tous les caractères", "Bulk select all characters": "Sélection groupée de tous les caractères",
"Bulk delete characters": "Suppression en masse des personnages", "Bulk delete characters": "Suppression en masse des personnages",
"popup_text_save": "Sauvegarder", "popup-button-save": "Sauvegarder",
"popup_text_yes": "Oui", "popup-button-yes": "Oui",
"popup_text_no": "Non", "popup-button-no": "Non",
"popup_text_cancel": "Annuler", "popup-button-cancel": "Annuler",
"popup_text_import": "Importer", "popup-button-import": "Importer",
"Advanced Defininitions": "Définitions avancées", "Advanced Defininitions": "Définitions avancées",
"Prompt Overrides": "Remplacements d'invite", "Prompt Overrides": "Remplacements d'invite",
"(For Chat Completion and Instruct Mode)": "(Pour l'achèvement du chat et le mode instruction)", "(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_edit_characters": "Breyta mörgum persónum í einu",
"Bulk select all characters": "Velja alla stafi í magni", "Bulk select all characters": "Velja alla stafi í magni",
"Bulk delete characters": "Eyða mörgum persónum í einu", "Bulk delete characters": "Eyða mörgum persónum í einu",
"popup_text_save": "Vista", "popup-button-save": "Vista",
"popup_text_yes": "Já", "popup-button-yes": "Já",
"popup_text_no": "Nei", "popup-button-no": "Nei",
"popup_text_cancel": "Hætta við", "popup-button-cancel": "Hætta við",
"popup_text_import": "Flytja inn", "popup-button-import": "Flytja inn",
"Advanced Defininitions": "Ítarleg skilgreiningar", "Advanced Defininitions": "Ítarleg skilgreiningar",
"Prompt Overrides": "Hnekkja hvetjandi", "Prompt Overrides": "Hnekkja hvetjandi",
"(For Chat Completion and Instruct Mode)": "(Til að ljúka spjalli og leiðbeiningarham)", "(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_edit_characters": "Modifica personaggi in blocco",
"Bulk select all characters": "Seleziona in blocco tutti i personaggi", "Bulk select all characters": "Seleziona in blocco tutti i personaggi",
"Bulk delete characters": "Elimina personaggi in blocco", "Bulk delete characters": "Elimina personaggi in blocco",
"popup_text_save": "Salva", "popup-button-save": "Salva",
"popup_text_yes": "SÌ", "popup-button-yes": "SÌ",
"popup_text_no": "NO", "popup-button-no": "NO",
"popup_text_cancel": "Annulla", "popup-button-cancel": "Annulla",
"popup_text_import": "Importare", "popup-button-import": "Importare",
"Advanced Defininitions": "Definizioni avanzate", "Advanced Defininitions": "Definizioni avanzate",
"Prompt Overrides": "Sostituzioni richieste", "Prompt Overrides": "Sostituzioni richieste",
"(For Chat Completion and Instruct Mode)": "(Per il completamento della chat e la modalità istruzione)", "(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_edit_characters": "キャラクターを一括編集",
"Bulk select all characters": "すべての文字を一括選択", "Bulk select all characters": "すべての文字を一括選択",
"Bulk delete characters": "キャラクターを一括削除", "Bulk delete characters": "キャラクターを一括削除",
"popup_text_save": "保存", "popup-button-save": "保存",
"popup_text_yes": "はい", "popup-button-yes": "はい",
"popup_text_no": "いいえ", "popup-button-no": "いいえ",
"popup_text_cancel": "キャンセル", "popup-button-cancel": "キャンセル",
"popup_text_import": "輸入", "popup-button-import": "輸入",
"Advanced Defininitions": "高度な定義", "Advanced Defininitions": "高度な定義",
"Prompt Overrides": "プロンプトのオーバーライド", "Prompt Overrides": "プロンプトのオーバーライド",
"(For Chat Completion and Instruct Mode)": "(チャット補完と指示モード用)", "(For Chat Completion and Instruct Mode)": "(チャット補完と指示モード用)",

View File

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

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Massaal bewerken personages", "Bulk_edit_characters": "Massaal bewerken personages",
"Bulk select all characters": "Selecteer alle tekens in bulk", "Bulk select all characters": "Selecteer alle tekens in bulk",
"Bulk delete characters": "Massaal verwijderen personages", "Bulk delete characters": "Massaal verwijderen personages",
"popup_text_save": "Redden", "popup-button-save": "Redden",
"popup_text_yes": "Ja", "popup-button-yes": "Ja",
"popup_text_no": "Nee", "popup-button-no": "Nee",
"popup_text_cancel": "Annuleren", "popup-button-cancel": "Annuleren",
"popup_text_import": "Importeren", "popup-button-import": "Importeren",
"Advanced Defininitions": "Geavanceerde definities", "Advanced Defininitions": "Geavanceerde definities",
"Prompt Overrides": "Prompt-overschrijvingen", "Prompt Overrides": "Prompt-overschrijvingen",
"(For Chat Completion and Instruct Mode)": "(Voor voltooiing van chat en instructiemodus)", "(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_edit_characters": "Editar personagens em massa",
"Bulk select all characters": "Selecione em massa todos os caracteres", "Bulk select all characters": "Selecione em massa todos os caracteres",
"Bulk delete characters": "Excluir personagens em massa", "Bulk delete characters": "Excluir personagens em massa",
"popup_text_save": "Salvar", "popup-button-save": "Salvar",
"popup_text_yes": "Sim", "popup-button-yes": "Sim",
"popup_text_no": "Não", "popup-button-no": "Não",
"popup_text_cancel": "Cancelar", "popup-button-cancel": "Cancelar",
"popup_text_import": "Importar", "popup-button-import": "Importar",
"Advanced Defininitions": "Definições Avançadas", "Advanced Defininitions": "Definições Avançadas",
"Prompt Overrides": "Substituições de prompt", "Prompt Overrides": "Substituições de prompt",
"(For Chat Completion and Instruct Mode)": "(Para conclusão de bate-papo e modo de instrução)", "(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_edit_characters": "Массовое редактирование персонажей",
"Bulk select all characters": "Массовый выбор всех персонажей", "Bulk select all characters": "Массовый выбор всех персонажей",
"Bulk delete characters": "Массовое удаление персонажей", "Bulk delete characters": "Массовое удаление персонажей",
"popup_text_save": "Сохранить", "popup-button-save": "Сохранить",
"popup_text_yes": "Да", "popup-button-yes": "Да",
"popup_text_no": "Нет", "popup-button-no": "Нет",
"popup_text_cancel": "Отмена", "popup-button-cancel": "Отмена",
"popup_text_import": "Импортировать", "popup-button-import": "Импортировать",
"Advanced Defininitions": "Расширенное описание", "Advanced Defininitions": "Расширенное описание",
"Prompt Overrides": "Индивидуальные промпты", "Prompt Overrides": "Индивидуальные промпты",
"(For Chat Completion and Instruct Mode)": "(для Chat Completion и режима Instruct)", "(For Chat Completion and Instruct Mode)": "(для Chat Completion и режима Instruct)",

View File

@ -885,11 +885,11 @@
"Bulk_edit_characters": "Масове редагування персонажів", "Bulk_edit_characters": "Масове редагування персонажів",
"Bulk select all characters": "Масове виділення всіх символів", "Bulk select all characters": "Масове виділення всіх символів",
"Bulk delete characters": "Масове видалення персонажів", "Bulk delete characters": "Масове видалення персонажів",
"popup_text_save": "зберегти", "popup-button-save": "зберегти",
"popup_text_yes": "Так", "popup-button-yes": "Так",
"popup_text_no": "Немає", "popup-button-no": "Немає",
"popup_text_cancel": "Скасувати", "popup-button-cancel": "Скасувати",
"popup_text_import": "Імпорт", "popup-button-import": "Імпорт",
"Advanced Defininitions": "Розширені визначення", "Advanced Defininitions": "Розширені визначення",
"Prompt Overrides": "Перевизначення підказок", "Prompt Overrides": "Перевизначення підказок",
"(For Chat Completion and Instruct Mode)": "(Для завершення чату та режиму інструктажу)", "(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_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 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ô", "Bulk delete characters": "Xóa nhân vật theo lô",
"popup_text_save": "Cứu", "popup-button-save": "Cứu",
"popup_text_yes": "Đúng", "popup-button-yes": "Đúng",
"popup_text_no": "KHÔNG", "popup-button-no": "KHÔNG",
"popup_text_cancel": "Hủy bỏ", "popup-button-cancel": "Hủy bỏ",
"popup_text_import": "Nhập khẩu", "popup-button-import": "Nhập khẩu",
"Advanced Defininitions": "Các Định nghĩa Nâng cao", "Advanced Defininitions": "Các Định nghĩa Nâng cao",
"Prompt Overrides": "Ghi đè nhắc nhở", "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)", "(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_edit_characters": "批量编辑角色",
"Bulk select all characters": "批量选择所有角色", "Bulk select all characters": "批量选择所有角色",
"Bulk delete characters": "批量删除角色", "Bulk delete characters": "批量删除角色",
"popup_text_save": "保存", "popup-button-save": "保存",
"popup_text_yes": "是", "popup-button-yes": "是",
"popup_text_no": "否", "popup-button-no": "否",
"popup_text_cancel": "取消", "popup-button-cancel": "取消",
"popup_text_import": "导入", "popup-button-import": "导入",
"Advanced Defininitions": "高级定义", "Advanced Defininitions": "高级定义",
"Prompt Overrides": "提示覆盖", "Prompt Overrides": "提示覆盖",
"(For Chat Completion and Instruct Mode)": "(用于聊天完成和指导模式)", "(For Chat Completion and Instruct Mode)": "(用于聊天完成和指导模式)",

View File

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

View File

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

View File

@ -220,17 +220,17 @@
align-items: baseline; align-items: baseline;
} }
@media screen and (max-width: 750px) { @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; flex-direction: column;
overflow: auto; 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; 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; 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; min-height: 50svh;
height: 50svh; height: 50svh;
} }
@ -238,50 +238,50 @@
.popup:has(#qr--modalEditor) { .popup:has(#qr--modalEditor) {
aspect-ratio: unset; aspect-ratio: unset;
} }
.popup:has(#qr--modalEditor) .popup_text { .popup:has(#qr--modalEditor) .popup-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.popup:has(#qr--modalEditor) .popup_text > #qr--modalEditor { .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor {
flex: 1 1 auto; flex: 1 1 auto;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 1em; gap: 1em;
overflow: hidden; 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; flex: 1 1 auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; 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; flex: 0 0 auto;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: 0.5em; 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; flex: 1 1 1px;
display: flex; display: flex;
flex-direction: column; 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; 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; 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; 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; flex: 1 1 auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; 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; display: flex;
flex-direction: row; flex-direction: row;
gap: 1em; gap: 1em;
@ -289,19 +289,19 @@
font-size: smaller; font-size: smaller;
align-items: baseline; 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; 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; 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; flex: 1 1 auto;
display: grid; display: grid;
text-align: left; text-align: left;
overflow: hidden; 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-column: 1;
grid-row: 1; grid-row: 1;
padding: 0; padding: 0;
@ -311,22 +311,22 @@
min-width: 100%; min-width: 100%;
width: 0; 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%; 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-column: 1;
grid-row: 1; grid-row: 1;
caret-color: white; caret-color: white;
mix-blend-mode: difference; 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-content > #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-thumb {
visibility: hidden; visibility: hidden;
cursor: default; 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-content > #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-messageSyntaxInner {
padding: 0.75em; padding: 0.75em;
margin: 0; margin: 0;
border: none; border: none;
@ -335,11 +335,11 @@
border: 1px solid var(--SmartThemeBorderColor); border: 1px solid var(--SmartThemeBorderColor);
border-radius: 5px; 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; display: flex;
gap: 1em; 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-width: 2px;
border-style: solid; border-style: solid;
display: flex; display: flex;
@ -347,42 +347,42 @@
gap: 0.5em; gap: 0.5em;
padding: 0.5em 0.75em; 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; 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; transition: 200ms;
filter: grayscale(0); 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; cursor: wait;
opacity: 0.5; opacity: 0.5;
filter: grayscale(1); 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; border-color: #51a351;
} }
.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,
.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 {
cursor: default; cursor: default;
opacity: 0.5; opacity: 0.5;
filter: grayscale(1); filter: grayscale(1);
pointer-events: none; pointer-events: none;
} }
.popup:has(#qr--modalEditor) .popup_text > #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-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-stop {
cursor: pointer; cursor: pointer;
opacity: 1; opacity: 1;
filter: grayscale(0); filter: grayscale(0);
pointer-events: all; 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; 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; 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; --prog: 0;
--progColor: #92befc; --progColor: #92befc;
--progFlashColor: #d78872; --progFlashColor: #d78872;
@ -393,7 +393,7 @@
background-color: var(--black50a); background-color: var(--black50a);
position: relative; 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: ''; content: '';
background-color: var(--progColor); background-color: var(--progColor);
position: absolute; position: absolute;
@ -401,23 +401,23 @@
right: calc(100% - var(--prog) * 1%); right: calc(100% - var(--prog) * 1%);
transition: 200ms; 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-name: qr--progressPulse;
animation-duration: 1500ms; animation-duration: 1500ms;
animation-timing-function: ease-in-out; animation-timing-function: ease-in-out;
animation-delay: 0s; animation-delay: 0s;
animation-iteration-count: infinite; 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); 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); 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); 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; display: none;
text-align: left; text-align: left;
font-size: smaller; font-size: smaller;
@ -428,10 +428,10 @@
min-width: 100%; min-width: 100%;
width: 0; 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; 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; display: none;
text-align: left; text-align: left;
font-size: smaller; font-size: smaller;
@ -442,10 +442,10 @@
min-width: 100%; min-width: 100%;
width: 0; 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; 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: '; content: 'Result: ';
} }
@keyframes qr--progressPulse { @keyframes qr--progressPulse {

View File

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

View File

@ -1,5 +1,4 @@
import { debounce_timeout } from './constants.js'; import { removeFromArray, runAfterAnimation, uuidv4 } from './utils.js';
import { hasAnimation, removeFromArray, runAfterAnimation, uuidv4 } from './utils.js';
/** @readonly */ /** @readonly */
/** @enum {Number} */ /** @enum {Number} */
@ -10,16 +9,13 @@ export const POPUP_TYPE = {
}; };
/** @readonly */ /** @readonly */
/** @enum {number} */ /** @enum {number?} */
export const POPUP_RESULT = { export const POPUP_RESULT = {
'AFFIRMATIVE': 1, 'AFFIRMATIVE': 1,
'NEGATIVE': 0, 'NEGATIVE': 0,
'CANCELLED': undefined, 'CANCELLED': null,
}; };
/** @type {Popup[]} Remember all popups */
export const popups = [];
/** /**
* @typedef {object} PopupOptions * @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) * @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 * @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 { export class Popup {
/** @type {POPUP_TYPE} */ type; /** @type {POPUP_TYPE} */ type;
/** @type {string} */ id; /** @type {string} */ id;
/** @type {HTMLDialogElement} */ dlg; /** @type {HTMLDialogElement} */ dlg;
/** @type {HTMLElement} */ body;
/** @type {HTMLElement} */ content; /** @type {HTMLElement} */ content;
/** @type {HTMLElement} */ text;
/** @type {HTMLTextAreaElement} */ input; /** @type {HTMLTextAreaElement} */ input;
/** @type {HTMLElement} */ controls; /** @type {HTMLElement} */ controls;
/** @type {HTMLElement} */ ok; /** @type {HTMLElement} */ ok;
@ -67,15 +87,15 @@ export class Popup {
/** @type {(result: any) => any} */ resolver; /** @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 {POPUP_TYPE} type - The type of the popup
* @param {string} [inputValue=''] - The initial value of the input field * @param {string} [inputValue=''] - The initial value of the input field
* @param {PopupOptions} [options={}] - Additional options for the popup * @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 } = {}) { 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 } = {}) {
popups.push(this); Popup.util.popups.push(this);
// Make this popup uniquely identifiable // Make this popup uniquely identifiable
this.id = uuidv4(); this.id = uuidv4();
@ -85,12 +105,12 @@ export class Popup {
const template = document.querySelector('#popup_template'); const template = document.querySelector('#popup_template');
// @ts-ignore // @ts-ignore
this.dlg = template.content.cloneNode(true).querySelector('.popup'); this.dlg = template.content.cloneNode(true).querySelector('.popup');
this.content = this.dlg.querySelector('.popup_content'); this.body = this.dlg.querySelector('.popup-body');
this.text = this.dlg.querySelector('.popup_text'); this.content = this.dlg.querySelector('.popup-content');
this.input = this.dlg.querySelector('.popup_input'); this.input = this.dlg.querySelector('.popup-input');
this.controls = this.dlg.querySelector('.popup_controls'); this.controls = this.dlg.querySelector('.popup-controls');
this.ok = this.dlg.querySelector('.popup_ok'); this.ok = this.dlg.querySelector('.popup-button-ok');
this.cancel = this.dlg.querySelector('.popup_cancel'); this.cancel = this.dlg.querySelector('.popup-button-cancel');
this.dlg.setAttribute('data-id', this.id); this.dlg.setAttribute('data-id', this.id);
if (wide) this.dlg.classList.add('wide_dialogue_popup'); 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 // If custom button captions are provided, we set them beforehand
this.ok.textContent = typeof okButton === 'string' ? okButton : 'OK'; 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.defaultResult = defaultResult;
this.customButtons = customButtons; this.customButtons = customButtons;
@ -110,7 +130,7 @@ export class Popup {
const button = typeof x === 'string' ? { text: x, result: index + 2 } : x; const button = typeof x === 'string' ? { text: x, result: index + 2 } : x;
const buttonElement = document.createElement('div'); 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.classList.add(...(button.classes ?? []));
buttonElement.setAttribute('data-result', String(button.result ?? undefined)); buttonElement.setAttribute('data-result', String(button.result ?? undefined));
buttonElement.textContent = button.text; buttonElement.textContent = button.text;
@ -138,13 +158,13 @@ export class Popup {
} }
case POPUP_TYPE.CONFIRM: { case POPUP_TYPE.CONFIRM: {
this.input.style.display = 'none'; this.input.style.display = 'none';
if (!okButton) this.ok.textContent = template.getAttribute('popup_text_yes'); if (!okButton) this.ok.textContent = template.getAttribute('popup-button-yes');
if (!cancelButton) this.cancel.textContent = template.getAttribute('popup_text_no'); if (!cancelButton) this.cancel.textContent = template.getAttribute('popup-button-no');
break; break;
} }
case POPUP_TYPE.INPUT: { case POPUP_TYPE.INPUT: {
this.input.style.display = 'block'; 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; break;
} }
default: { default: {
@ -156,15 +176,15 @@ export class Popup {
this.input.value = inputValue; this.input.value = inputValue;
this.input.rows = rows ?? 1; this.input.rows = rows ?? 1;
this.text.innerHTML = ''; this.content.innerHTML = '';
if (text instanceof jQuery) { if (content instanceof jQuery) {
$(this.text).append(text); $(this.content).append(content);
} else if (text instanceof HTMLElement) { } else if (content instanceof HTMLElement) {
this.text.append(text); this.content.append(content);
} else if (typeof text == 'string') { } else if (typeof content == 'string') {
this.text.innerHTML = text; this.content.innerHTML = content;
} else { } 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() // 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; return;
// Check if the current focus is a result control. Only should we apply the compelete action // 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) if (!resultControl)
return; return;
@ -297,6 +317,7 @@ export class Popup {
this.value = value; this.value = value;
this.result = result; this.result = result;
Popup.util.lastResult = { value, result };
this.hide(); this.hide();
} }
@ -320,13 +341,13 @@ export class Popup {
this.dlg.remove(); this.dlg.remove();
// Remove it from the popup references // 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 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 activeDialog = document.activeElement?.closest('.popup');
const id = activeDialog?.getAttribute('data-id'); 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) {
if (popup.lastFocus) popup.lastFocus.focus(); if (popup.lastFocus) popup.lastFocus.focus();
else popup.setAutoFocus(); else popup.setAutoFocus();
@ -336,19 +357,45 @@ export class Popup {
this.resolver(this.value); 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 * Displays a blocking popup with a given content and type
* @param {JQuery<HTMLElement>|string|Element} text - Text to display in the popup * @param {JQuery<HTMLElement>|string|Element} content - Content or text to display in the popup
* @param {POPUP_TYPE} type * @param {POPUP_TYPE} type
* @param {string} inputValue - Value to set the input to * @param {string} inputValue - Value to set the input to
* @param {PopupOptions} [popupOptions={}] - Options for the popup * @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 * @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( const popup = new Popup(
text, content,
type, type,
inputValue, inputValue,
popupOptions, popupOptions,
@ -356,6 +403,9 @@ export function callGenericPopup(text, type, inputValue = '', popupOptions = {})
return popup.show(); 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() { export function fixToastrForDialogs() {
// Hacky way of getting toastr to actually display on top of the popup... // Hacky way of getting toastr to actually display on top of the popup...