mirror of
https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
synced 2025-08-09 13:49:48 +00:00
Merge branch 'dev' into startup-profile
This commit is contained in:
@@ -81,7 +81,7 @@ function dimensionChange(e, is_width, is_height) {
|
||||
}
|
||||
|
||||
|
||||
onUiUpdate(function() {
|
||||
onAfterUiUpdate(function() {
|
||||
var arPreviewRect = gradioApp().querySelector('#imageARPreview');
|
||||
if (arPreviewRect) {
|
||||
arPreviewRect.style.display = 'none';
|
||||
|
@@ -167,6 +167,4 @@ var addContextMenuEventListener = initResponse[2];
|
||||
})();
|
||||
//End example Context Menu Items
|
||||
|
||||
onUiUpdate(function() {
|
||||
addContextMenuEventListener();
|
||||
});
|
||||
onAfterUiUpdate(addContextMenuEventListener);
|
||||
|
55
javascript/dragdrop.js
vendored
55
javascript/dragdrop.js
vendored
@@ -48,12 +48,27 @@ function dropReplaceImage(imgWrap, files) {
|
||||
}
|
||||
}
|
||||
|
||||
function eventHasFiles(e) {
|
||||
if (!e.dataTransfer || !e.dataTransfer.files) return false;
|
||||
if (e.dataTransfer.files.length > 0) return true;
|
||||
if (e.dataTransfer.items.length > 0 && e.dataTransfer.items[0].kind == "file") return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function dragDropTargetIsPrompt(target) {
|
||||
if (target?.placeholder && target?.placeholder.indexOf("Prompt") >= 0) return true;
|
||||
if (target?.parentNode?.parentNode?.className?.indexOf("prompt") > 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
window.document.addEventListener('dragover', e => {
|
||||
const target = e.composedPath()[0];
|
||||
const imgWrap = target.closest('[data-testid="image"]');
|
||||
if (!imgWrap && target.placeholder && target.placeholder.indexOf("Prompt") == -1) {
|
||||
return;
|
||||
}
|
||||
if (!eventHasFiles(e)) return;
|
||||
|
||||
var targetImage = target.closest('[data-testid="image"]');
|
||||
if (!dragDropTargetIsPrompt(target) && !targetImage) return;
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
@@ -61,17 +76,31 @@ window.document.addEventListener('dragover', e => {
|
||||
|
||||
window.document.addEventListener('drop', e => {
|
||||
const target = e.composedPath()[0];
|
||||
if (target.placeholder.indexOf("Prompt") == -1) {
|
||||
if (!eventHasFiles(e)) return;
|
||||
|
||||
if (dragDropTargetIsPrompt(target)) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
let prompt_target = get_tab_index('tabs') == 1 ? "img2img_prompt_image" : "txt2img_prompt_image";
|
||||
|
||||
const imgParent = gradioApp().getElementById(prompt_target);
|
||||
const files = e.dataTransfer.files;
|
||||
const fileInput = imgParent.querySelector('input[type="file"]');
|
||||
if (fileInput) {
|
||||
fileInput.files = files;
|
||||
fileInput.dispatchEvent(new Event('change'));
|
||||
}
|
||||
}
|
||||
|
||||
var targetImage = target.closest('[data-testid="image"]');
|
||||
if (targetImage) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const files = e.dataTransfer.files;
|
||||
dropReplaceImage(targetImage, files);
|
||||
return;
|
||||
}
|
||||
const imgWrap = target.closest('[data-testid="image"]');
|
||||
if (!imgWrap) {
|
||||
return;
|
||||
}
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const files = e.dataTransfer.files;
|
||||
dropReplaceImage(imgWrap, files);
|
||||
});
|
||||
|
||||
window.addEventListener('paste', e => {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
function keyupEditAttention(event) {
|
||||
let target = event.originalTarget || event.composedPath()[0];
|
||||
if (!target.matches("[id*='_toprow'] [id*='_prompt'] textarea")) return;
|
||||
if (!target.matches("*:is([id*='_toprow'] [id*='_prompt'], .prompt) textarea")) return;
|
||||
if (!(event.metaKey || event.ctrlKey)) return;
|
||||
|
||||
let isPlus = event.key == "ArrowUp";
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// attaches listeners to the txt2img and img2img galleries to update displayed generation param text when the image changes
|
||||
|
||||
let txt2img_gallery, img2img_gallery, modal = undefined;
|
||||
onUiUpdate(function() {
|
||||
onAfterUiUpdate(function() {
|
||||
if (!txt2img_gallery) {
|
||||
txt2img_gallery = attachGalleryListeners("txt2img");
|
||||
}
|
||||
|
@@ -116,17 +116,25 @@ var titles = {
|
||||
"Negative Guidance minimum sigma": "Skip negative prompt for steps where image is already mostly denoised; the higher this value, the more skips there will be; provides increased performance in exchange for minor quality reduction."
|
||||
};
|
||||
|
||||
function updateTooltipForSpan(span) {
|
||||
if (span.title) return; // already has a title
|
||||
function updateTooltip(element) {
|
||||
if (element.title) return; // already has a title
|
||||
|
||||
let tooltip = localization[titles[span.textContent]] || titles[span.textContent];
|
||||
let text = element.textContent;
|
||||
let tooltip = localization[titles[text]] || titles[text];
|
||||
|
||||
if (!tooltip) {
|
||||
tooltip = localization[titles[span.value]] || titles[span.value];
|
||||
let value = element.value;
|
||||
if (value) tooltip = localization[titles[value]] || titles[value];
|
||||
}
|
||||
|
||||
if (!tooltip) {
|
||||
for (const c of span.classList) {
|
||||
// Gradio dropdown options have `data-value`.
|
||||
let dataValue = element.dataset.value;
|
||||
if (dataValue) tooltip = localization[titles[dataValue]] || titles[dataValue];
|
||||
}
|
||||
|
||||
if (!tooltip) {
|
||||
for (const c of element.classList) {
|
||||
if (c in titles) {
|
||||
tooltip = localization[titles[c]] || titles[c];
|
||||
break;
|
||||
@@ -135,34 +143,53 @@ function updateTooltipForSpan(span) {
|
||||
}
|
||||
|
||||
if (tooltip) {
|
||||
span.title = tooltip;
|
||||
element.title = tooltip;
|
||||
}
|
||||
}
|
||||
|
||||
function updateTooltipForSelect(select) {
|
||||
if (select.onchange != null) return;
|
||||
// Nodes to check for adding tooltips.
|
||||
const tooltipCheckNodes = new Set();
|
||||
// Timer for debouncing tooltip check.
|
||||
let tooltipCheckTimer = null;
|
||||
|
||||
select.onchange = function() {
|
||||
select.title = localization[titles[select.value]] || titles[select.value] || "";
|
||||
};
|
||||
function processTooltipCheckNodes() {
|
||||
for (const node of tooltipCheckNodes) {
|
||||
updateTooltip(node);
|
||||
}
|
||||
tooltipCheckNodes.clear();
|
||||
}
|
||||
|
||||
var observedTooltipElements = {SPAN: 1, BUTTON: 1, SELECT: 1, P: 1};
|
||||
|
||||
onUiUpdate(function(m) {
|
||||
m.forEach(function(record) {
|
||||
record.addedNodes.forEach(function(node) {
|
||||
if (observedTooltipElements[node.tagName]) {
|
||||
updateTooltipForSpan(node);
|
||||
onUiUpdate(function(mutationRecords) {
|
||||
for (const record of mutationRecords) {
|
||||
if (record.type === "childList" && record.target.classList.contains("options")) {
|
||||
// This smells like a Gradio dropdown menu having changed,
|
||||
// so let's enqueue an update for the input element that shows the current value.
|
||||
let wrap = record.target.parentNode;
|
||||
let input = wrap?.querySelector("input");
|
||||
if (input) {
|
||||
input.title = ""; // So we'll even have a chance to update it.
|
||||
tooltipCheckNodes.add(input);
|
||||
}
|
||||
if (node.tagName == "SELECT") {
|
||||
updateTooltipForSelect(node);
|
||||
}
|
||||
for (const node of record.addedNodes) {
|
||||
if (node.nodeType === Node.ELEMENT_NODE && !node.classList.contains("hide")) {
|
||||
if (!node.title) {
|
||||
if (
|
||||
node.tagName === "SPAN" ||
|
||||
node.tagName === "BUTTON" ||
|
||||
node.tagName === "P" ||
|
||||
node.tagName === "INPUT" ||
|
||||
(node.tagName === "LI" && node.classList.contains("item")) // Gradio dropdown item
|
||||
) {
|
||||
tooltipCheckNodes.add(node);
|
||||
}
|
||||
}
|
||||
node.querySelectorAll('span, button, p').forEach(n => tooltipCheckNodes.add(n));
|
||||
}
|
||||
|
||||
if (node.querySelectorAll) {
|
||||
node.querySelectorAll('span, button, select, p').forEach(updateTooltipForSpan);
|
||||
node.querySelectorAll('select').forEach(updateTooltipForSelect);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
if (tooltipCheckNodes.size) {
|
||||
clearTimeout(tooltipCheckTimer);
|
||||
tooltipCheckTimer = setTimeout(processTooltipCheckNodes, 1000);
|
||||
}
|
||||
});
|
||||
|
@@ -39,5 +39,5 @@ function imageMaskResize() {
|
||||
});
|
||||
}
|
||||
|
||||
onUiUpdate(imageMaskResize);
|
||||
onAfterUiUpdate(imageMaskResize);
|
||||
window.addEventListener('resize', imageMaskResize);
|
||||
|
@@ -1,18 +0,0 @@
|
||||
window.onload = (function() {
|
||||
window.addEventListener('drop', e => {
|
||||
const target = e.composedPath()[0];
|
||||
if (target.placeholder.indexOf("Prompt") == -1) return;
|
||||
|
||||
let prompt_target = get_tab_index('tabs') == 1 ? "img2img_prompt_image" : "txt2img_prompt_image";
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
const imgParent = gradioApp().getElementById(prompt_target);
|
||||
const files = e.dataTransfer.files;
|
||||
const fileInput = imgParent.querySelector('input[type="file"]');
|
||||
if (fileInput) {
|
||||
fileInput.files = files;
|
||||
fileInput.dispatchEvent(new Event('change'));
|
||||
}
|
||||
});
|
||||
});
|
@@ -170,7 +170,7 @@ function modalTileImageToggle(event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
onUiUpdate(function() {
|
||||
onAfterUiUpdate(function() {
|
||||
var fullImg_preview = gradioApp().querySelectorAll('.gradio-gallery > div > img');
|
||||
if (fullImg_preview != null) {
|
||||
fullImg_preview.forEach(setupImageForLightbox);
|
||||
|
@@ -1,7 +1,9 @@
|
||||
let gamepads = [];
|
||||
|
||||
window.addEventListener('gamepadconnected', (e) => {
|
||||
const index = e.gamepad.index;
|
||||
let isWaiting = false;
|
||||
setInterval(async() => {
|
||||
gamepads[index] = setInterval(async() => {
|
||||
if (!opts.js_modal_lightbox_gamepad || isWaiting) return;
|
||||
const gamepad = navigator.getGamepads()[index];
|
||||
const xValue = gamepad.axes[0];
|
||||
@@ -24,6 +26,10 @@ window.addEventListener('gamepadconnected', (e) => {
|
||||
}, 10);
|
||||
});
|
||||
|
||||
window.addEventListener('gamepaddisconnected', (e) => {
|
||||
clearInterval(gamepads[e.gamepad.index]);
|
||||
});
|
||||
|
||||
/*
|
||||
Primarily for vr controller type pointer devices.
|
||||
I use the wheel event because there's currently no way to do it properly with web xr.
|
||||
|
@@ -4,7 +4,7 @@ let lastHeadImg = null;
|
||||
|
||||
let notificationButton = null;
|
||||
|
||||
onUiUpdate(function() {
|
||||
onAfterUiUpdate(function() {
|
||||
if (notificationButton == null) {
|
||||
notificationButton = gradioApp().getElementById('request_notifications');
|
||||
|
||||
|
83
javascript/token-counters.js
Normal file
83
javascript/token-counters.js
Normal file
@@ -0,0 +1,83 @@
|
||||
let promptTokenCountDebounceTime = 800;
|
||||
let promptTokenCountTimeouts = {};
|
||||
var promptTokenCountUpdateFunctions = {};
|
||||
|
||||
function update_txt2img_tokens(...args) {
|
||||
// Called from Gradio
|
||||
update_token_counter("txt2img_token_button");
|
||||
if (args.length == 2) {
|
||||
return args[0];
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function update_img2img_tokens(...args) {
|
||||
// Called from Gradio
|
||||
update_token_counter("img2img_token_button");
|
||||
if (args.length == 2) {
|
||||
return args[0];
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function update_token_counter(button_id) {
|
||||
if (opts.disable_token_counters) {
|
||||
return;
|
||||
}
|
||||
if (promptTokenCountTimeouts[button_id]) {
|
||||
clearTimeout(promptTokenCountTimeouts[button_id]);
|
||||
}
|
||||
promptTokenCountTimeouts[button_id] = setTimeout(
|
||||
() => gradioApp().getElementById(button_id)?.click(),
|
||||
promptTokenCountDebounceTime,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function recalculatePromptTokens(name) {
|
||||
promptTokenCountUpdateFunctions[name]?.();
|
||||
}
|
||||
|
||||
function recalculate_prompts_txt2img() {
|
||||
// Called from Gradio
|
||||
recalculatePromptTokens('txt2img_prompt');
|
||||
recalculatePromptTokens('txt2img_neg_prompt');
|
||||
return Array.from(arguments);
|
||||
}
|
||||
|
||||
function recalculate_prompts_img2img() {
|
||||
// Called from Gradio
|
||||
recalculatePromptTokens('img2img_prompt');
|
||||
recalculatePromptTokens('img2img_neg_prompt');
|
||||
return Array.from(arguments);
|
||||
}
|
||||
|
||||
function setupTokenCounting(id, id_counter, id_button) {
|
||||
var prompt = gradioApp().getElementById(id);
|
||||
var counter = gradioApp().getElementById(id_counter);
|
||||
var textarea = gradioApp().querySelector(`#${id} > label > textarea`);
|
||||
|
||||
if (opts.disable_token_counters) {
|
||||
counter.style.display = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
if (counter.parentElement == prompt.parentElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
prompt.parentElement.insertBefore(counter, prompt);
|
||||
prompt.parentElement.style.position = "relative";
|
||||
|
||||
promptTokenCountUpdateFunctions[id] = function() {
|
||||
update_token_counter(id_button);
|
||||
};
|
||||
textarea.addEventListener("input", promptTokenCountUpdateFunctions[id]);
|
||||
}
|
||||
|
||||
function setupTokenCounters() {
|
||||
setupTokenCounting('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button');
|
||||
setupTokenCounting('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button');
|
||||
setupTokenCounting('img2img_prompt', 'img2img_token_counter', 'img2img_token_button');
|
||||
setupTokenCounting('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button');
|
||||
}
|
@@ -248,29 +248,8 @@ function confirm_clear_prompt(prompt, negative_prompt) {
|
||||
}
|
||||
|
||||
|
||||
var promptTokecountUpdateFuncs = {};
|
||||
|
||||
function recalculatePromptTokens(name) {
|
||||
if (promptTokecountUpdateFuncs[name]) {
|
||||
promptTokecountUpdateFuncs[name]();
|
||||
}
|
||||
}
|
||||
|
||||
function recalculate_prompts_txt2img() {
|
||||
recalculatePromptTokens('txt2img_prompt');
|
||||
recalculatePromptTokens('txt2img_neg_prompt');
|
||||
return Array.from(arguments);
|
||||
}
|
||||
|
||||
function recalculate_prompts_img2img() {
|
||||
recalculatePromptTokens('img2img_prompt');
|
||||
recalculatePromptTokens('img2img_neg_prompt');
|
||||
return Array.from(arguments);
|
||||
}
|
||||
|
||||
|
||||
var opts = {};
|
||||
onUiUpdate(function() {
|
||||
onAfterUiUpdate(function() {
|
||||
if (Object.keys(opts).length != 0) return;
|
||||
|
||||
var json_elem = gradioApp().getElementById('settings_json');
|
||||
@@ -302,28 +281,7 @@ onUiUpdate(function() {
|
||||
|
||||
json_elem.parentElement.style.display = "none";
|
||||
|
||||
function registerTextarea(id, id_counter, id_button) {
|
||||
var prompt = gradioApp().getElementById(id);
|
||||
var counter = gradioApp().getElementById(id_counter);
|
||||
var textarea = gradioApp().querySelector("#" + id + " > label > textarea");
|
||||
|
||||
if (counter.parentElement == prompt.parentElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
prompt.parentElement.insertBefore(counter, prompt);
|
||||
prompt.parentElement.style.position = "relative";
|
||||
|
||||
promptTokecountUpdateFuncs[id] = function() {
|
||||
update_token_counter(id_button);
|
||||
};
|
||||
textarea.addEventListener("input", promptTokecountUpdateFuncs[id]);
|
||||
}
|
||||
|
||||
registerTextarea('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button');
|
||||
registerTextarea('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button');
|
||||
registerTextarea('img2img_prompt', 'img2img_token_counter', 'img2img_token_button');
|
||||
registerTextarea('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button');
|
||||
setupTokenCounters();
|
||||
|
||||
var show_all_pages = gradioApp().getElementById('settings_show_all_pages');
|
||||
var settings_tabs = gradioApp().querySelector('#settings div');
|
||||
@@ -354,33 +312,6 @@ onOptionsChanged(function() {
|
||||
});
|
||||
|
||||
let txt2img_textarea, img2img_textarea = undefined;
|
||||
let wait_time = 800;
|
||||
let token_timeouts = {};
|
||||
|
||||
function update_txt2img_tokens(...args) {
|
||||
update_token_counter("txt2img_token_button");
|
||||
if (args.length == 2) {
|
||||
return args[0];
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function update_img2img_tokens(...args) {
|
||||
update_token_counter(
|
||||
"img2img_token_button"
|
||||
);
|
||||
if (args.length == 2) {
|
||||
return args[0];
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function update_token_counter(button_id) {
|
||||
if (token_timeouts[button_id]) {
|
||||
clearTimeout(token_timeouts[button_id]);
|
||||
}
|
||||
token_timeouts[button_id] = setTimeout(() => gradioApp().getElementById(button_id)?.click(), wait_time);
|
||||
}
|
||||
|
||||
function restart_reload() {
|
||||
document.body.innerHTML = '<h1 style="font-family:monospace;margin-top:20%;color:lightgray;text-align:center;">Reloading...</h1>';
|
||||
|
Reference in New Issue
Block a user