| 
									
										
										
										
											2023-10-15 11:01:45 +03:00
										 |  |  | function gradioApp() { | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Get the currently selected top-level UI tab button (e.g. the button that says "Extras"). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function get_uiCurrentTab() { | 
					
						
							|  |  |  |     return gradioApp().querySelector('#tabs > .tab-nav > button.selected'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Get the first currently visible top-level UI tab content (e.g. the div hosting the "txt2img" UI). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function get_uiCurrentTabContent() { | 
					
						
							|  |  |  |     return gradioApp().querySelector('#tabs > .tabitem[id^=tab_]:not([style*="display: none"])'); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var uiUpdateCallbacks = []; | 
					
						
							|  |  |  | var uiAfterUpdateCallbacks = []; | 
					
						
							|  |  |  | var uiLoadedCallbacks = []; | 
					
						
							|  |  |  | var uiTabChangeCallbacks = []; | 
					
						
							|  |  |  | var optionsChangedCallbacks = []; | 
					
						
							|  |  |  | var uiAfterUpdateTimeout = null; | 
					
						
							|  |  |  | var uiCurrentTab = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * 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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * 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); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Register callback to be called when the UI is loaded. | 
					
						
							|  |  |  |  * The callback receives no arguments. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function onUiLoaded(callback) { | 
					
						
							|  |  |  |     uiLoadedCallbacks.push(callback); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Register callback to be called when the UI tab is changed. | 
					
						
							|  |  |  |  * The callback receives no arguments. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function onUiTabChange(callback) { | 
					
						
							|  |  |  |     uiTabChangeCallbacks.push(callback); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * 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); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * 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')) { | 
					
						
							|  |  |  |             executedOnLoaded = true; | 
					
						
							|  |  |  |             executeCallbacks(uiLoadedCallbacks); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         executeCallbacks(uiUpdateCallbacks, m); | 
					
						
							|  |  |  |         scheduleAfterUiUpdateCallbacks(); | 
					
						
							|  |  |  |         const newTab = get_uiCurrentTab(); | 
					
						
							|  |  |  |         if (newTab && (newTab !== uiCurrentTab)) { | 
					
						
							|  |  |  |             uiCurrentTab = newTab; | 
					
						
							|  |  |  |             executeCallbacks(uiTabChangeCallbacks); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     mutationObserver.observe(gradioApp(), {childList: true, subtree: true}); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2023-12-09 21:04:45 +06:00
										 |  |  |  * Add keyboard shortcuts: | 
					
						
							|  |  |  |  * Ctrl+Enter to start/restart a generation | 
					
						
							|  |  |  |  * Alt/Option+Enter to skip a generation | 
					
						
							| 
									
										
										
										
											2023-12-10 16:28:56 +06:00
										 |  |  |  * Esc to interrupt a generation | 
					
						
							| 
									
										
										
										
											2023-10-15 11:01:45 +03:00
										 |  |  |  */ | 
					
						
							|  |  |  | document.addEventListener('keydown', function(e) { | 
					
						
							|  |  |  |     const isEnter = e.key === 'Enter' || e.keyCode === 13; | 
					
						
							| 
									
										
										
										
											2023-12-09 21:04:45 +06:00
										 |  |  |     const isCtrlKey = e.metaKey || e.ctrlKey; | 
					
						
							|  |  |  |     const isAltKey = e.altKey; | 
					
						
							| 
									
										
										
										
											2023-12-10 16:28:56 +06:00
										 |  |  |     const isEsc = e.key === 'Escape'; | 
					
						
							| 
									
										
										
										
											2023-10-15 11:01:45 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const generateButton = get_uiCurrentTabContent().querySelector('button[id$=_generate]'); | 
					
						
							| 
									
										
										
										
											2023-12-09 21:04:45 +06:00
										 |  |  |     const interruptButton = get_uiCurrentTabContent().querySelector('button[id$=_interrupt]'); | 
					
						
							|  |  |  |     const skipButton = get_uiCurrentTabContent().querySelector('button[id$=_skip]'); | 
					
						
							| 
									
										
										
										
											2023-10-15 11:01:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-10 16:28:56 +06:00
										 |  |  |     if (isCtrlKey && isEnter) { | 
					
						
							| 
									
										
										
										
											2023-10-15 11:01:45 +03:00
										 |  |  |         if (interruptButton.style.display === 'block') { | 
					
						
							|  |  |  |             interruptButton.click(); | 
					
						
							| 
									
										
										
										
											2023-11-13 14:51:06 +06:00
										 |  |  |             const callback = (mutationList) => { | 
					
						
							|  |  |  |                 for (const mutation of mutationList) { | 
					
						
							|  |  |  |                     if (mutation.type === 'attributes' && mutation.attributeName === 'style') { | 
					
						
							|  |  |  |                         if (interruptButton.style.display === 'none') { | 
					
						
							|  |  |  |                             generateButton.click(); | 
					
						
							|  |  |  |                             observer.disconnect(); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  |             const observer = new MutationObserver(callback); | 
					
						
							|  |  |  |             observer.observe(interruptButton, {attributes: true}); | 
					
						
							| 
									
										
										
										
											2023-10-15 11:01:45 +03:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             generateButton.click(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e.preventDefault(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-12-09 21:04:45 +06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-10 16:28:56 +06:00
										 |  |  |     if (isAltKey && isEnter) { | 
					
						
							| 
									
										
										
										
											2023-12-09 21:04:45 +06:00
										 |  |  |         skipButton.click(); | 
					
						
							|  |  |  |         e.preventDefault(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-10 16:28:56 +06:00
										 |  |  |     if (isEsc) { | 
					
						
							| 
									
										
										
										
											2023-12-10 17:06:12 +06:00
										 |  |  |         const globalPopup = document.querySelector('.global-popup'); | 
					
						
							| 
									
										
										
										
											2023-12-11 18:06:08 +06:00
										 |  |  |         const lightboxModal = document.querySelector('#lightboxModal'); | 
					
						
							|  |  |  |         if (!globalPopup || globalPopup.style.display === 'none') { | 
					
						
							|  |  |  |             if (document.activeElement === lightboxModal) return; | 
					
						
							| 
									
										
										
										
											2024-02-17 11:40:53 +03:00
										 |  |  |             if (interruptButton.style.display === 'block') { | 
					
						
							| 
									
										
										
										
											2024-02-15 13:05:39 -05:00
										 |  |  |                 interruptButton.click(); | 
					
						
							|  |  |  |                 e.preventDefault(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-12-10 16:28:56 +06:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-09 21:04:45 +06:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-15 11:01:45 +03:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * checks that a UI element is not in another hidden element or tab content | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function uiElementIsVisible(el) { | 
					
						
							|  |  |  |     if (el === document) { | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | } |