Files
stable-diffusion-webui-forge/javascript/ui.js
DenOfEquity 7876862c43 Vae/te preferences via cards (#1912)
Allows setting of preferred VAE and Text encoder(s) for checkpoints when selected via Checkpoint cards. No selection saved means no change to current toprow setting. 'Built in' option, if the only choice, means clear the toprow selection (therefore use vae/te built-in to checkpoint).
Also allows setting model type for checkpoints (SD1/SD2/SDXL/Flux/Unknown) (user set only, no attempt at autodetection), enabling filtering of the cards based on UI preset.
2024-09-25 20:45:11 +01:00

428 lines
12 KiB
JavaScript

// various functions for interaction with ui.py not large enough to warrant putting them in separate files
function set_theme(theme) {
var gradioURL = window.location.href;
if (!gradioURL.includes('?__theme=')) {
window.location.replace(gradioURL + '?__theme=' + theme);
}
}
function all_gallery_buttons() {
var allGalleryButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small');
var visibleGalleryButtons = [];
allGalleryButtons.forEach(function(elem) {
if (elem.parentElement.offsetParent) {
visibleGalleryButtons.push(elem);
}
});
return visibleGalleryButtons;
}
function selected_gallery_button() {
return all_gallery_buttons().find(elem => elem.classList.contains('selected')) ?? null;
}
function selected_gallery_index() {
return all_gallery_buttons().findIndex(elem => elem.classList.contains('selected'));
}
function gallery_container_buttons(gallery_container) {
return gradioApp().querySelectorAll(`#${gallery_container} .thumbnail-item.thumbnail-small`);
}
function selected_gallery_index_id(gallery_container) {
return Array.from(gallery_container_buttons(gallery_container)).findIndex(elem => elem.classList.contains('selected'));
}
function extract_image_from_gallery(gallery) {
if (gallery.length == 0) {
return [null];
}
var index = selected_gallery_index();
if (index < 0 || index >= gallery.length) {
// Use the first image in the gallery as the default
index = 0;
}
return [[gallery[index]]];
}
window.args_to_array = Array.from; // Compatibility with e.g. extensions that may expect this to be around
function switch_to_txt2img() {
gradioApp().querySelector('#tabs').querySelectorAll('button')[0].click();
return Array.from(arguments);
}
function switch_to_img2img_tab(no) {
gradioApp().querySelector('#tabs').querySelectorAll('button')[1].click();
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[no].click();
}
function switch_to_img2img() {
switch_to_img2img_tab(0);
return Array.from(arguments);
}
function switch_to_sketch() {
switch_to_img2img_tab(1);
return Array.from(arguments);
}
function switch_to_inpaint() {
switch_to_img2img_tab(2);
return Array.from(arguments);
}
function switch_to_inpaint_sketch() {
switch_to_img2img_tab(3);
return Array.from(arguments);
}
function switch_to_extras() {
gradioApp().querySelector('#tabs').querySelectorAll('button')[3].click();
return Array.from(arguments);
}
function get_tab_index(tabId) {
let buttons = gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button');
for (let i = 0; i < buttons.length; i++) {
if (buttons[i].classList.contains('selected')) {
return i;
}
}
return 0;
}
function create_tab_index_args(tabId, args) {
var res = Array.from(args);
res[0] = get_tab_index(tabId);
return res;
}
function get_img2img_tab_index() {
let res = Array.from(arguments);
res.splice(-2);
res[0] = get_tab_index('mode_img2img');
return res;
}
function create_submit_args(args) {
var res = Array.from(args);
return res;
}
function setSubmitButtonsVisibility(tabname, showInterrupt, showSkip, showInterrupting) {
gradioApp().getElementById(tabname + '_interrupt').style.display = showInterrupt ? "block" : "none";
gradioApp().getElementById(tabname + '_skip').style.display = showSkip ? "block" : "none";
gradioApp().getElementById(tabname + '_interrupting').style.display = showInterrupting ? "block" : "none";
}
function showSubmitButtons(tabname, show) {
setSubmitButtonsVisibility(tabname, !show, !show, false);
}
function showSubmitInterruptingPlaceholder(tabname) {
setSubmitButtonsVisibility(tabname, false, true, true);
}
function showRestoreProgressButton(tabname, show) {
var button = gradioApp().getElementById(tabname + "_restore_progress");
if (!button) return;
button.style.setProperty('display', show ? 'flex' : 'none', 'important');
}
function submit(args) {
showSubmitButtons('txt2img', false);
var id = randomId();
localSet("txt2img_task_id", id);
requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), function() {
showSubmitButtons('txt2img', true);
localRemove("txt2img_task_id");
showRestoreProgressButton('txt2img', false);
});
var res = create_submit_args(args);
res[0] = id;
return res;
}
function submit_txt2img_upscale(args) {
var res = submit(args);
res[2] = selected_gallery_index();
return res;
}
function submit_img2img(args) {
showSubmitButtons('img2img', false);
var id = randomId();
localSet("img2img_task_id", id);
requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), function() {
showSubmitButtons('img2img', true);
localRemove("img2img_task_id");
showRestoreProgressButton('img2img', false);
});
var res = create_submit_args(args);
res[0] = id;
return res;
}
function submit_extras(args) {
showSubmitButtons('extras', false);
var id = randomId();
requestProgress(id, gradioApp().getElementById('extras_gallery_container'), gradioApp().getElementById('extras_gallery'), function() {
showSubmitButtons('extras', true);
});
var res = create_submit_args(args);
res[0] = id;
return res;
}
function restoreProgressTxt2img() {
showRestoreProgressButton("txt2img", false);
var id = localGet("txt2img_task_id");
if (id) {
showSubmitInterruptingPlaceholder('txt2img');
requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), function() {
showSubmitButtons('txt2img', true);
}, null, 0);
}
return id;
}
function restoreProgressImg2img() {
showRestoreProgressButton("img2img", false);
var id = localGet("img2img_task_id");
if (id) {
showSubmitInterruptingPlaceholder('img2img');
requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), function() {
showSubmitButtons('img2img', true);
}, null, 0);
}
return id;
}
/**
* Configure the width and height elements on `tabname` to accept
* pasting of resolutions in the form of "width x height".
*/
function setupResolutionPasting(tabname) {
var width = gradioApp().querySelector(`#${tabname}_width input[type=number]`);
var height = gradioApp().querySelector(`#${tabname}_height input[type=number]`);
for (const el of [width, height]) {
el.addEventListener('paste', function(event) {
var pasteData = event.clipboardData.getData('text/plain');
var parsed = pasteData.match(/^\s*(\d+)\D+(\d+)\s*$/);
if (parsed) {
width.value = parsed[1];
height.value = parsed[2];
updateInput(width);
updateInput(height);
event.preventDefault();
}
});
}
}
onUiLoaded(function() {
showRestoreProgressButton('txt2img', localGet("txt2img_task_id"));
showRestoreProgressButton('img2img', localGet("img2img_task_id"));
setupResolutionPasting('txt2img');
setupResolutionPasting('img2img');
});
function modelmerger() {
var id = randomId();
requestProgress(id, gradioApp().getElementById('modelmerger_results_panel'), null, function() {});
var res = create_submit_args(arguments);
res[0] = id;
return res;
}
function ask_for_style_name(_, prompt_text, negative_prompt_text) {
var name_ = prompt('Style name:');
return [name_, prompt_text, negative_prompt_text];
}
function confirm_clear_prompt(prompt, negative_prompt) {
if (confirm("Delete prompt?")) {
prompt = "";
negative_prompt = "";
}
return [prompt, negative_prompt];
}
var opts = {};
onAfterUiUpdate(function() {
if (Object.keys(opts).length != 0) return;
var json_elem = gradioApp().getElementById('settings_json');
if (json_elem == null) return;
var textarea = json_elem.querySelector('textarea');
var jsdata = textarea.value;
opts = JSON.parse(jsdata);
executeCallbacks(optionsAvailableCallbacks); /*global optionsAvailableCallbacks*/
executeCallbacks(optionsChangedCallbacks); /*global optionsChangedCallbacks*/
Object.defineProperty(textarea, 'value', {
set: function(newValue) {
var valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
var oldValue = valueProp.get.call(textarea);
valueProp.set.call(textarea, newValue);
if (oldValue != newValue) {
opts = JSON.parse(textarea.value);
}
executeCallbacks(optionsChangedCallbacks);
},
get: function() {
var valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value');
return valueProp.get.call(textarea);
}
});
json_elem.parentElement.style.display = "none";
});
onOptionsChanged(function() {
var elem = gradioApp().getElementById('sd_checkpoint_hash');
var sd_checkpoint_hash = opts.sd_checkpoint_hash || "";
var shorthash = sd_checkpoint_hash.substring(0, 10);
if (elem && elem.textContent != shorthash) {
elem.textContent = shorthash;
elem.title = sd_checkpoint_hash;
elem.href = "https://google.com/search?q=" + sd_checkpoint_hash;
}
});
let txt2img_textarea, img2img_textarea = undefined;
function restart_reload() {
document.body.style.backgroundColor = "var(--background-fill-primary)";
document.body.innerHTML = '<h1 style="font-family:monospace;margin-top:20%;color:lightgray;text-align:center;">Reloading...</h1>';
var requestPing = function() {
requestGet("./internal/ping", {}, function(data) {
location.reload();
}, function() {
setTimeout(requestPing, 500);
});
};
setTimeout(requestPing, 2000);
return [];
}
// Simulate an `input` DOM event for Gradio Textbox component. Needed after you edit its contents in javascript, otherwise your edits
// will only visible on web page and not sent to python.
function updateInput(target) {
let e = new Event("input", {bubbles: true});
Object.defineProperty(e, "target", {value: target});
target.dispatchEvent(e);
}
var desiredCheckpointName = null;
function selectCheckpoint(name) {
desiredCheckpointName = name;
gradioApp().getElementById('change_checkpoint').click();
}
var desiredVAEName = 0;
function selectVAE(vae) {
desiredVAEName = vae;
}
function currentImg2imgSourceResolution(w, h, r) {
var img = gradioApp().querySelector('#mode_img2img > div[style="display: block;"] :is(img, canvas)');
return img ? [img.naturalWidth || img.width, img.naturalHeight || img.height, r] : [0, 0, r];
}
function updateImg2imgResizeToTextAfterChangingImage() {
// At the time this is called from gradio, the image has no yet been replaced.
// There may be a better solution, but this is simple and straightforward so I'm going with it.
setTimeout(function() {
gradioApp().getElementById('img2img_update_resize_to').click();
}, 500);
return [];
}
function setRandomSeed(elem_id) {
var input = gradioApp().querySelector("#" + elem_id + " input");
if (!input) return [];
input.value = "-1";
updateInput(input);
return [];
}
function switchWidthHeight(tabname) {
var width = gradioApp().querySelector("#" + tabname + "_width input[type=number]");
var height = gradioApp().querySelector("#" + tabname + "_height input[type=number]");
if (!width || !height) return [];
var tmp = width.value;
width.value = height.value;
height.value = tmp;
updateInput(width);
updateInput(height);
return [];
}
var onEditTimers = {};
// calls func after afterMs milliseconds has passed since the input elem has been edited by user
function onEdit(editId, elem, afterMs, func) {
var edited = function() {
var existingTimer = onEditTimers[editId];
if (existingTimer) clearTimeout(existingTimer);
onEditTimers[editId] = setTimeout(func, afterMs);
};
elem.addEventListener("input", edited);
return edited;
}