Refactor: Replace Deprecated Code (#4221) * refactor: :recycle: Replace deprecated code defined within this repository - Replace ““/public/scripts.js” > `callPopup`” with ““/public/scripts/popup.js” > `callGenericPopup`”. - Replace ““/public/scripts/tokenizers.js” > `getTokenCount`” with ““/public/scripts/tokenizers.js” > `getTokenCountAsync`”. - Replace ““/public/scripts/extensions/assets/index.js” > `executeSlashCommands`” with ““/public/scripts/extensions/assets/index.js” > `executeSlashCommandsWithOptions`”. * refactor: :recycle: Replace deprecated code from standard library 1. Replace set of deprecated `escape` and deprecated `unescape` functions with `encodeURIComponent` and `decodeURIComponent` functions. 2. Replace set of `encodeURIComponent` and deprecated `unescape` functions with a custom `convertTextToBinaryString` function. * refactor: :recycle: Replace deprecated code imported from external library All of them is from jQuery. 1. Replace `$(document).ready(() => { ... })` → `jQuery(() => { ... })`. 2. Replace event type direct calls. 1) Change - `$('...').change(function () { ... })` → `$('...').on('change', function () { ... })`. 2) Click - `$('...').click(function () { ... })` → `$('...').on('click', function () { ... })`. - `$('...').click()` → `$('...').trigger('click')`. 3) Focus - `$('...').focus(function () { ... })` → `$('...').on('focus', function () { ... })`. - `$('...').focus()` → `$('...').trigger('focus')`. 4) Blur - `$('...').blur(function () { ... })` → `$('...').on('blur', function () { ... })`. 5) Keyup - `$('...').keyup(function () { ... })` → `$('...').on('keyup', function () { ... })`. * refactor(Attachment): :recycle: Merge `convertTextToBinaryString` and `convertTextToBase64` `convertTextToBase64` function use `Uint8Array.prototype.toBase64` if supported by the Browser and use a combination of `Window.btoa` and `String.fromCharCode` as fallback. * fix: :bug: Fix Bind World Info to Character Card Using the new `Popup` class. * fix: :bug: Fix Bind World Info to Character Card Using the new `Popup` class. * refactor: 🐛 Refactor and fix Character World Info popup Add singleton back and some optimization. - **🛡️ Singleton Pattern:** Implemented a singleton pattern using the `characterWorldPopup` variable. This prevents multiple instances of the popup from being created, ensuring a clean and predictable UI. If the popup is already open, it will be brought into focus instead of creating a duplicate. - **♻️ Improved Readability:** The event handling logic has been extracted into clearly named functions (`handlePrimaryWorldSelect`, `handleExtrasWorldSelect`), making the `Popup` constructor cleaner and the overall code more readable and maintainable. - **⚙️ Optimized Performance:** The new implementation caches frequently accessed values and jQuery selectors, reducing redundant DOM lookups and improving performance. --- * refactor(Chat): ♻️ Modernize chat deletion confirmation Replaces the deprecated `callPopup` with the modern `callGenericPopup` for the chat deletion confirmation dialog. * Fix /delchat command * Remove unused code * Fix type. Change value to debug log * Remove value logs * Remove singleton pattern for openCharacterWorldPopup --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>

1547a53d7c7de5c9225f33cf5d78486e75bc2623

GregW6 <atlanticgreg1@gmail.com>

Signed
12 files changed, +197 -165Ignore whitespace
public/script.js+135 -112
@@ -3560,7 +3560,7 @@ class StreamingProcessor {
35603560
3561 // Token count update.3561 // Token count update.
3562 const tokenCountText = this.reasoningHandler.reasoning + processedText;3562 const tokenCountText = this.reasoningHandler.reasoning + processedText;
3563 const currentTokenCount = isFinal && power_user.message_token_count_enabled ? getTokenCount(tokenCountText, 0) : 0;3563 const currentTokenCount = isFinal && power_user.message_token_count_enabled ? await getTokenCountAsync(tokenCountText, 0) : 0;
3564 if (currentTokenCount) {3564 if (currentTokenCount) {
3565 chat[messageId]['extra']['token_count'] = currentTokenCount;3565 chat[messageId]['extra']['token_count'] = currentTokenCount;
3566 if (this.messageTokenCounterDom instanceof HTMLElement) {3566 if (this.messageTokenCounterDom instanceof HTMLElement) {
@@ -8930,19 +8930,25 @@ function updateAlternateGreetingsHintVisibility(root) {
8930 $(root).find('.alternate_grettings_hint').toggle(numberOfGreetings == 0);8930 $(root).find('.alternate_grettings_hint').toggle(numberOfGreetings == 0);
8931}8931}
89328932
8933function openCharacterWorldPopup() {8933async function openCharacterWorldPopup() {
8934 const chid = $('#set_character_world').data('chid');8934 const chid = $('#set_character_world').data('chid');
8935
8936 if (menu_type != 'create' && chid === undefined) {8935 if (menu_type != 'create' && chid === undefined) {
8937 toastr.error('Does not have an Id for this character in world select menu.');8936 toastr.error('Does not have an Id for this character in world select menu.');
8938 return;8937 return;
8939 }8938 }
89408939
8941 async function onSelectCharacterWorld() {8940 // TODO: Maybe make this utility function not use the window context?
8942 const value = $('.character_world_info_selector').find('option:selected').val();8941 const fileName = getCharaFilename(chid);
8943 const worldIndex = value !== '' ? Number(value) : NaN;8942 const charName = (menu_type == 'create' ? create_save.name : characters[chid]?.data?.name) || 'Nameless';
8944 const name = !isNaN(worldIndex) ? world_names[worldIndex] : '';8943 const worldId = (menu_type == 'create' ? create_save.world : characters[chid]?.data?.extensions?.world) || '';
8944 const template = $('#character_world_template .character_world').clone();
8945 template.find('.character_name').text(charName);
89458946
8947 // --- Event Handlers ---
8948 async function handlePrimaryWorldSelect() {
8949 const selectedValue = $(this).val();
8950 const worldIndex = selectedValue !== '' ? Number(selectedValue) : NaN;
8951 const name = !isNaN(worldIndex) ? world_names[worldIndex] : '';
8946 const previousValue = $('#character_world').val();8952 const previousValue = $('#character_world').val();
8947 $('#character_world').val(name);8953 $('#character_world').val(name);
89488954
@@ -8970,26 +8976,21 @@ function openCharacterWorldPopup() {
8970 await createOrEditCharacter();8976 await createOrEditCharacter();
8971 }8977 }
89728978
8973 setWorldInfoButtonClass(undefined, !!value);8979 setWorldInfoButtonClass(undefined, !!name);
8974 }8980 }
89758981
8976 function onExtraWorldInfoChanged() {8982 function handleExtrasWorldSelect() {
8977 const selectorFieldValue = $('.character_extra_world_info_selector').val();8983 const selectedValues = $(this).val();
8978 const selectedWorlds = Array.isArray(selectorFieldValue) ? selectorFieldValue : [];8984 const selectedWorlds = Array.isArray(selectedValues) ? selectedValues : [];
8979 let charLore = world_info.charLore ?? [];8985 let charLore = world_info.charLore ?? [];
89808986 const tempExtraBooks = selectedWorlds.map((index) => world_names[index]).filter(Boolean);
8981 // TODO: Maybe make this utility function not use the window context?
8982 const fileName = getCharaFilename(chid);
8983 const tempExtraBooks = selectedWorlds.map((index) => world_names[index]).filter((e) => e !== undefined);
8984
8985 const existingCharIndex = charLore.findIndex((e) => e.name === fileName);8987 const existingCharIndex = charLore.findIndex((e) => e.name === fileName);
8986 if (existingCharIndex === -1) {
8987 const newCharLoreEntry = {
8988 name: fileName,
8989 extraBooks: tempExtraBooks,
8990 };
89918988
8992 charLore.push(newCharLoreEntry);8989 if (existingCharIndex === -1) {
8990 // Add record only if at least 1 lorebook is selected.
8991 if (tempExtraBooks.length > 0) {
8992 charLore.push({ name: fileName, extraBooks: tempExtraBooks });
8993 }
8993 } else if (tempExtraBooks.length === 0) {8994 } else if (tempExtraBooks.length === 0) {
8994 charLore.splice(existingCharIndex, 1);8995 charLore.splice(existingCharIndex, 1);
8995 } else {8996 } else {
@@ -9000,62 +9001,42 @@ function openCharacterWorldPopup() {
9000 saveSettingsDebounced();9001 saveSettingsDebounced();
9001 }9002 }
90029003
9003 const template = $('#character_world_template .character_world').clone();9004 // --- Populate Dropdowns ---
9004 const select = template.find('.character_world_info_selector');9005 // Append to primary dropdown.
9005 const extraSelect = template.find('.character_extra_world_info_selector');9006 const primarySelect = template.find('.character_world_info_selector');
9006 const name = (menu_type == 'create' ? create_save.name : characters[chid]?.data?.name) || 'Nameless';
9007 const worldId = (menu_type == 'create' ? create_save.world : characters[chid]?.data?.extensions?.world) || '';
9008 template.find('.character_name').text(name);
9009
9010 // Not needed on mobile
9011 if (!isMobile()) {
9012 $(extraSelect).select2({
9013 width: '100%',
9014 placeholder: t`No auxillary Lorebooks set. Click here to select.`,
9015 allowClear: true,
9016 closeOnSelect: false,
9017 });
9018 }
9019
9020 // Apped to base dropdown
9021 world_names.forEach((item, i) => {9007 world_names.forEach((item, i) => {
9022 const option = document.createElement('option');9008 primarySelect.append(new Option(item, String(i), item === worldId, item === worldId));
9023 option.value = String(i);
9024 option.innerText = item;
9025 option.selected = item === worldId;
9026 select.append(option);
9027 });9009 });
90289010
9029 // Append to extras dropdown9011 // Append to extras dropdown.
9030 if (world_names.length > 0) {9012 const extrasSelect = template.find('.character_extra_world_info_selector');
9031 extraSelect.empty();9013 const existingCharLore = world_info.charLore?.find((e) => e.name === fileName);
9032 }
9033 world_names.forEach((item, i) => {9014 world_names.forEach((item, i) => {
9034 const option = document.createElement('option');9015 const isSelected = !!existingCharLore?.extraBooks.includes(item);
9035 option.value = String(i);9016 extrasSelect.append(new Option(item, String(i), isSelected, isSelected));
9036 option.innerText = item;
9037
9038 const existingCharLore = world_info.charLore?.find((e) => e.name === getCharaFilename());
9039 if (existingCharLore) {
9040 option.selected = existingCharLore.extraBooks.includes(item);
9041 } else {
9042 option.selected = false;
9043 }
9044 extraSelect.append(option);
9045 });9017 });
90469018
9047 select.on('change', onSelectCharacterWorld);9019 const popup = new Popup(template, POPUP_TYPE.TEXT, '', {
9048 extraSelect.on('mousedown change', async function (e) {9020 onOpen: function (popup) {
9049 // If there's no world names, don't do anything9021 const popupDialog = $(popup.dlg);
9050 if (world_names.length === 0) {9022
9051 e.preventDefault();9023 primarySelect.on('change', handlePrimaryWorldSelect);
9052 return;9024 extrasSelect.on('change', handleExtrasWorldSelect);
9053 }9025
90549026 // Not needed on mobile.
9055 onExtraWorldInfoChanged();9027 if (!isMobile()) {
9028 extrasSelect.select2({
9029 width: '100%',
9030 placeholder: t`No auxiliary Lorebooks set. Click here to select.`,
9031 allowClear: true,
9032 closeOnSelect: false,
9033 dropdownParent: popupDialog,
9034 });
9035 }
9036 },
9056 });9037 });
90579038
9058 callPopup(template, 'text');9039 await popup.show();
9059}9040}
90609041
9061function openAlternateGreetings() {9042function openAlternateGreetings() {
@@ -10089,12 +10070,32 @@ export async function doNewChat({ deleteCurrentChat = false } = {}) {
10089}10070}
1009010071
10091async function doDeleteChat() {10072async function doDeleteChat() {
10092 await displayPastChats();10073 return displayPastChats().then(() => new Promise((resolve) => {
10093 let currentChatDeleteButton = $('.select_chat_block[highlight=\'true\']').parent().find('.PastChat_cross');10074 let resolved = false;
10094 $(currentChatDeleteButton).trigger('click');10075 const timeOutId = setTimeout(() => {
10095 await delay(1);10076 toastr.error(t`Chat deletion timed out. Please try again.`);
10096 $('#dialogue_popup_ok').trigger('click', { fromSlashCommand: true });10077 setResolved();
10097 return '';10078 }, 5000);
10079
10080 const setResolved = () => {
10081 if (resolved) {
10082 return;
10083 }
10084 resolved = true;
10085 [event_types.CHAT_DELETED, event_types.GROUP_CHAT_DELETED].forEach((eventType) => {
10086 eventSource.removeListener(eventType, setResolved);
10087 });
10088 clearTimeout(timeOutId);
10089 resolve('');
10090 };
10091
10092 [event_types.CHAT_DELETED, event_types.GROUP_CHAT_DELETED].forEach((eventType) => {
10093 eventSource.on(eventType, setResolved);
10094 });
10095
10096 const currentChatDeleteButton = $('.select_chat_block[highlight=\'true\']').parent().find('.PastChat_cross');
10097 $(currentChatDeleteButton).trigger('click', { fromSlashCommand: true });
10098 }));
10098}10099}
1009910100
10100async function doRenameChat(_, chatName) {10101async function doRenameChat(_, chatName) {
@@ -10764,10 +10765,10 @@ jQuery(async function () {
10764 });10765 });
10765 $('#send_but, #option_regenerate, #option_continue, #mes_continue, #mes_impersonate').on('click', () => {10766 $('#send_but, #option_regenerate, #option_continue, #mes_continue, #mes_impersonate').on('click', () => {
10766 if (S_TAPreviouslyFocused) {10767 if (S_TAPreviouslyFocused) {
10767 $('#send_textarea').focus();10768 $('#send_textarea').trigger('focus');
10768 }10769 }
10769 });10770 });
10770 $(document).click(event => {10771 $(document).on('click', event => {
10771 if ($(':focus').attr('id') !== 'send_textarea') {10772 if ($(':focus').attr('id') !== 'send_textarea') {
10772 var validIDs = ['options_button', 'send_but', 'mes_impersonate', 'mes_continue', 'send_textarea', 'option_regenerate', 'option_continue'];10773 var validIDs = ['options_button', 'send_but', 'mes_impersonate', 'mes_continue', 'send_textarea', 'option_regenerate', 'option_continue'];
10773 if (!validIDs.includes($(event.target).attr('id'))) {10774 if (!validIDs.includes($(event.target).attr('id'))) {
@@ -10780,7 +10781,7 @@ jQuery(async function () {
1078010781
10781 /////////////////10782 /////////////////
1078210783
10783 $('#swipes-checkbox').change(function () {10784 $('#swipes-checkbox').on('change', function () {
10784 swipes = !!$('#swipes-checkbox').prop('checked');10785 swipes = !!$('#swipes-checkbox').prop('checked');
10785 if (swipes) {10786 if (swipes) {
10786 //console.log('toggle change calling showswipebtns');10787 //console.log('toggle change calling showswipebtns');
@@ -10923,11 +10924,51 @@ jQuery(async function () {
10923 }10924 }
10924 });10925 });
1092510926
10926 $(document).on('click', '.PastChat_cross', function (e) {10927 /**
10928 * Handles the deletion of a chat file, including group chats.
10929 *
10930 * @param {string} chatFile - The name of the chat file to delete.
10931 * @param {object} group - The group object if the chat is part of a group.
10932 * @param {boolean} [fromSlashCommand=false] - Whether the deletion was triggered from a slash command.
10933 * @returns {Promise<void>}
10934 */
10935 async function handleDeleteChat(chatFile, group, fromSlashCommand = false) {
10936 // Close past chat popup.
10937 $('#select_chat_cross').trigger('click');
10938 showLoader();
10939 if (group) {
10940 await deleteGroupChat(group, chatFile);
10941 } else {
10942 await delChat(chatFile);
10943 }
10944
10945 if (fromSlashCommand) { // When called from `/delchat` command, don't re-open the history view.
10946 $('#options').hide(); // Hide option popup menu.
10947 hideLoader();
10948 } else { // Open the history view again after 2 seconds (delay to avoid edge cases for deleting last chat).
10949 setTimeout(function () {
10950 $('#option_select_chat').trigger('click');
10951 $('#options').hide(); // Hide option popup menu.
10952 hideLoader();
10953 }, 2000);
10954 }
10955 }
10956
10957 $(document).on('click', '.PastChat_cross', async function (e, { fromSlashCommand = false } = {}) {
10927 e.stopPropagation();10958 e.stopPropagation();
10928 chat_file_for_del = $(this).attr('file_name');10959 chat_file_for_del = $(this).attr('file_name');
10929 console.debug('detected cross click for' + chat_file_for_del);10960 console.debug('detected cross click for' + chat_file_for_del);
10930 callPopup('<h3>' + t`Delete the Chat File?` + '</h3>', 'del_chat');10961
10962 // Skip confirmation if called from a slash command.
10963 if (fromSlashCommand) {
10964 await handleDeleteChat(chat_file_for_del, selected_group, true);
10965 return;
10966 }
10967
10968 const result = await callGenericPopup('<h3>' + t`Delete the Chat File?` + '</h3>', POPUP_TYPE.CONFIRM);
10969 if (result === POPUP_RESULT.AFFIRMATIVE) {
10970 await handleDeleteChat(chat_file_for_del, selected_group, false);
10971 }
10931 });10972 });
1093210973
10933 $('#advanced_div').on('click', function () {10974 $('#advanced_div').on('click', function () {
@@ -10976,25 +11017,7 @@ jQuery(async function () {
10976 }, animation_duration);11017 }, animation_duration);
1097711018
10978 if (popup_type == 'del_chat') {11019 if (popup_type == 'del_chat') {
10979 //close past chat popup11020 await handleDeleteChat(chat_file_for_del, selected_group, fromSlashCommand);
10980 $('#select_chat_cross').trigger('click');
10981 showLoader();
10982 if (selected_group) {
10983 await deleteGroupChat(selected_group, chat_file_for_del);
10984 } else {
10985 await delChat(chat_file_for_del);
10986 }
10987
10988 if (fromSlashCommand) { // When called from `/delchat` command, don't re-open the history view.
10989 $('#options').hide(); // hide option popup menu
10990 hideLoader();
10991 } else { // Open the history view again after 2 seconds (delay to avoid edge cases for deleting last chat).
10992 setTimeout(function () {
10993 $('#option_select_chat').trigger('click');
10994 $('#options').hide(); // hide option popup menu
10995 hideLoader();
10996 }, 2000);
10997 }
10998 }11021 }
1099911022
11000 if (dialogueResolve) {11023 if (dialogueResolve) {
@@ -11457,7 +11480,7 @@ jQuery(async function () {
11457 is_delete_mode = false;11480 is_delete_mode = false;
11458 });11481 });
1145911482
11460 $('#settings_preset').change(function () {11483 $('#settings_preset').on('change', function () {
11461 if ($('#settings_preset').find(':selected').val() != 'gui') {11484 if ($('#settings_preset').find(':selected').val() != 'gui') {
11462 preset_settings = $('#settings_preset').find(':selected').text();11485 preset_settings = $('#settings_preset').find(':selected').text();
11463 const preset = koboldai_settings[koboldai_setting_names[preset_settings]];11486 const preset = koboldai_settings[koboldai_setting_names[preset_settings]];
@@ -11482,7 +11505,7 @@ jQuery(async function () {
11482 saveSettingsDebounced();11505 saveSettingsDebounced();
11483 });11506 });
1148411507
11485 $('#settings_preset_novel').change(function () {11508 $('#settings_preset_novel').on('change', function () {
11486 nai_settings.preset_settings_novel = $('#settings_preset_novel')11509 nai_settings.preset_settings_novel = $('#settings_preset_novel')
11487 .find(':selected')11510 .find(':selected')
11488 .text();11511 .text();
@@ -11495,7 +11518,7 @@ jQuery(async function () {
11495 saveSettingsDebounced();11518 saveSettingsDebounced();
11496 });11519 });
1149711520
11498 $('#main_api').change(function () {11521 $('#main_api').on('change', function () {
11499 cancelStatusCheck('Canceled because main api changed');11522 cancelStatusCheck('Canceled because main api changed');
11500 changeMainAPI();11523 changeMainAPI();
11501 saveSettingsDebounced();11524 saveSettingsDebounced();
@@ -12023,7 +12046,7 @@ jQuery(async function () {
12023 select_rm_characters();12046 select_rm_characters();
12024 });12047 });
1202512048
12026 $('#dupe_button').click(async function () {12049 $('#dupe_button').on('click', async function () {
12027 await duplicateCharacter();12050 await duplicateCharacter();
12028 });12051 });
1202912052
@@ -12223,18 +12246,18 @@ jQuery(async function () {
12223 }12246 }
12224 });12247 });
1222512248
12226 $(document).keyup(function (e) {12249 $(document).on('keyup', function (e) {
12227 if (e.key === 'Escape') {12250 if (e.key === 'Escape') {
12228 const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0;12251 const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0;
12229 if (isEditVisible && power_user.auto_save_msg_edits === false) {12252 if (isEditVisible && power_user.auto_save_msg_edits === false) {
12230 closeMessageEditor('all');12253 closeMessageEditor('all');
12231 $('#send_textarea').focus();12254 $('#send_textarea').trigger('focus');
12232 return;12255 return;
12233 }12256 }
12234 if (isEditVisible && power_user.auto_save_msg_edits === true) {12257 if (isEditVisible && power_user.auto_save_msg_edits === true) {
12235 $(`#chat .mes[mesid="${this_edit_mes_id}"] .mes_edit_done`).trigger('click');12258 $(`#chat .mes[mesid="${this_edit_mes_id}"] .mes_edit_done`).trigger('click');
12236 closeMessageEditor('reasoning');12259 closeMessageEditor('reasoning');
12237 $('#send_textarea').focus();12260 $('#send_textarea').trigger('focus');
12238 return;12261 return;
12239 }12262 }
12240 if (!this_edit_mes_id && $('#mes_stop').is(':visible')) {12263 if (!this_edit_mes_id && $('#mes_stop').is(':visible')) {
@@ -12251,13 +12274,13 @@ jQuery(async function () {
12251 const target = $(targetElement.selectedOptions).attr('id');12274 const target = $(targetElement.selectedOptions).attr('id');
12252 switch (target) {12275 switch (target) {
12253 case 'set_character_world':12276 case 'set_character_world':
12254 openCharacterWorldPopup();12277 await openCharacterWorldPopup();
12255 break;12278 break;
12256 case 'set_chat_scenario':12279 case 'set_chat_scenario':
12257 await setScenarioOverride();12280 await setScenarioOverride();
12258 break;12281 break;
12259 case 'renameCharButton':12282 case 'renameCharButton':
12260 renameCharacter();12283 await renameCharacter();
12261 break;12284 break;
12262 case 'import_character_info':12285 case 'import_character_info':
12263 await importEmbeddedWorldInfo();12286 await importEmbeddedWorldInfo();
@@ -12335,6 +12358,9 @@ jQuery(async function () {
12335 });12358 });
1233612359
12337 $(document).on('change', '.range-block-counter input, .neo-range-input', function (e) {12360 $(document).on('change', '.range-block-counter input, .neo-range-input', function (e) {
12361 if (!(e.target instanceof HTMLElement)) {
12362 return;
12363 }
12338 e.target.focus();12364 e.target.focus();
12339 e.target.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true }));12365 e.target.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true }));
12340 });12366 });
@@ -12355,7 +12381,6 @@ jQuery(async function () {
12355 } else {12381 } else {
12356 //if value not ok, warn and reset to last known valid value12382 //if value not ok, warn and reset to last known valid value
12357 toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);12383 toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);
12358 console.log(valueBeforeManualInput);
12359 //newSlider.val(valueBeforeManualInput)12384 //newSlider.val(valueBeforeManualInput)
12360 $(this).val(valueBeforeManualInput);12385 $(this).val(valueBeforeManualInput);
12361 }12386 }
@@ -12365,7 +12390,6 @@ jQuery(async function () {
1236512390
12366 $(document).on('keyup', '.range-block-counter input, .neo-range-input', function () {12391 $(document).on('keyup', '.range-block-counter input, .neo-range-input', function () {
12367 valueBeforeManualInput = $(this).val();12392 valueBeforeManualInput = $(this).val();
12368 console.log(valueBeforeManualInput);
12369 isManualInput = true;12393 isManualInput = true;
12370 });12394 });
1237112395
@@ -12383,7 +12407,6 @@ jQuery(async function () {
12383 } else {12407 } else {
12384 //if value not ok, warn and reset to last known valid value12408 //if value not ok, warn and reset to last known valid value
12385 toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);12409 toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);
12386 console.log(valueBeforeManualInput);
12387 $(this).val(valueBeforeManualInput);12410 $(this).val(valueBeforeManualInput);
12388 }12411 }
12389 }12412 }
public/scripts/RossAscends-mods.js+11 -11
@@ -434,19 +434,19 @@ function OpenNavPanels() {
434 //auto-open R nav if locked and previously open434 //auto-open R nav if locked and previously open
435 if (accountStorage.getItem('NavLockOn') == 'true' && accountStorage.getItem('NavOpened') == 'true') {435 if (accountStorage.getItem('NavLockOn') == 'true' && accountStorage.getItem('NavOpened') == 'true') {
436 //console.log("RA -- clicking right nav to open");436 //console.log("RA -- clicking right nav to open");
437 $('#rightNavDrawerIcon').click();437 $('#rightNavDrawerIcon').trigger('click');
438 }438 }
439439
440 //auto-open L nav if locked and previously open440 //auto-open L nav if locked and previously open
441 if (accountStorage.getItem('LNavLockOn') == 'true' && accountStorage.getItem('LNavOpened') == 'true') {441 if (accountStorage.getItem('LNavLockOn') == 'true' && accountStorage.getItem('LNavOpened') == 'true') {
442 console.debug('RA -- clicking left nav to open');442 console.debug('RA -- clicking left nav to open');
443 $('#leftNavDrawerIcon').click();443 $('#leftNavDrawerIcon').trigger('click');
444 }444 }
445445
446 //auto-open WI if locked and previously open446 //auto-open WI if locked and previously open
447 if (accountStorage.getItem('WINavLockOn') == 'true' && accountStorage.getItem('WINavOpened') == 'true') {447 if (accountStorage.getItem('WINavLockOn') == 'true' && accountStorage.getItem('WINavOpened') == 'true') {
448 console.debug('RA -- clicking WI to open');448 console.debug('RA -- clicking WI to open');
449 $('#WIDrawerIcon').click();449 $('#WIDrawerIcon').trigger('click');
450 }450 }
451 }451 }
452}452}
@@ -711,7 +711,7 @@ export function initRossMods() {
711 RA_autoconnect();711 RA_autoconnect();
712 }712 }
713713
714 $('#main_api').change(function () {714 $('#main_api').on('change', function () {
715 var PrevAPI = main_api;715 var PrevAPI = main_api;
716 setTimeout(() => RA_autoconnect(PrevAPI), 100);716 setTimeout(() => RA_autoconnect(PrevAPI), 100);
717 });717 });
@@ -834,11 +834,11 @@ export function initRossMods() {
834 });834 });
835835
836 var chatbarInFocus = false;836 var chatbarInFocus = false;
837 $('#send_textarea').focus(function () {837 $('#send_textarea').on('focus', function () {
838 chatbarInFocus = true;838 chatbarInFocus = true;
839 });839 });
840840
841 $('#send_textarea').blur(function () {841 $('#send_textarea').on('blur', function () {
842 chatbarInFocus = false;842 chatbarInFocus = false;
843 });843 });
844844
@@ -846,8 +846,8 @@ export function initRossMods() {
846 OpenNavPanels();846 OpenNavPanels();
847 }, 300);847 }, 300);
848848
849 $(SelectedCharacterTab).click(function () { accountStorage.setItem('SelectedNavTab', 'rm_button_selected_ch'); });849 $(SelectedCharacterTab).on('click', function () { accountStorage.setItem('SelectedNavTab', 'rm_button_selected_ch'); });
850 $('#rm_button_characters').click(function () { accountStorage.setItem('SelectedNavTab', 'rm_button_characters'); });850 $('#rm_button_characters').on('click', function () { accountStorage.setItem('SelectedNavTab', 'rm_button_characters'); });
851851
852 // when a char is selected from the list, save them as the auto-load character for next page load852 // when a char is selected from the list, save them as the auto-load character for next page load
853853
@@ -932,7 +932,7 @@ export function initRossMods() {
932 var SwipeTargetMesClassParent = $(e.target).closest('.last_mes');932 var SwipeTargetMesClassParent = $(e.target).closest('.last_mes');
933 if (SwipeTargetMesClassParent !== null) {933 if (SwipeTargetMesClassParent !== null) {
934 if (SwipeButR.css('display') === 'flex') {934 if (SwipeButR.css('display') === 'flex') {
935 SwipeButR.click();935 SwipeButR.trigger('click');
936 }936 }
937 }937 }
938 });938 });
@@ -956,7 +956,7 @@ export function initRossMods() {
956 var SwipeTargetMesClassParent = $(e.target).closest('.last_mes');956 var SwipeTargetMesClassParent = $(e.target).closest('.last_mes');
957 if (SwipeTargetMesClassParent !== null) {957 if (SwipeTargetMesClassParent !== null) {
958 if (SwipeButL.css('display') === 'flex') {958 if (SwipeButL.css('display') === 'flex') {
959 SwipeButL.click();959 SwipeButL.trigger('click');
960 }960 }
961 }961 }
962 });962 });
@@ -1159,7 +1159,7 @@ export function initRossMods() {
1159 const lastMes = document.querySelector('.last_mes');1159 const lastMes = document.querySelector('.last_mes');
1160 const editMes = lastMes.querySelector('.mes_block .mes_edit');1160 const editMes = lastMes.querySelector('.mes_block .mes_edit');
1161 if (editMes !== null) {1161 if (editMes !== null) {
1162 $(editMes).click();1162 $(editMes).trigger('click');
1163 return;1163 return;
1164 }1164 }
1165 }1165 }
public/scripts/cfg-scale.js+1 -1
@@ -135,7 +135,7 @@ function onCfgMenuItemClick() {
135 .siblings('.inline-drawer-content')135 .siblings('.inline-drawer-content')
136 .css('display') !== 'block') {136 .css('display') !== 'block') {
137 $('#floatingPrompt').addClass('resizing');137 $('#floatingPrompt').addClass('resizing');
138 $('#CFGBlockToggle').click();138 $('#CFGBlockToggle').trigger('click');
139 }139 }
140 } else {140 } else {
141 //hide AN if it's already displayed141 //hide AN if it's already displayed
public/scripts/chats.js+6 -5
@@ -44,6 +44,7 @@ import {
44 download,44 download,
45 getFileText,45 getFileText,
46 getFileExtension,46 getFileExtension,
47 convertTextToBase64,
47} from './utils.js';48} from './utils.js';
48import { extension_settings, renderExtensionTemplateAsync, saveMetadataDebounced } from './extensions.js';49import { extension_settings, renderExtensionTemplateAsync, saveMetadataDebounced } from './extensions.js';
49import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';50import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
@@ -224,7 +225,7 @@ export async function populateFileAttachment(message, inputId = 'file_form_input
224 try {225 try {
225 const converter = getConverter(file.type);226 const converter = getConverter(file.type);
226 const fileText = await converter(file);227 const fileText = await converter(file);
227 base64Data = window.btoa(unescape(encodeURIComponent(fileText)));228 base64Data = convertTextToBase64(fileText);
228 } catch (error) {229 } catch (error) {
229 toastr.error(String(error), t`Could not convert file`);230 toastr.error(String(error), t`Could not convert file`);
230 console.error('Could not convert file', error);231 console.error('Could not convert file', error);
@@ -477,7 +478,7 @@ export async function appendFileContent(message, messageText) {
477export function encodeStyleTags(text) {478export function encodeStyleTags(text) {
478 const styleRegex = /<style>(.+?)<\/style>/gims;479 const styleRegex = /<style>(.+?)<\/style>/gims;
479 return text.replaceAll(styleRegex, (_, match) => {480 return text.replaceAll(styleRegex, (_, match) => {
480 return `<custom-style>${escape(match)}</custom-style>`;481 return `<custom-style>${encodeURIComponent(match)}</custom-style>`;
481 });482 });
482}483}
483484
@@ -530,7 +531,7 @@ export function decodeStyleTags(text, { prefix } = { prefix: '.mes_text ' }) {
530531
531 return text.replaceAll(styleDecodeRegex, (_, style) => {532 return text.replaceAll(styleDecodeRegex, (_, style) => {
532 try {533 try {
533 let styleCleaned = unescape(style).replaceAll(/<br\/>/g, '');534 let styleCleaned = decodeURIComponent(style).replaceAll(/<br\/>/g, '');
534 const ast = css.parse(styleCleaned);535 const ast = css.parse(styleCleaned);
535 const sheet = ast?.stylesheet;536 const sheet = ast?.stylesheet;
536 if (sheet) {537 if (sheet) {
@@ -1497,14 +1498,14 @@ export async function uploadFileAttachmentToServer(file, target) {
1497 try {1498 try {
1498 const converter = getConverter(file.type);1499 const converter = getConverter(file.type);
1499 const fileText = await converter(file);1500 const fileText = await converter(file);
1500 base64Data = window.btoa(unescape(encodeURIComponent(fileText)));1501 base64Data = convertTextToBase64(fileText);
1501 } catch (error) {1502 } catch (error) {
1502 toastr.error(String(error), t`Could not convert file`);1503 toastr.error(String(error), t`Could not convert file`);
1503 console.error('Could not convert file', error);1504 console.error('Could not convert file', error);
1504 }1505 }
1505 } else {1506 } else {
1506 const fileText = await file.text();1507 const fileText = await file.text();
1507 base64Data = window.btoa(unescape(encodeURIComponent(fileText)));1508 base64Data = convertTextToBase64(fileText);
1508 }1509 }
15091510
1510 const fileUrl = await uploadFileAttachment(uniqueFileName, base64Data);1511 const fileUrl = await uploadFileAttachment(uniqueFileName, base64Data);
public/scripts/extensions/assets/index.js+2 -2
@@ -7,7 +7,7 @@ import { DOMPurify } from '../../../lib.js';
7import { getRequestHeaders, processDroppedFiles, eventSource, event_types } from '../../../script.js';7import { getRequestHeaders, processDroppedFiles, eventSource, event_types } from '../../../script.js';
8import { deleteExtension, extensionNames, getContext, installExtension, renderExtensionTemplateAsync } from '../../extensions.js';8import { deleteExtension, extensionNames, getContext, installExtension, renderExtensionTemplateAsync } from '../../extensions.js';
9import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js';9import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js';
10import { executeSlashCommands } from '../../slash-commands.js';10import { executeSlashCommandsWithOptions } from '../../slash-commands.js';
11import { accountStorage } from '../../util/AccountStorage.js';11import { accountStorage } from '../../util/AccountStorage.js';
12import { flashHighlight, getStringHash, isValidUrl } from '../../utils.js';12import { flashHighlight, getStringHash, isValidUrl } from '../../utils.js';
13import { t } from '../../i18n.js';13import { t } from '../../i18n.js';
@@ -142,7 +142,7 @@ async function downloadAssetsList(url) {
142 const assetDelete = async function () {142 const assetDelete = async function () {
143 if (assetType === 'character') {143 if (assetType === 'character') {
144 toastr.error('Go to the characters menu to delete a character.', 'Character deletion not supported');144 toastr.error('Go to the characters menu to delete a character.', 'Character deletion not supported');
145 await executeSlashCommands(`/go ${asset['id']}`);145 await executeSlashCommandsWithOptions(`/go ${asset['id']}`);
146 return;146 return;
147 }147 }
148 element.off('click');148 element.off('click');
public/scripts/extensions/token-counter/index.js+0 -13
@@ -9,19 +9,6 @@ import { POPUP_TYPE, callGenericPopup } from '../../popup.js';
9import { renderExtensionTemplateAsync } from '../../extensions.js';9import { renderExtensionTemplateAsync } from '../../extensions.js';
10import { t } from '../../i18n.js';10import { t } from '../../i18n.js';
1111
12function rgb2hex(rgb) {
13 rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
14 return (rgb && rgb.length === 4) ? '#' +
15 ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) +
16 ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2) +
17 ('0' + parseInt(rgb[3], 10).toString(16)).slice(-2) : '';
18}
19
20$('button').click(function () {
21 var hex = rgb2hex($('input').val());
22 $('.result').html(hex);
23});
24
25async function doTokenCounter() {12async function doTokenCounter() {
26 const { tokenizerName, tokenizerId } = getFriendlyTokenizerName(main_api);13 const { tokenizerName, tokenizerId } = getFriendlyTokenizerName(main_api);
27 const html = await renderExtensionTemplateAsync('token-counter', 'window', { tokenizerName });14 const html = await renderExtensionTemplateAsync('token-counter', 'window', { tokenizerName });
public/scripts/extensions/tts/alltalk.js+9 -9
@@ -296,20 +296,20 @@ class AllTalkTtsProvider {
296 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues');296 const ttsNarrateDialoguesCheckbox = document.getElementById('tts_narrate_dialogues');
297 if (this.settings.narrator_enabled) {297 if (this.settings.narrator_enabled) {
298 ttsPassAsterisksCheckbox.checked = false;298 ttsPassAsterisksCheckbox.checked = false;
299 $('#tts_pass_asterisks').click();299 $('#tts_pass_asterisks').trigger('click');
300 $('#tts_pass_asterisks').trigger('change');300 $('#tts_pass_asterisks').trigger('change');
301 }301 }
302 if (!this.settings.narrator_enabled) {302 if (!this.settings.narrator_enabled) {
303 ttsPassAsterisksCheckbox.checked = true;303 ttsPassAsterisksCheckbox.checked = true;
304 $('#tts_pass_asterisks').click();304 $('#tts_pass_asterisks').trigger('click');
305 $('#tts_pass_asterisks').trigger('change');305 $('#tts_pass_asterisks').trigger('change');
306 }306 }
307 if (this.settings.narrator_enabled) {307 if (this.settings.narrator_enabled) {
308 ttsNarrateQuotedCheckbox.checked = true;308 ttsNarrateQuotedCheckbox.checked = true;
309 ttsNarrateDialoguesCheckbox.checked = true;309 ttsNarrateDialoguesCheckbox.checked = true;
310 $('#tts_narrate_quoted').click();310 $('#tts_narrate_quoted').trigger('click');
311 $('#tts_narrate_quoted').trigger('change');311 $('#tts_narrate_quoted').trigger('change');
312 $('#tts_narrate_dialogues').click();312 $('#tts_narrate_dialogues').trigger('click');
313 $('#tts_narrate_dialogues').trigger('change');313 $('#tts_narrate_dialogues').trigger('change');
314 }314 }
315 atNarratorSelect.value = this.settings.narrator_enabled.toString();315 atNarratorSelect.value = this.settings.narrator_enabled.toString();
@@ -783,21 +783,21 @@ class AllTalkTtsProvider {
783783
784 if (narratorOption === 'true') {784 if (narratorOption === 'true') {
785 ttsPassAsterisksCheckbox.checked = false;785 ttsPassAsterisksCheckbox.checked = false;
786 $('#tts_pass_asterisks').click();786 $('#tts_pass_asterisks').trigger('click');
787 $('#tts_pass_asterisks').trigger('change');787 $('#tts_pass_asterisks').trigger('change');
788 ttsNarrateQuotedCheckbox.checked = true;788 ttsNarrateQuotedCheckbox.checked = true;
789 ttsNarrateDialoguesCheckbox.checked = true;789 ttsNarrateDialoguesCheckbox.checked = true;
790 $('#tts_narrate_quoted').click();790 $('#tts_narrate_quoted').trigger('click');
791 $('#tts_narrate_quoted').trigger('change');791 $('#tts_narrate_quoted').trigger('change');
792 $('#tts_narrate_dialogues').click();792 $('#tts_narrate_dialogues').trigger('click');
793 $('#tts_narrate_dialogues').trigger('change');793 $('#tts_narrate_dialogues').trigger('change');
794 } else if (narratorOption === 'silent') {794 } else if (narratorOption === 'silent') {
795 ttsPassAsterisksCheckbox.checked = false;795 ttsPassAsterisksCheckbox.checked = false;
796 $('#tts_pass_asterisks').click();796 $('#tts_pass_asterisks').trigger('click');
797 $('#tts_pass_asterisks').trigger('change');797 $('#tts_pass_asterisks').trigger('change');
798 } else {798 } else {
799 ttsPassAsterisksCheckbox.checked = true;799 ttsPassAsterisksCheckbox.checked = true;
800 $('#tts_pass_asterisks').click();800 $('#tts_pass_asterisks').trigger('click');
801 $('#tts_pass_asterisks').trigger('change');801 $('#tts_pass_asterisks').trigger('change');
802 }802 }
803803
public/scripts/nai-settings.js+1 -1
@@ -837,7 +837,7 @@ jQuery(function () {
837 saveSettingsDebounced();837 saveSettingsDebounced();
838 });838 });
839839
840 $('#model_novel_select').change(function () {840 $('#model_novel_select').on('change', function () {
841 nai_settings.model_novel = String($('#model_novel_select').find(':selected').val());841 nai_settings.model_novel = String($('#model_novel_select').find(':selected').val());
842 saveSettingsDebounced();842 saveSettingsDebounced();
843843
public/scripts/power-user.js+9 -9
@@ -3151,7 +3151,7 @@ export function forceCharacterEditorTokenize() {
3151 $('#character_popup').trigger('input');3151 $('#character_popup').trigger('input');
3152}3152}
31533153
3154$(document).ready(() => {3154jQuery(() => {
3155 const adjustAutocompleteDebounced = debounce(() => {3155 const adjustAutocompleteDebounced = debounce(() => {
3156 $('.ui-autocomplete-input').each(function () {3156 $('.ui-autocomplete-input').each(function () {
3157 const isOpen = $(this).autocomplete('widget')[0].style.display !== 'none';3157 const isOpen = $(this).autocomplete('widget')[0].style.display !== 'none';
@@ -3236,7 +3236,7 @@ $(document).ready(() => {
3236 });3236 });
32373237
3238 // Settings that go to settings.json3238 // Settings that go to settings.json
3239 $('#collapse-newlines-checkbox').change(function () {3239 $('#collapse-newlines-checkbox').on('change', function () {
3240 power_user.collapse_newlines = !!$(this).prop('checked');3240 power_user.collapse_newlines = !!$(this).prop('checked');
3241 saveSettingsDebounced();3241 saveSettingsDebounced();
3242 });3242 });
@@ -3244,7 +3244,7 @@ $(document).ready(() => {
3244 // include newline is the child of trim sentences3244 // include newline is the child of trim sentences
3245 // if include newline is checked, trim sentences must be checked3245 // if include newline is checked, trim sentences must be checked
3246 // if trim sentences is unchecked, include newline must be unchecked3246 // if trim sentences is unchecked, include newline must be unchecked
3247 $('#trim_sentences_checkbox').change(function () {3247 $('#trim_sentences_checkbox').on('change', function () {
3248 power_user.trim_sentences = !!$(this).prop('checked');3248 power_user.trim_sentences = !!$(this).prop('checked');
3249 saveSettingsDebounced();3249 saveSettingsDebounced();
3250 });3250 });
@@ -3293,7 +3293,7 @@ $(document).ready(() => {
32933293
3294 $('#bind_model_templates').on('change', updateBindModelTemplatesState);3294 $('#bind_model_templates').on('change', updateBindModelTemplatesState);
32953295
3296 $('#always-force-name2-checkbox').change(function () {3296 $('#always-force-name2-checkbox').on('change', function () {
3297 power_user.always_force_name2 = !!$(this).prop('checked');3297 power_user.always_force_name2 = !!$(this).prop('checked');
3298 saveSettingsDebounced();3298 saveSettingsDebounced();
3299 });3299 });
@@ -3309,7 +3309,7 @@ $(document).ready(() => {
3309 saveSettingsDebounced();3309 saveSettingsDebounced();
3310 });3310 });
33113311
3312 $('#chat-show-reply-prefix-checkbox').change(function () {3312 $('#chat-show-reply-prefix-checkbox').on('change', function () {
3313 power_user.show_user_prompt_bias = !!$(this).prop('checked');3313 power_user.show_user_prompt_bias = !!$(this).prop('checked');
3314 reloadCurrentChat();3314 reloadCurrentChat();
3315 saveSettingsDebounced();3315 saveSettingsDebounced();
@@ -3355,7 +3355,7 @@ $(document).ready(() => {
3355 saveSettingsDebounced();3355 saveSettingsDebounced();
3356 });3356 });
33573357
3358 $('#fast_ui_mode').change(function () {3358 $('#fast_ui_mode').on('change', function () {
3359 power_user.fast_ui_mode = $(this).prop('checked');3359 power_user.fast_ui_mode = $(this).prop('checked');
3360 switchUiMode();3360 switchUiMode();
3361 saveSettingsDebounced();3361 saveSettingsDebounced();
@@ -3373,13 +3373,13 @@ $(document).ready(() => {
3373 applyCustomCSS();3373 applyCustomCSS();
3374 });3374 });
33753375
3376 $('#movingUImode').change(function () {3376 $('#movingUImode').on('change', function () {
3377 power_user.movingUI = $(this).prop('checked');3377 power_user.movingUI = $(this).prop('checked');
3378 switchMovingUI();3378 switchMovingUI();
3379 saveSettingsDebounced();3379 saveSettingsDebounced();
3380 });3380 });
33813381
3382 $('#noShadowsmode').change(function () {3382 $('#noShadowsmode').on('change', function () {
3383 power_user.noShadows = $(this).prop('checked');3383 power_user.noShadows = $(this).prop('checked');
3384 applyNoShadows();3384 applyNoShadows();
3385 saveSettingsDebounced();3385 saveSettingsDebounced();
@@ -3848,7 +3848,7 @@ $(document).ready(() => {
3848 saveSettingsDebounced();3848 saveSettingsDebounced();
3849 });3849 });
38503850
3851 $('#custom_stopping_strings_macro').change(function () {3851 $('#custom_stopping_strings_macro').on('change', function () {
3852 power_user.custom_stopping_strings_macro = !!$(this).prop('checked');3852 power_user.custom_stopping_strings_macro = !!$(this).prop('checked');
3853 saveSettingsDebounced();3853 saveSettingsDebounced();
3854 });3854 });
public/scripts/server-history.js+1 -1
@@ -46,7 +46,7 @@ function createServerAutocomplete() {
46 select: (e, u) => selectServer(e, u, serverLabel),46 select: (e, u) => selectServer(e, u, serverLabel),
47 minLength: 0,47 minLength: 0,
48 })48 })
49 .focus(onInputFocus); // <== show tag list on click49 .on('focus', onInputFocus); // <== show tag list on click
50}50}
5151
52function onInputFocus() {52function onInputFocus() {
public/scripts/tags.js+1 -1
@@ -1301,7 +1301,7 @@ export function createTagInput(inputSelector, listSelector, tagListOptions = {})
1301 select: (e, u) => selectTag(e, u, listSelector, { tagListOptions: tagListOptions }),1301 select: (e, u) => selectTag(e, u, listSelector, { tagListOptions: tagListOptions }),
1302 minLength: 0,1302 minLength: 0,
1303 })1303 })
1304 .focus(onTagInputFocus); // <== show tag list on click1304 .on('focus', onTagInputFocus); // <== show tag list on click
1305}1305}
13061306
1307async function onViewTagsListClick() {1307async function onViewTagsListClick() {
public/scripts/utils.js+21 -0
@@ -1453,6 +1453,27 @@ export function getFileExtension(file) {
1453}1453}
14541454
1455/**1455/**
1456 * Converts UTF-8 string into Base64-encoded string.
1457 *
1458 * @param {string} text The UTF-8 string
1459 * @returns {string} The Base64-encoded string
1460 */
1461export function convertTextToBase64(text) {
1462 const encoder = new TextEncoder();
1463 const utf8Bytes = encoder.encode(text);
1464 /**
1465 * return `true` if `Uint8Array.prototype.toBase64` function is supported.
1466 * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array/toBase64|MDN Reference}
1467 */
1468 if ('toBase64' in Uint8Array.prototype) {
1469 return utf8Bytes.toBase64();
1470 }
1471 // Creates binary string, where each character's code point directly matches the byte value (0-255).
1472 const binaryString = String.fromCharCode(...utf8Bytes);
1473 return window.btoa(binaryString);
1474}
1475
1476/**
1456 * Loads either a CSS or JS file and appends it to the appropriate document section.1477 * Loads either a CSS or JS file and appends it to the appropriate document section.
1457 *1478 *
1458 * @param {string} url - The URL of the file to be loaded.1479 * @param {string} url - The URL of the file to be loaded.