aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.eslintignore4
-rw-r--r--.eslintrc.js89
-rw-r--r--.github/workflows/on_pull_request.yaml36
-rw-r--r--.gitignore2
-rw-r--r--extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js52
-rw-r--r--javascript/aspectRatioOverlay.js224
-rw-r--r--javascript/contextMenus.js338
-rw-r--r--javascript/dragdrop.js47
-rw-r--r--javascript/edit-attention.js240
-rw-r--r--javascript/extensions.js145
-rw-r--r--javascript/extraNetworks.js420
-rw-r--r--javascript/generationParams.js48
-rw-r--r--javascript/hints.js86
-rw-r--r--javascript/hires_fix.js36
-rw-r--r--javascript/imageMaskFix.js19
-rw-r--r--javascript/imageParams.js4
-rw-r--r--javascript/imageviewer.js226
-rw-r--r--javascript/imageviewerGamepad.js4
-rw-r--r--javascript/localization.js353
-rw-r--r--javascript/notification.js12
-rw-r--r--javascript/progressbar.js184
-rw-r--r--javascript/textualInversion.js34
-rw-r--r--javascript/ui.js423
-rw-r--r--javascript/ui_settings_hints.js124
-rw-r--r--package.json11
-rw-r--r--script.js76
26 files changed, 1680 insertions, 1557 deletions
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 00000000..1cfd9487
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,4 @@
+extensions
+extensions-disabled
+repositories
+venv \ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 00000000..78275554
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,89 @@
+module.exports = {
+ env: {
+ browser: true,
+ es2021: true,
+ },
+ extends: "eslint:recommended",
+ parserOptions: {
+ ecmaVersion: "latest",
+ },
+ rules: {
+ "arrow-spacing": "error",
+ "block-spacing": "error",
+ "brace-style": "error",
+ "comma-dangle": ["error", "only-multiline"],
+ "comma-spacing": "error",
+ "comma-style": ["error", "last"],
+ "curly": ["error", "multi-line", "consistent"],
+ "eol-last": "error",
+ "func-call-spacing": "error",
+ "function-call-argument-newline": ["error", "consistent"],
+ "function-paren-newline": ["error", "consistent"],
+ "indent": ["error", 4],
+ "key-spacing": "error",
+ "keyword-spacing": "error",
+ "linebreak-style": ["error", "unix"],
+ "no-extra-semi": "error",
+ "no-mixed-spaces-and-tabs": "error",
+ "no-trailing-spaces": "error",
+ "no-whitespace-before-property": "error",
+ "object-curly-newline": ["error", {consistent: true, multiline: true}],
+ "quote-props": ["error", "consistent-as-needed"],
+ "semi": ["error", "always"],
+ "semi-spacing": "error",
+ "semi-style": ["error", "last"],
+ "space-before-blocks": "error",
+ "space-before-function-paren": ["error", "never"],
+ "space-in-parens": ["error", "never"],
+ "space-infix-ops": "error",
+ "space-unary-ops": "error",
+ "switch-colon-spacing": "error",
+ "template-curly-spacing": ["error", "never"],
+ "unicode-bom": "error",
+ "no-multi-spaces": "error",
+ "object-curly-spacing": ["error", "never"],
+ "operator-linebreak": ["error", "after"],
+ "no-unused-vars": "off",
+ "no-redeclare": "off",
+ },
+ globals: {
+ // this file
+ module: "writable",
+ //script.js
+ gradioApp: "writable",
+ onUiLoaded: "writable",
+ onUiUpdate: "writable",
+ onOptionsChanged: "writable",
+ uiCurrentTab: "writable",
+ uiElementIsVisible: "writable",
+ executeCallbacks: "writable",
+ //ui.js
+ opts: "writable",
+ all_gallery_buttons: "writable",
+ selected_gallery_button: "writable",
+ selected_gallery_index: "writable",
+ args_to_array: "writable",
+ switch_to_txt2img: "writable",
+ switch_to_img2img_tab: "writable",
+ switch_to_img2img: "writable",
+ switch_to_sketch: "writable",
+ switch_to_inpaint: "writable",
+ switch_to_inpaint_sketch: "writable",
+ switch_to_extras: "writable",
+ get_tab_index: "writable",
+ create_submit_args: "writable",
+ restart_reload: "writable",
+ updateInput: "writable",
+ //extraNetworks.js
+ requestGet: "writable",
+ popup: "writable",
+ // from python
+ localization: "writable",
+ // progrssbar.js
+ randomId: "writable",
+ requestProgress: "writable",
+ // imageviewer.js
+ modalPrevImage: "writable",
+ modalNextImage: "writable",
+ }
+};
diff --git a/.github/workflows/on_pull_request.yaml b/.github/workflows/on_pull_request.yaml
index d42965b1..7b7219fd 100644
--- a/.github/workflows/on_pull_request.yaml
+++ b/.github/workflows/on_pull_request.yaml
@@ -1,19 +1,11 @@
-# See https://github.com/actions/starter-workflows/blob/1067f16ad8a1eac328834e4b0ae24f7d206f810d/ci/pylint.yml for original reference file
name: Run Linting/Formatting on Pull Requests
on:
- push
- pull_request
- # See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onpull_requestpull_request_targetbranchesbranches-ignore for syntax docs
- # if you want to filter out branches, delete the `- pull_request` and uncomment these lines :
- # pull_request:
- # branches:
- # - master
- # branches-ignore:
- # - development
jobs:
- lint:
+ lint-python:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
@@ -29,18 +21,14 @@ jobs:
run: pip install ruff==0.0.265
- name: Run Ruff
run: ruff .
-
-# The rest are currently disabled pending fixing of e.g. installing the torch dependency.
-
-# - name: Install PyLint
-# run: |
-# python -m pip install --upgrade pip
-# pip install pylint
-# # This lets PyLint check to see if it can resolve imports
-# - name: Install dependencies
-# run: |
-# export COMMANDLINE_ARGS="--skip-torch-cuda-test --exit"
-# python launch.py
-# - name: Analysing the code with pylint
-# run: |
-# pylint $(git ls-files '*.py')
+ lint-js:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Code
+ uses: actions/checkout@v3
+ - name: Install Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - run: npm i --ci
+ - run: npm run lint
diff --git a/.gitignore b/.gitignore
index 7328401f..46654d83 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,5 @@ notification.mp3
/test/stderr.txt
/cache.json*
/config_states/
+/node_modules
+/package-lock.json \ No newline at end of file
diff --git a/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js b/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js
index 5c7a836a..114cf94c 100644
--- a/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js
+++ b/extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js
@@ -4,39 +4,39 @@
// If there's a mismatch, the keyword counter turns red and if you hover on it, a tooltip tells you what's wrong.
function checkBrackets(textArea, counterElt) {
- var counts = {};
- (textArea.value.match(/[(){}\[\]]/g) || []).forEach(bracket => {
- counts[bracket] = (counts[bracket] || 0) + 1;
- });
- var errors = [];
+ var counts = {};
+ (textArea.value.match(/[(){}[\]]/g) || []).forEach(bracket => {
+ counts[bracket] = (counts[bracket] || 0) + 1;
+ });
+ var errors = [];
- function checkPair(open, close, kind) {
- if (counts[open] !== counts[close]) {
- errors.push(
- `${open}...${close} - Detected ${counts[open] || 0} opening and ${counts[close] || 0} closing ${kind}.`
- );
+ function checkPair(open, close, kind) {
+ if (counts[open] !== counts[close]) {
+ errors.push(
+ `${open}...${close} - Detected ${counts[open] || 0} opening and ${counts[close] || 0} closing ${kind}.`
+ );
+ }
}
- }
- checkPair('(', ')', 'round brackets');
- checkPair('[', ']', 'square brackets');
- checkPair('{', '}', 'curly brackets');
- counterElt.title = errors.join('\n');
- counterElt.classList.toggle('error', errors.length !== 0);
+ checkPair('(', ')', 'round brackets');
+ checkPair('[', ']', 'square brackets');
+ checkPair('{', '}', 'curly brackets');
+ counterElt.title = errors.join('\n');
+ counterElt.classList.toggle('error', errors.length !== 0);
}
function setupBracketChecking(id_prompt, id_counter) {
- var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea");
- var counter = gradioApp().getElementById(id_counter)
+ var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea");
+ var counter = gradioApp().getElementById(id_counter);
- if (textarea && counter) {
- textarea.addEventListener("input", () => checkBrackets(textarea, counter));
- }
+ if (textarea && counter) {
+ textarea.addEventListener("input", () => checkBrackets(textarea, counter));
+ }
}
-onUiLoaded(function () {
- setupBracketChecking('txt2img_prompt', 'txt2img_token_counter');
- setupBracketChecking('txt2img_neg_prompt', 'txt2img_negative_token_counter');
- setupBracketChecking('img2img_prompt', 'img2img_token_counter');
- setupBracketChecking('img2img_neg_prompt', 'img2img_negative_token_counter');
+onUiLoaded(function() {
+ setupBracketChecking('txt2img_prompt', 'txt2img_token_counter');
+ setupBracketChecking('txt2img_neg_prompt', 'txt2img_negative_token_counter');
+ setupBracketChecking('img2img_prompt', 'img2img_token_counter');
+ setupBracketChecking('img2img_neg_prompt', 'img2img_negative_token_counter');
});
diff --git a/javascript/aspectRatioOverlay.js b/javascript/aspectRatioOverlay.js
index 5160081d..1c08a1a9 100644
--- a/javascript/aspectRatioOverlay.js
+++ b/javascript/aspectRatioOverlay.js
@@ -1,111 +1,113 @@
-
-let currentWidth = null;
-let currentHeight = null;
-let arFrameTimeout = setTimeout(function(){},0);
-
-function dimensionChange(e, is_width, is_height){
-
- if(is_width){
- currentWidth = e.target.value*1.0
- }
- if(is_height){
- currentHeight = e.target.value*1.0
- }
-
- var inImg2img = gradioApp().querySelector("#tab_img2img").style.display == "block";
-
- if(!inImg2img){
- return;
- }
-
- var targetElement = null;
-
- var tabIndex = get_tab_index('mode_img2img')
- if(tabIndex == 0){ // img2img
- targetElement = gradioApp().querySelector('#img2img_image div[data-testid=image] img');
- } else if(tabIndex == 1){ //Sketch
- targetElement = gradioApp().querySelector('#img2img_sketch div[data-testid=image] img');
- } else if(tabIndex == 2){ // Inpaint
- targetElement = gradioApp().querySelector('#img2maskimg div[data-testid=image] img');
- } else if(tabIndex == 3){ // Inpaint sketch
- targetElement = gradioApp().querySelector('#inpaint_sketch div[data-testid=image] img');
- }
-
-
- if(targetElement){
-
- var arPreviewRect = gradioApp().querySelector('#imageARPreview');
- if(!arPreviewRect){
- arPreviewRect = document.createElement('div')
- arPreviewRect.id = "imageARPreview";
- gradioApp().appendChild(arPreviewRect)
- }
-
-
-
- var viewportOffset = targetElement.getBoundingClientRect();
-
- var viewportscale = Math.min( targetElement.clientWidth/targetElement.naturalWidth, targetElement.clientHeight/targetElement.naturalHeight )
-
- var scaledx = targetElement.naturalWidth*viewportscale
- var scaledy = targetElement.naturalHeight*viewportscale
-
- var cleintRectTop = (viewportOffset.top+window.scrollY)
- var cleintRectLeft = (viewportOffset.left+window.scrollX)
- var cleintRectCentreY = cleintRectTop + (targetElement.clientHeight/2)
- var cleintRectCentreX = cleintRectLeft + (targetElement.clientWidth/2)
-
- var arscale = Math.min( scaledx/currentWidth, scaledy/currentHeight )
- var arscaledx = currentWidth*arscale
- var arscaledy = currentHeight*arscale
-
- var arRectTop = cleintRectCentreY-(arscaledy/2)
- var arRectLeft = cleintRectCentreX-(arscaledx/2)
- var arRectWidth = arscaledx
- var arRectHeight = arscaledy
-
- arPreviewRect.style.top = arRectTop+'px';
- arPreviewRect.style.left = arRectLeft+'px';
- arPreviewRect.style.width = arRectWidth+'px';
- arPreviewRect.style.height = arRectHeight+'px';
-
- clearTimeout(arFrameTimeout);
- arFrameTimeout = setTimeout(function(){
- arPreviewRect.style.display = 'none';
- },2000);
-
- arPreviewRect.style.display = 'block';
-
- }
-
-}
-
-
-onUiUpdate(function(){
- var arPreviewRect = gradioApp().querySelector('#imageARPreview');
- if(arPreviewRect){
- arPreviewRect.style.display = 'none';
- }
- var tabImg2img = gradioApp().querySelector("#tab_img2img");
- if (tabImg2img) {
- var inImg2img = tabImg2img.style.display == "block";
- if(inImg2img){
- let inputs = gradioApp().querySelectorAll('input');
- inputs.forEach(function(e){
- var is_width = e.parentElement.id == "img2img_width"
- var is_height = e.parentElement.id == "img2img_height"
-
- if((is_width || is_height) && !e.classList.contains('scrollwatch')){
- e.addEventListener('input', function(e){dimensionChange(e, is_width, is_height)} )
- e.classList.add('scrollwatch')
- }
- if(is_width){
- currentWidth = e.value*1.0
- }
- if(is_height){
- currentHeight = e.value*1.0
- }
- })
- }
- }
-});
+
+let currentWidth = null;
+let currentHeight = null;
+let arFrameTimeout = setTimeout(function() {}, 0);
+
+function dimensionChange(e, is_width, is_height) {
+
+ if (is_width) {
+ currentWidth = e.target.value * 1.0;
+ }
+ if (is_height) {
+ currentHeight = e.target.value * 1.0;
+ }
+
+ var inImg2img = gradioApp().querySelector("#tab_img2img").style.display == "block";
+
+ if (!inImg2img) {
+ return;
+ }
+
+ var targetElement = null;
+
+ var tabIndex = get_tab_index('mode_img2img');
+ if (tabIndex == 0) { // img2img
+ targetElement = gradioApp().querySelector('#img2img_image div[data-testid=image] img');
+ } else if (tabIndex == 1) { //Sketch
+ targetElement = gradioApp().querySelector('#img2img_sketch div[data-testid=image] img');
+ } else if (tabIndex == 2) { // Inpaint
+ targetElement = gradioApp().querySelector('#img2maskimg div[data-testid=image] img');
+ } else if (tabIndex == 3) { // Inpaint sketch
+ targetElement = gradioApp().querySelector('#inpaint_sketch div[data-testid=image] img');
+ }
+
+
+ if (targetElement) {
+
+ var arPreviewRect = gradioApp().querySelector('#imageARPreview');
+ if (!arPreviewRect) {
+ arPreviewRect = document.createElement('div');
+ arPreviewRect.id = "imageARPreview";
+ gradioApp().appendChild(arPreviewRect);
+ }
+
+
+
+ var viewportOffset = targetElement.getBoundingClientRect();
+
+ var viewportscale = Math.min(targetElement.clientWidth / targetElement.naturalWidth, targetElement.clientHeight / targetElement.naturalHeight);
+
+ var scaledx = targetElement.naturalWidth * viewportscale;
+ var scaledy = targetElement.naturalHeight * viewportscale;
+
+ var cleintRectTop = (viewportOffset.top + window.scrollY);
+ var cleintRectLeft = (viewportOffset.left + window.scrollX);
+ var cleintRectCentreY = cleintRectTop + (targetElement.clientHeight / 2);
+ var cleintRectCentreX = cleintRectLeft + (targetElement.clientWidth / 2);
+
+ var arscale = Math.min(scaledx / currentWidth, scaledy / currentHeight);
+ var arscaledx = currentWidth * arscale;
+ var arscaledy = currentHeight * arscale;
+
+ var arRectTop = cleintRectCentreY - (arscaledy / 2);
+ var arRectLeft = cleintRectCentreX - (arscaledx / 2);
+ var arRectWidth = arscaledx;
+ var arRectHeight = arscaledy;
+
+ arPreviewRect.style.top = arRectTop + 'px';
+ arPreviewRect.style.left = arRectLeft + 'px';
+ arPreviewRect.style.width = arRectWidth + 'px';
+ arPreviewRect.style.height = arRectHeight + 'px';
+
+ clearTimeout(arFrameTimeout);
+ arFrameTimeout = setTimeout(function() {
+ arPreviewRect.style.display = 'none';
+ }, 2000);
+
+ arPreviewRect.style.display = 'block';
+
+ }
+
+}
+
+
+onUiUpdate(function() {
+ var arPreviewRect = gradioApp().querySelector('#imageARPreview');
+ if (arPreviewRect) {
+ arPreviewRect.style.display = 'none';
+ }
+ var tabImg2img = gradioApp().querySelector("#tab_img2img");
+ if (tabImg2img) {
+ var inImg2img = tabImg2img.style.display == "block";
+ if (inImg2img) {
+ let inputs = gradioApp().querySelectorAll('input');
+ inputs.forEach(function(e) {
+ var is_width = e.parentElement.id == "img2img_width";
+ var is_height = e.parentElement.id == "img2img_height";
+
+ if ((is_width || is_height) && !e.classList.contains('scrollwatch')) {
+ e.addEventListener('input', function(e) {
+ dimensionChange(e, is_width, is_height);
+ });
+ e.classList.add('scrollwatch');
+ }
+ if (is_width) {
+ currentWidth = e.value * 1.0;
+ }
+ if (is_height) {
+ currentHeight = e.value * 1.0;
+ }
+ });
+ }
+ }
+});
diff --git a/javascript/contextMenus.js b/javascript/contextMenus.js
index b2bdf053..f14af1d4 100644
--- a/javascript/contextMenus.js
+++ b/javascript/contextMenus.js
@@ -1,166 +1,172 @@
-
-contextMenuInit = function(){
- let eventListenerApplied=false;
- let menuSpecs = new Map();
-
- const uid = function(){
- return Date.now().toString(36) + Math.random().toString(36).substring(2);
- }
-
- function showContextMenu(event,element,menuEntries){
- let posx = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
- let posy = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
-
- let oldMenu = gradioApp().querySelector('#context-menu')
- if(oldMenu){
- oldMenu.remove()
- }
-
- let baseStyle = window.getComputedStyle(uiCurrentTab)
-
- const contextMenu = document.createElement('nav')
- contextMenu.id = "context-menu"
- contextMenu.style.background = baseStyle.background
- contextMenu.style.color = baseStyle.color
- contextMenu.style.fontFamily = baseStyle.fontFamily
- contextMenu.style.top = posy+'px'
- contextMenu.style.left = posx+'px'
-
-
-
- const contextMenuList = document.createElement('ul')
- contextMenuList.className = 'context-menu-items';
- contextMenu.append(contextMenuList);
-
- menuEntries.forEach(function(entry){
- let contextMenuEntry = document.createElement('a')
- contextMenuEntry.innerHTML = entry['name']
- contextMenuEntry.addEventListener("click", function() {
- entry['func']();
- })
- contextMenuList.append(contextMenuEntry);
-
- })
-
- gradioApp().appendChild(contextMenu)
-
- let menuWidth = contextMenu.offsetWidth + 4;
- let menuHeight = contextMenu.offsetHeight + 4;
-
- let windowWidth = window.innerWidth;
- let windowHeight = window.innerHeight;
-
- if ( (windowWidth - posx) < menuWidth ) {
- contextMenu.style.left = windowWidth - menuWidth + "px";
- }
-
- if ( (windowHeight - posy) < menuHeight ) {
- contextMenu.style.top = windowHeight - menuHeight + "px";
- }
-
- }
-
- function appendContextMenuOption(targetElementSelector,entryName,entryFunction){
-
- var currentItems = menuSpecs.get(targetElementSelector)
-
- if(!currentItems){
- currentItems = []
- menuSpecs.set(targetElementSelector,currentItems);
- }
- let newItem = {'id':targetElementSelector+'_'+uid(),
- 'name':entryName,
- 'func':entryFunction,
- 'isNew':true}
-
- currentItems.push(newItem)
- return newItem['id']
- }
-
- function removeContextMenuOption(uid){
- menuSpecs.forEach(function(v) {
- let index = -1
- v.forEach(function(e,ei){if(e['id']==uid){index=ei}})
- if(index>=0){
- v.splice(index, 1);
- }
- })
- }
-
- function addContextMenuEventListener(){
- if(eventListenerApplied){
- return;
- }
- gradioApp().addEventListener("click", function(e) {
- if(! e.isTrusted){
- return
- }
-
- let oldMenu = gradioApp().querySelector('#context-menu')
- if(oldMenu){
- oldMenu.remove()
- }
- });
- gradioApp().addEventListener("contextmenu", function(e) {
- let oldMenu = gradioApp().querySelector('#context-menu')
- if(oldMenu){
- oldMenu.remove()
- }
- menuSpecs.forEach(function(v,k) {
- if(e.composedPath()[0].matches(k)){
- showContextMenu(e,e.composedPath()[0],v)
- e.preventDefault()
- }
- })
- });
- eventListenerApplied=true
-
- }
-
- return [appendContextMenuOption, removeContextMenuOption, addContextMenuEventListener]
-}
-
-initResponse = contextMenuInit();
-appendContextMenuOption = initResponse[0];
-removeContextMenuOption = initResponse[1];
-addContextMenuEventListener = initResponse[2];
-
-(function(){
- //Start example Context Menu Items
- let generateOnRepeat = function(genbuttonid,interruptbuttonid){
- let genbutton = gradioApp().querySelector(genbuttonid);
- let interruptbutton = gradioApp().querySelector(interruptbuttonid);
- if(!interruptbutton.offsetParent){
- genbutton.click();
- }
- clearInterval(window.generateOnRepeatInterval)
- window.generateOnRepeatInterval = setInterval(function(){
- if(!interruptbutton.offsetParent){
- genbutton.click();
- }
- },
- 500)
- }
-
- appendContextMenuOption('#txt2img_generate','Generate forever',function(){
- generateOnRepeat('#txt2img_generate','#txt2img_interrupt');
- })
- appendContextMenuOption('#img2img_generate','Generate forever',function(){
- generateOnRepeat('#img2img_generate','#img2img_interrupt');
- })
-
- let cancelGenerateForever = function(){
- clearInterval(window.generateOnRepeatInterval)
- }
-
- appendContextMenuOption('#txt2img_interrupt','Cancel generate forever',cancelGenerateForever)
- appendContextMenuOption('#txt2img_generate', 'Cancel generate forever',cancelGenerateForever)
- appendContextMenuOption('#img2img_interrupt','Cancel generate forever',cancelGenerateForever)
- appendContextMenuOption('#img2img_generate', 'Cancel generate forever',cancelGenerateForever)
-
-})();
-//End example Context Menu Items
-
-onUiUpdate(function(){
- addContextMenuEventListener()
-});
+
+var contextMenuInit = function() {
+ let eventListenerApplied = false;
+ let menuSpecs = new Map();
+
+ const uid = function() {
+ return Date.now().toString(36) + Math.random().toString(36).substring(2);
+ };
+
+ function showContextMenu(event, element, menuEntries) {
+ let posx = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
+ let posy = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
+
+ let oldMenu = gradioApp().querySelector('#context-menu');
+ if (oldMenu) {
+ oldMenu.remove();
+ }
+
+ let baseStyle = window.getComputedStyle(uiCurrentTab);
+
+ const contextMenu = document.createElement('nav');
+ contextMenu.id = "context-menu";
+ contextMenu.style.background = baseStyle.background;
+ contextMenu.style.color = baseStyle.color;
+ contextMenu.style.fontFamily = baseStyle.fontFamily;
+ contextMenu.style.top = posy + 'px';
+ contextMenu.style.left = posx + 'px';
+
+
+
+ const contextMenuList = document.createElement('ul');
+ contextMenuList.className = 'context-menu-items';
+ contextMenu.append(contextMenuList);
+
+ menuEntries.forEach(function(entry) {
+ let contextMenuEntry = document.createElement('a');
+ contextMenuEntry.innerHTML = entry['name'];
+ contextMenuEntry.addEventListener("click", function() {
+ entry['func']();
+ });
+ contextMenuList.append(contextMenuEntry);
+
+ });
+
+ gradioApp().appendChild(contextMenu);
+
+ let menuWidth = contextMenu.offsetWidth + 4;
+ let menuHeight = contextMenu.offsetHeight + 4;
+
+ let windowWidth = window.innerWidth;
+ let windowHeight = window.innerHeight;
+
+ if ((windowWidth - posx) < menuWidth) {
+ contextMenu.style.left = windowWidth - menuWidth + "px";
+ }
+
+ if ((windowHeight - posy) < menuHeight) {
+ contextMenu.style.top = windowHeight - menuHeight + "px";
+ }
+
+ }
+
+ function appendContextMenuOption(targetElementSelector, entryName, entryFunction) {
+
+ var currentItems = menuSpecs.get(targetElementSelector);
+
+ if (!currentItems) {
+ currentItems = [];
+ menuSpecs.set(targetElementSelector, currentItems);
+ }
+ let newItem = {
+ id: targetElementSelector + '_' + uid(),
+ name: entryName,
+ func: entryFunction,
+ isNew: true
+ };
+
+ currentItems.push(newItem);
+ return newItem['id'];
+ }
+
+ function removeContextMenuOption(uid) {
+ menuSpecs.forEach(function(v) {
+ let index = -1;
+ v.forEach(function(e, ei) {
+ if (e['id'] == uid) {
+ index = ei;
+ }
+ });
+ if (index >= 0) {
+ v.splice(index, 1);
+ }
+ });
+ }
+
+ function addContextMenuEventListener() {
+ if (eventListenerApplied) {
+ return;
+ }
+ gradioApp().addEventListener("click", function(e) {
+ if (!e.isTrusted) {
+ return;
+ }
+
+ let oldMenu = gradioApp().querySelector('#context-menu');
+ if (oldMenu) {
+ oldMenu.remove();
+ }
+ });
+ gradioApp().addEventListener("contextmenu", function(e) {
+ let oldMenu = gradioApp().querySelector('#context-menu');
+ if (oldMenu) {
+ oldMenu.remove();
+ }
+ menuSpecs.forEach(function(v, k) {
+ if (e.composedPath()[0].matches(k)) {
+ showContextMenu(e, e.composedPath()[0], v);
+ e.preventDefault();
+ }
+ });
+ });
+ eventListenerApplied = true;
+
+ }
+
+ return [appendContextMenuOption, removeContextMenuOption, addContextMenuEventListener];
+};
+
+var initResponse = contextMenuInit();
+var appendContextMenuOption = initResponse[0];
+var removeContextMenuOption = initResponse[1];
+var addContextMenuEventListener = initResponse[2];
+
+(function() {
+ //Start example Context Menu Items
+ let generateOnRepeat = function(genbuttonid, interruptbuttonid) {
+ let genbutton = gradioApp().querySelector(genbuttonid);
+ let interruptbutton = gradioApp().querySelector(interruptbuttonid);
+ if (!interruptbutton.offsetParent) {
+ genbutton.click();
+ }
+ clearInterval(window.generateOnRepeatInterval);
+ window.generateOnRepeatInterval = setInterval(function() {
+ if (!interruptbutton.offsetParent) {
+ genbutton.click();
+ }
+ },
+ 500);
+ };
+
+ appendContextMenuOption('#txt2img_generate', 'Generate forever', function() {
+ generateOnRepeat('#txt2img_generate', '#txt2img_interrupt');
+ });
+ appendContextMenuOption('#img2img_generate', 'Generate forever', function() {
+ generateOnRepeat('#img2img_generate', '#img2img_interrupt');
+ });
+
+ let cancelGenerateForever = function() {
+ clearInterval(window.generateOnRepeatInterval);
+ };
+
+ appendContextMenuOption('#txt2img_interrupt', 'Cancel generate forever', cancelGenerateForever);
+ appendContextMenuOption('#txt2img_generate', 'Cancel generate forever', cancelGenerateForever);
+ appendContextMenuOption('#img2img_interrupt', 'Cancel generate forever', cancelGenerateForever);
+ appendContextMenuOption('#img2img_generate', 'Cancel generate forever', cancelGenerateForever);
+
+})();
+//End example Context Menu Items
+
+onUiUpdate(function() {
+ addContextMenuEventListener();
+});
diff --git a/javascript/dragdrop.js b/javascript/dragdrop.js
index fe008924..e316a365 100644
--- a/javascript/dragdrop.js
+++ b/javascript/dragdrop.js
@@ -1,11 +1,11 @@
// allows drag-dropping files into gradio image elements, and also pasting images from clipboard
-function isValidImageList( files ) {
+function isValidImageList(files) {
return files && files?.length === 1 &&