text-generation-webui/js/main.js

467 lines
15 KiB
JavaScript
Raw Normal View History

2023-10-07 22:07:57 -04:00
let main_parent = document.getElementById("chat-tab").parentNode;
let extensions = document.getElementById("extensions");
2023-08-13 00:12:15 -04:00
main_parent.childNodes[0].classList.add("header_bar");
main_parent.style = "padding: 0; margin: 0";
2023-08-29 19:15:12 -04:00
main_parent.parentNode.style = "gap: 0";
2023-08-13 00:12:15 -04:00
main_parent.parentNode.parentNode.style = "padding: 0";
2023-10-07 22:07:57 -04:00
document.querySelector(".header_bar").addEventListener("click", function(event) {
if (event.target.tagName === "BUTTON") {
const buttonText = event.target.textContent.trim();
let chat_visible = (buttonText == "Chat");
let default_visible = (buttonText == "Default");
let notebook_visible = (buttonText == "Notebook");
// Check if one of the generation tabs is visible
if (chat_visible || notebook_visible || default_visible) {
extensions && (extensions.style.display = "flex");
2023-10-07 22:07:57 -04:00
if (chat_visible) {
2023-12-19 17:27:11 -05:00
this.style.marginBottom = "0px";
extensions && (extensions.style.maxWidth = "880px");
extensions && (extensions.style.padding = "0px");
2023-10-07 22:07:57 -04:00
} else {
2023-12-19 17:27:11 -05:00
this.style.marginBottom = "19px";
extensions && (extensions.style.maxWidth = "none");
extensions && (extensions.style.padding = "15px");
2023-10-07 22:07:57 -04:00
}
} else {
2023-12-19 17:42:13 -05:00
this.style.marginBottom = "19px";
extensions && (extensions.style.display = "none");
}
2023-10-07 22:07:57 -04:00
}
});
//------------------------------------------------
2023-08-27 16:06:01 -04:00
// Keyboard shortcuts
//------------------------------------------------
2024-01-09 19:27:50 -05:00
let previousTabId = "chat-tab-button";
2023-08-03 11:13:17 -04:00
document.addEventListener("keydown", function(event) {
2023-08-27 16:06:01 -04:00
// Stop generation on Esc pressed
2023-08-03 11:13:17 -04:00
if (event.key === "Escape") {
// Find the element with id 'stop' and click it
var stopButton = document.getElementById("stop");
if (stopButton) {
stopButton.click();
}
}
2023-08-27 16:06:01 -04:00
2023-09-13 22:21:39 -04:00
// Show chat controls on Ctrl + S
2023-08-27 16:06:01 -04:00
else if (event.ctrlKey && event.key == "s") {
event.preventDefault();
2023-10-07 22:07:57 -04:00
var showControlsElement = document.getElementById("show-controls");
2023-08-27 16:06:01 -04:00
if (showControlsElement && showControlsElement.childNodes.length >= 4) {
showControlsElement.childNodes[3].click();
2023-08-27 19:45:37 -04:00
2023-10-07 22:07:57 -04:00
var arr = document.getElementById("chat-input").childNodes[2].childNodes;
2023-08-27 19:45:37 -04:00
arr[arr.length - 1].focus();
2023-08-27 16:06:01 -04:00
}
}
2023-09-13 22:21:39 -04:00
// Regenerate on Ctrl + Enter
2023-10-07 22:07:57 -04:00
else if (event.ctrlKey && event.key === "Enter") {
2023-09-13 22:21:39 -04:00
event.preventDefault();
2023-10-07 22:07:57 -04:00
document.getElementById("Regenerate").click();
2023-09-13 22:21:39 -04:00
}
2023-09-14 06:59:12 -04:00
// Continue on Alt + Enter
2023-10-07 22:07:57 -04:00
else if (event.altKey && event.key === "Enter") {
2023-09-13 22:21:39 -04:00
event.preventDefault();
2023-10-07 22:07:57 -04:00
document.getElementById("Continue").click();
2023-09-13 22:21:39 -04:00
}
// Remove last on Ctrl + Shift + Backspace
2023-10-07 22:07:57 -04:00
else if (event.ctrlKey && event.shiftKey && event.key === "Backspace") {
2023-09-13 22:21:39 -04:00
event.preventDefault();
2023-10-07 22:07:57 -04:00
document.getElementById("Remove-last").click();
2023-09-13 22:21:39 -04:00
}
// Copy last on Ctrl + Shift + K
2023-10-07 22:07:57 -04:00
else if (event.ctrlKey && event.shiftKey && event.key === "K") {
2023-09-13 22:21:39 -04:00
event.preventDefault();
2023-10-07 22:07:57 -04:00
document.getElementById("Copy-last").click();
2023-09-13 22:21:39 -04:00
}
// Replace last on Ctrl + Shift + L
2023-10-07 22:07:57 -04:00
else if (event.ctrlKey && event.shiftKey && event.key === "L") {
2023-09-13 22:21:39 -04:00
event.preventDefault();
2023-10-07 22:07:57 -04:00
document.getElementById("Replace-last").click();
2023-09-13 22:21:39 -04:00
}
// Impersonate on Ctrl + Shift + M
2023-10-07 22:07:57 -04:00
else if (event.ctrlKey && event.shiftKey && event.key === "M") {
2023-09-13 22:21:39 -04:00
event.preventDefault();
2023-10-07 22:07:57 -04:00
document.getElementById("Impersonate").click();
2023-09-13 22:21:39 -04:00
}
// Switch between tabs on Tab
2024-01-10 06:57:32 -05:00
else if (!event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey && event.key === "Tab") {
event.preventDefault();
2024-01-09 19:27:50 -05:00
var parametersButton = document.getElementById("parameters-button");
var parentContainer = parametersButton.parentNode;
2024-01-09 19:27:50 -05:00
var selectedChild = parentContainer.querySelector(".selected");
2024-01-09 19:27:50 -05:00
if (selectedChild.id == "parameters-button") {
document.getElementById(previousTabId).click();
} else {
2024-01-09 19:27:50 -05:00
previousTabId = selectedChild.id;
parametersButton.click();
}
}
2023-08-03 11:13:17 -04:00
});
2023-08-17 00:03:40 -04:00
//------------------------------------------------
// Position the chat typing dots
//------------------------------------------------
2023-10-07 22:07:57 -04:00
typing = document.getElementById("typing-container");
typingParent = typing.parentNode;
typingSibling = typing.previousElementSibling;
typingSibling.insertBefore(typing, typingSibling.childNodes[2]);
//------------------------------------------------
2023-08-17 00:03:40 -04:00
// Chat scrolling
//------------------------------------------------
2023-10-07 22:07:57 -04:00
const targetElement = document.getElementById("chat").parentNode.parentNode.parentNode;
targetElement.classList.add("pretty_scrollbar");
targetElement.classList.add("chat-parent");
let isScrolled = false;
2023-10-07 22:07:57 -04:00
targetElement.addEventListener("scroll", function() {
let diff = targetElement.scrollHeight - targetElement.clientHeight;
2023-09-19 16:12:34 -04:00
if(Math.abs(targetElement.scrollTop - diff) <= 10 || diff == 0) {
isScrolled = false;
} else {
isScrolled = true;
}
});
2023-08-17 00:03:40 -04:00
// Create a MutationObserver instance
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
updateCssProperties();
2023-12-16 20:16:26 -05:00
if(!isScrolled) {
targetElement.scrollTop = targetElement.scrollHeight;
}
const firstChild = targetElement.children[0];
2023-10-07 22:07:57 -04:00
if (firstChild.classList.contains("generating")) {
typing.parentNode.classList.add("visible-dots");
document.getElementById("stop").style.display = "flex";
document.getElementById("Generate").style.display = "none";
} else {
2023-10-07 22:07:57 -04:00
typing.parentNode.classList.remove("visible-dots");
document.getElementById("stop").style.display = "none";
document.getElementById("Generate").style.display = "flex";
}
2023-08-17 00:03:40 -04:00
});
});
// Configure the observer to watch for changes in the subtree and attributes
const config = {
childList: true,
subtree: true,
characterData: true,
attributeOldValue: true,
characterDataOldValue: true
};
// Start observing the target element
observer.observe(targetElement, config);
//------------------------------------------------
// Add some scrollbars
//------------------------------------------------
2023-10-07 22:07:57 -04:00
const textareaElements = document.querySelectorAll(".add_scrollbar textarea");
for(i = 0; i < textareaElements.length; i++) {
2023-10-07 22:07:57 -04:00
textareaElements[i].classList.remove("scroll-hide");
textareaElements[i].classList.add("pretty_scrollbar");
textareaElements[i].style.resize = "none";
}
//------------------------------------------------
// Remove some backgrounds
//------------------------------------------------
2023-10-07 22:07:57 -04:00
const noBackgroundelements = document.querySelectorAll(".no-background");
for(i = 0; i < noBackgroundelements.length; i++) {
2023-10-07 22:07:57 -04:00
noBackgroundelements[i].parentNode.style.border = "none";
noBackgroundelements[i].parentNode.parentNode.parentNode.style.alignItems = "center";
}
2023-09-13 01:36:12 -04:00
2023-12-27 12:59:23 -05:00
const slimDropdownElements = document.querySelectorAll(".slim-dropdown");
2023-10-10 21:20:49 -04:00
for (i = 0; i < slimDropdownElements.length; i++) {
2023-12-27 12:59:23 -05:00
const parentNode = slimDropdownElements[i].parentNode;
parentNode.style.background = "transparent";
parentNode.style.border = "0";
2023-10-10 21:20:49 -04:00
}
2023-09-13 01:36:12 -04:00
//------------------------------------------------
// Create the hover menu in the chat tab
// The show/hide events were adapted from:
// https://github.com/SillyTavern/SillyTavern/blob/6c8bd06308c69d51e2eb174541792a870a83d2d6/public/script.js
2023-09-13 01:36:12 -04:00
//------------------------------------------------
var buttonsInChat = document.querySelectorAll("#chat-tab:not(.old-ui) #chat-buttons button");
2023-10-07 22:07:57 -04:00
var button = document.getElementById("hover-element-button");
var menu = document.getElementById("hover-menu");
var istouchscreen = (navigator.maxTouchPoints > 0) || "ontouchstart" in document.documentElement;
function showMenu() {
2023-10-07 22:07:57 -04:00
menu.style.display = "flex"; // Show the menu
}
function hideMenu() {
2023-10-07 22:07:57 -04:00
menu.style.display = "none"; // Hide the menu
if (!istouchscreen) {
document.querySelector("#chat-input textarea").focus(); // Focus on the chat input
}
}
2023-09-13 01:36:12 -04:00
if (buttonsInChat.length > 0) {
2023-10-07 22:07:57 -04:00
for (let i = buttonsInChat.length - 1; i >= 0; i--) {
const thisButton = buttonsInChat[i];
menu.appendChild(thisButton);
thisButton.addEventListener("click", () => {
hideMenu();
});
const buttonText = thisButton.textContent;
const matches = buttonText.match(/(\(.*?\))/);
if (matches && matches.length > 1) {
// Apply the transparent-substring class to the matched substring
const substring = matches[1];
const newText = buttonText.replace(substring, `&nbsp;<span class="transparent-substring">${substring.slice(1, -1)}</span>`);
thisButton.innerHTML = newText;
}
2023-10-07 22:07:57 -04:00
}
} else {
2023-10-07 22:07:57 -04:00
buttonsInChat = document.querySelectorAll("#chat-tab.old-ui #chat-buttons button");
for (let i = 0; i < buttonsInChat.length; i++) {
buttonsInChat[i].textContent = buttonsInChat[i].textContent.replace(/ \(.*?\)/, "");
}
document.getElementById("gr-hover-container").style.display = "none";
2023-09-13 01:36:12 -04:00
}
function isMouseOverButtonOrMenu() {
2023-10-07 22:07:57 -04:00
return menu.matches(":hover") || button.matches(":hover");
}
2023-10-07 22:07:57 -04:00
button.addEventListener("mouseenter", function () {
if (!istouchscreen) {
showMenu();
}
});
2023-10-07 22:07:57 -04:00
button.addEventListener("click", function () {
if (menu.style.display === "flex") {
hideMenu();
}
else {
2024-01-09 19:27:50 -05:00
showMenu();
}
});
// Add event listener for mouseleave on the button
2023-10-07 22:07:57 -04:00
button.addEventListener("mouseleave", function () {
// Delay to prevent menu hiding when the mouse leaves the button into the menu
setTimeout(function () {
if (!isMouseOverButtonOrMenu()) {
hideMenu();
}
}, 100);
});
// Add event listener for mouseleave on the menu
2023-10-07 22:07:57 -04:00
menu.addEventListener("mouseleave", function () {
// Delay to prevent menu hide when the mouse leaves the menu into the button
setTimeout(function () {
if (!isMouseOverButtonOrMenu()) {
hideMenu();
}
}, 100);
});
// Add event listener for click anywhere in the document
2023-10-07 22:07:57 -04:00
document.addEventListener("click", function (event) {
// Check if the click is outside the button/menu and the menu is visible
if (!isMouseOverButtonOrMenu() && menu.style.display === "flex") {
hideMenu();
}
if (event.target.classList.contains("pfp_character")) {
toggleBigPicture();
}
});
2023-09-13 13:02:25 -04:00
//------------------------------------------------
// Relocate the "Show controls" checkbox
//------------------------------------------------
2023-10-07 22:07:57 -04:00
var elementToMove = document.getElementById("show-controls");
2023-09-13 13:02:25 -04:00
var parent = elementToMove.parentNode;
for (var i = 0; i < 2; i++) {
parent = parent.parentNode;
}
parent.insertBefore(elementToMove, parent.firstChild);
//------------------------------------------------
// Make the chat input grow upwards instead of downwards
//------------------------------------------------
2023-10-07 22:07:57 -04:00
document.getElementById("show-controls").parentNode.style.position = "absolute";
document.getElementById("show-controls").parentNode.style.bottom = "0px";
2023-09-13 01:36:12 -04:00
//------------------------------------------------
// Focus on the chat input
//------------------------------------------------
const chatTextArea = document.getElementById("chat-input").querySelector("textarea");
function respondToChatInputVisibility(element, callback) {
var options = {
root: document.documentElement,
};
var observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
callback(entry.intersectionRatio > 0);
});
}, options);
observer.observe(element);
}
function handleChatInputVisibilityChange(isVisible) {
if (isVisible) {
chatTextArea.focus();
}
}
respondToChatInputVisibility(chatTextArea, handleChatInputVisibilityChange);
//------------------------------------------------
// Show enlarged character picture when the profile
// picture is clicked on
//------------------------------------------------
let bigPictureVisible = false;
function addBigPicture() {
var imgElement = document.createElement("img");
var timestamp = new Date().getTime();
imgElement.src = "/file/cache/pfp_character.png?time=" + timestamp;
imgElement.classList.add("bigProfilePicture");
2024-02-25 12:10:16 -05:00
imgElement.addEventListener("load", function () {
this.style.visibility = "visible";
});
imgElement.addEventListener("error", function () {
this.style.visibility = "hidden";
});
var imgElementParent = document.getElementById("chat").parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode;
imgElementParent.appendChild(imgElement);
}
function deleteBigPicture() {
2023-12-27 12:59:23 -05:00
var bigProfilePictures = document.querySelectorAll(".bigProfilePicture");
bigProfilePictures.forEach(function (element) {
element.parentNode.removeChild(element);
});
}
function toggleBigPicture() {
if(bigPictureVisible) {
deleteBigPicture();
bigPictureVisible = false;
} else {
addBigPicture();
bigPictureVisible = true;
}
}
2023-12-16 20:16:26 -05:00
//------------------------------------------------
// Handle the chat input box growth
2023-12-16 20:16:26 -05:00
//------------------------------------------------
let currentChatInputHeight = 0;
// Update chat layout based on chat and input dimensions
function updateCssProperties() {
2023-12-27 12:59:23 -05:00
const chatContainer = document.getElementById("chat").parentNode.parentNode.parentNode;
const chatInputHeight = document.querySelector("#chat-input textarea").clientHeight;
// Check if the chat container is visible
if (chatContainer.clientHeight > 0) {
// Calculate new chat height and adjust CSS properties
var numericHeight = chatContainer.parentNode.clientHeight - chatInputHeight + 40 - 100;
if (document.getElementById("chat-tab").style.paddingBottom != "") {
numericHeight += 20;
}
const newChatHeight = `${numericHeight}px`;
document.documentElement.style.setProperty("--chat-height", newChatHeight);
document.documentElement.style.setProperty("--input-delta", `${chatInputHeight - 40}px`);
// Get and set header height
const header = document.querySelector(".header_bar");
const headerHeight = `${header.clientHeight}px`;
document.documentElement.style.setProperty("--header-height", headerHeight);
// Adjust scrollTop based on input height change
if (chatInputHeight !== currentChatInputHeight) {
chatContainer.scrollTop += chatInputHeight > currentChatInputHeight ? chatInputHeight : -chatInputHeight + 40;
currentChatInputHeight = chatInputHeight;
}
}
2023-12-16 20:16:26 -05:00
}
// Observe textarea size changes and call update function
new ResizeObserver(updateCssProperties)
2023-12-27 12:59:23 -05:00
.observe(document.querySelector("#chat-input textarea"));
// Handle changes in window size
2023-12-27 12:59:23 -05:00
window.addEventListener("resize", updateCssProperties);
//------------------------------------------------
// Keep track of the display width to position the past
// chats dropdown on desktop
//------------------------------------------------
function updateDocumentWidth() {
var updatedWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
document.documentElement.style.setProperty("--document-width", updatedWidth + "px");
}
updateDocumentWidth();
window.addEventListener("resize", updateDocumentWidth);
//------------------------------------------------
// Focus on the rename text area when it becomes visible
//------------------------------------------------
2024-01-09 19:27:50 -05:00
const renameTextArea = document.getElementById("rename-row").querySelector("textarea");
function respondToRenameVisibility(element, callback) {
var options = {
root: document.documentElement,
};
var observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
callback(entry.intersectionRatio > 0);
});
}, options);
observer.observe(element);
}
function handleVisibilityChange(isVisible) {
if (isVisible) {
renameTextArea.focus();
}
}
respondToRenameVisibility(renameTextArea, handleVisibilityChange);