repo_description: Clarity AI | AI Image Upscaler & Enhancer - free and open-source Magnific Alternative
repo_topics: ai ai-art image-upscale image-upscaler image-upscaling image2image img2img stable-diffusion stable-diffusion-webui upscale upscaler upscalerimage
code: 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});
  });
  
  /**
   * Add a ctrl+enter as a shortcut to start a generation
   */
  document.addEventListener('keydown', function(e) {
      const isEnter = e.key === 'Enter' || e.keyCode === 13;
      const isModifierKey = e.metaKey || e.ctrlKey || e.altKey;
  
      const interruptButton = get_uiCurrentTabContent().querySelector('button[id$=_interrupt]');
      const generateButton = get_uiCurrentTabContent().querySelector('button[id$=_generate]');
  
      if (isEnter && isModifierKey) {
          if (interruptButton.style.display === 'block') {
              interruptButton.click();
              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});
          } else {
              generateButton.click();
          }
          e.preventDefault();
      }
  });
  
  /**
   * 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;
  }
  