diff options
Diffstat (limited to 'script.js')
-rw-r--r-- | script.js | 147 |
1 files changed, 100 insertions, 47 deletions
@@ -1,66 +1,117 @@ function gradioApp() { - const elems = document.getElementsByTagName('gradio-app') - const elem = elems.length == 0 ? document : elems[0] + const elems = document.getElementsByTagName('gradio-app'); + const elem = elems.length == 0 ? document : elems[0]; - if (elem !== document) elem.getElementById = function(id){ return document.getElementById(id) } - return elem.shadowRoot ? elem.shadowRoot : elem + if (elem !== document) { + elem.getElementById = function(id) { + return document.getElementById(id); + }; + } + return elem.shadowRoot ? elem.shadowRoot : elem; } function get_uiCurrentTab() { - return gradioApp().querySelector('#tabs button.selected') + return gradioApp().querySelector('#tabs button.selected'); } function get_uiCurrentTabContent() { - return gradioApp().querySelector('.tabitem[id^=tab_]:not([style*="display: none"])') + return gradioApp().querySelector('.tabitem[id^=tab_]:not([style*="display: none"])'); } -uiUpdateCallbacks = [] -uiLoadedCallbacks = [] -uiTabChangeCallbacks = [] -optionsChangedCallbacks = [] -let uiCurrentTab = null +var uiUpdateCallbacks = []; +var uiAfterUpdateCallbacks = []; +var uiLoadedCallbacks = []; +var uiTabChangeCallbacks = []; +var optionsChangedCallbacks = []; +var uiAfterUpdateTimeout = null; +var uiCurrentTab = null; -function onUiUpdate(callback){ - uiUpdateCallbacks.push(callback) +/** + * Register callback to be called at each UI update. + * The callback receives an array of MutationRecords as an argument. + */ +function onUiUpdate(callback) { + uiUpdateCallbacks.push(callback); } -function onUiLoaded(callback){ - uiLoadedCallbacks.push(callback) + +/** + * Register callback to be called soon after UI updates. + * The callback receives no arguments. + * + * This is preferred over `onUiUpdate` if you don't need + * access to the MutationRecords, as your function will + * not be called quite as often. + */ +function onAfterUiUpdate(callback) { + uiAfterUpdateCallbacks.push(callback); } -function onUiTabChange(callback){ - uiTabChangeCallbacks.push(callback) + +/** + * Register callback to be called when the UI is loaded. + * The callback receives no arguments. + */ +function onUiLoaded(callback) { + uiLoadedCallbacks.push(callback); } -function onOptionsChanged(callback){ - optionsChangedCallbacks.push(callback) + +/** + * Register callback to be called when the UI tab is changed. + * The callback receives no arguments. + */ +function onUiTabChange(callback) { + uiTabChangeCallbacks.push(callback); } -function runCallback(x, m){ - try { - x(m) - } catch (e) { - (console.error || console.log).call(console, e.message, e); +/** + * Register callback to be called when the options are changed. + * The callback receives no arguments. + * @param callback + */ +function onOptionsChanged(callback) { + optionsChangedCallbacks.push(callback); +} + +function executeCallbacks(queue, arg) { + for (const callback of queue) { + try { + callback(arg); + } catch (e) { + console.error("error running callback", callback, ":", e); + } } } -function executeCallbacks(queue, m) { - queue.forEach(function(x){runCallback(x, m)}) + +/** + * Schedule the execution of the callbacks registered with onAfterUiUpdate. + * The callbacks are executed after a short while, unless another call to this function + * is made before that time. IOW, the callbacks are executed only once, even + * when there are multiple mutations observed. + */ +function scheduleAfterUiUpdateCallbacks() { + clearTimeout(uiAfterUpdateTimeout); + uiAfterUpdateTimeout = setTimeout(function() { + executeCallbacks(uiAfterUpdateCallbacks); + }, 200); } var executedOnLoaded = false; document.addEventListener("DOMContentLoaded", function() { - var mutationObserver = new MutationObserver(function(m){ - if(!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')){ + var mutationObserver = new MutationObserver(function(m) { + if (!executedOnLoaded && gradioApp().querySelector('#txt2img_prompt')) { executedOnLoaded = true; executeCallbacks(uiLoadedCallbacks); } executeCallbacks(uiUpdateCallbacks, m); + scheduleAfterUiUpdateCallbacks(); const newTab = get_uiCurrentTab(); - if ( newTab && ( newTab !== uiCurrentTab ) ) { + if (newTab && (newTab !== uiCurrentTab)) { uiCurrentTab = newTab; executeCallbacks(uiTabChangeCallbacks); } }); - mutationObserver.observe( gradioApp(), { childList:true, subtree:true }) + mutationObserver.observe(gradioApp(), {childList: true, subtree: true}); }); /** @@ -69,36 +120,38 @@ document.addEventListener("DOMContentLoaded", function() { document.addEventListener('keydown', function(e) { var handled = false; if (e.key !== undefined) { - if((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; + if ((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; } else if (e.keyCode !== undefined) { - if((e.keyCode == 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; + if ((e.keyCode == 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true; } if (handled) { - button = get_uiCurrentTabContent().querySelector('button[id$=_generate]'); + var button = get_uiCurrentTabContent().querySelector('button[id$=_generate]'); if (button) { button.click(); } e.preventDefault(); } -}) +}); /** * checks that a UI element is not in another hidden element or tab content */ function uiElementIsVisible(el) { - let isVisible = !el.closest('.\\!hidden'); - if ( ! isVisible ) { - return false; + if (el === document) { + return true; } - while( isVisible = el.closest('.tabitem')?.style.display !== 'none' ) { - if ( ! isVisible ) { - return false; - } else if ( el.parentElement ) { - el = el.parentElement - } else { - break; - } - } - return isVisible; + const computedStyle = getComputedStyle(el); + const isVisible = computedStyle.display !== 'none'; + + if (!isVisible) return false; + return uiElementIsVisible(el.parentNode); +} + +function uiElementInSight(el) { + const clRect = el.getBoundingClientRect(); + const windowHeight = window.innerHeight; + const isOnScreen = clRect.bottom > 0 && clRect.top < windowHeight; + + return isOnScreen; } |