CoolFace
Apppublic

fluxdev/stable-diffusion-webui-forge

sourceHugging Faceupdated 2y agoView on Hugging Face
1likes
script.js200 linesDownload Raw Back to root
1function gradioApp() {2    const elems = document.getElementsByTagName('gradio-app');3    const elem = elems.length == 0 ? document : elems[0];4 5    if (elem !== document) {6        elem.getElementById = function(id) {7            return document.getElementById(id);8        };9    }10    return elem.shadowRoot ? elem.shadowRoot : elem;11}12 13/**14 * Get the currently selected top-level UI tab button (e.g. the button that says "Extras").15 */16function get_uiCurrentTab() {17    return gradioApp().querySelector('#tabs > .tab-nav > button.selected');18}19 20/**21 * Get the first currently visible top-level UI tab content (e.g. the div hosting the "txt2img" UI).22 */23function get_uiCurrentTabContent() {24    return gradioApp().querySelector('#tabs > .tabitem[id^=tab_]:not([style*="display: none"])');25}26 27var uiUpdateCallbacks = [];28var uiAfterUpdateCallbacks = [];29var uiLoadedCallbacks = [];30var uiTabChangeCallbacks = [];31var optionsChangedCallbacks = [];32var uiAfterUpdateTimeout = null;33var uiCurrentTab = null;34 35/**36 * Register callback to be called at each UI update.37 * The callback receives an array of MutationRecords as an argument.38 */39function onUiUpdate(callback) {40    uiUpdateCallbacks.push(callback);41}42 43/**44 * Register callback to be called soon after UI updates.45 * The callback receives no arguments.46 *47 * This is preferred over `onUiUpdate` if you don't need48 * access to the MutationRecords, as your function will49 * not be called quite as often.50 */51function onAfterUiUpdate(callback) {52    uiAfterUpdateCallbacks.push(callback);53}54 55/**56 * Register callback to be called when the UI is loaded.57 * The callback receives no arguments.58 */59function onUiLoaded(callback) {60    uiLoadedCallbacks.push(callback);61}62 63/**64 * Register callback to be called when the UI tab is changed.65 * The callback receives no arguments.66 */67function onUiTabChange(callback) {68    uiTabChangeCallbacks.push(callback);69}70 71/**72 * Register callback to be called when the options are changed.73 * The callback receives no arguments.74 * @param callback75 */76function onOptionsChanged(callback) {77    optionsChangedCallbacks.push(callback);78}79 80function executeCallbacks(queue, arg) {81    for (const callback of queue) {82        try {83            callback(arg);84        } catch (e) {85            console.error("error running callback", callback, ":", e);86        }87    }88}89 90/**91 * Schedule the execution of the callbacks registered with onAfterUiUpdate.92 * The callbacks are executed after a short while, unless another call to this function93 * is made before that time. IOW, the callbacks are executed only once, even94 * when there are multiple mutations observed.95 */96function scheduleAfterUiUpdateCallbacks() {97    clearTimeout(uiAfterUpdateTimeout);98    uiAfterUpdateTimeout = setTimeout(function() {99        executeCallbacks(uiAfterUpdateCallbacks);100    }, 200);101}102 103var executedOnLoaded = false;104 105document.addEventListener("DOMContentLoaded", function() {106    var mutationObserver = new MutationObserver(function(m) {107        if (!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')) {108            executedOnLoaded = true;109            executeCallbacks(uiLoadedCallbacks);110        }111 112        executeCallbacks(uiUpdateCallbacks, m);113        scheduleAfterUiUpdateCallbacks();114        const newTab = get_uiCurrentTab();115        if (newTab && (newTab !== uiCurrentTab)) {116            uiCurrentTab = newTab;117            executeCallbacks(uiTabChangeCallbacks);118        }119    });120    mutationObserver.observe(gradioApp(), {childList: true, subtree: true});121});122 123/**124 * Add keyboard shortcuts:125 * Ctrl+Enter to start/restart a generation126 * Alt/Option+Enter to skip a generation127 * Esc to interrupt a generation128 */129document.addEventListener('keydown', function(e) {130    const isEnter = e.key === 'Enter' || e.keyCode === 13;131    const isCtrlKey = e.metaKey || e.ctrlKey;132    const isAltKey = e.altKey;133    const isEsc = e.key === 'Escape';134 135    const generateButton = get_uiCurrentTabContent().querySelector('button[id$=_generate]');136    const interruptButton = get_uiCurrentTabContent().querySelector('button[id$=_interrupt]');137    const skipButton = get_uiCurrentTabContent().querySelector('button[id$=_skip]');138 139    if (isCtrlKey && isEnter) {140        if (interruptButton.style.display === 'block') {141            interruptButton.click();142            const callback = (mutationList) => {143                for (const mutation of mutationList) {144                    if (mutation.type === 'attributes' && mutation.attributeName === 'style') {145                        if (interruptButton.style.display === 'none') {146                            generateButton.click();147                            observer.disconnect();148                        }149                    }150                }151            };152            const observer = new MutationObserver(callback);153            observer.observe(interruptButton, {attributes: true});154        } else {155            generateButton.click();156        }157        e.preventDefault();158    }159 160    if (isAltKey && isEnter) {161        skipButton.click();162        e.preventDefault();163    }164 165    if (isEsc) {166        const globalPopup = document.querySelector('.global-popup');167        const lightboxModal = document.querySelector('#lightboxModal');168        if (!globalPopup || globalPopup.style.display === 'none') {169            if (document.activeElement === lightboxModal) return;170            if (interruptButton.style.display === 'block') {171                interruptButton.click();172                e.preventDefault();173            }174        }175    }176});177 178/**179 * checks that a UI element is not in another hidden element or tab content180 */181function uiElementIsVisible(el) {182    if (el === document) {183        return true;184    }185 186    const computedStyle = getComputedStyle(el);187    const isVisible = computedStyle.display !== 'none';188 189    if (!isVisible) return false;190    return uiElementIsVisible(el.parentNode);191}192 193function uiElementInSight(el) {194    const clRect = el.getBoundingClientRect();195    const windowHeight = window.innerHeight;196    const isOnScreen = clRect.bottom > 0 && clRect.top < windowHeight;197 198    return isOnScreen;199}200