Adityadn commited on
Commit
57315d7
·
verified ·
1 Parent(s): 492b7c0

Delete javascript

Browse files
javascript/contextMenus.js DELETED
@@ -1,166 +0,0 @@
1
- // based on https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/v1.6.0/javascript/contextMenus.js
2
-
3
- var contextMenuInit = function() {
4
- let eventListenerApplied = false;
5
- let menuSpecs = new Map();
6
-
7
- const uid = function() {
8
- return Date.now().toString(36) + Math.random().toString(36).substring(2);
9
- };
10
-
11
- function showContextMenu(event, element, menuEntries) {
12
- let posx = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
13
- let posy = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
14
-
15
- let oldMenu = gradioApp().querySelector('#context-menu');
16
- if (oldMenu) {
17
- oldMenu.remove();
18
- }
19
-
20
- let baseStyle = window.getComputedStyle(gradioApp().querySelector('button.selected'));
21
-
22
- const contextMenu = document.createElement('nav');
23
- contextMenu.id = "context-menu";
24
- contextMenu.style.background = baseStyle.background;
25
- contextMenu.style.color = baseStyle.color;
26
- contextMenu.style.fontFamily = baseStyle.fontFamily;
27
- contextMenu.style.top = posy + 'px';
28
- contextMenu.style.left = posx + 'px';
29
-
30
- const contextMenuList = document.createElement('ul');
31
- contextMenuList.className = 'context-menu-items';
32
- contextMenu.append(contextMenuList);
33
-
34
- menuEntries.forEach(function(entry) {
35
- let contextMenuEntry = document.createElement('a');
36
- contextMenuEntry.innerHTML = entry['name'];
37
- contextMenuEntry.addEventListener("click", function() {
38
- entry['func']();
39
- });
40
- contextMenuList.append(contextMenuEntry);
41
-
42
- });
43
-
44
- gradioApp().appendChild(contextMenu);
45
-
46
- let menuWidth = contextMenu.offsetWidth + 4;
47
- let menuHeight = contextMenu.offsetHeight + 4;
48
-
49
- let windowWidth = window.innerWidth;
50
- let windowHeight = window.innerHeight;
51
-
52
- if ((windowWidth - posx) < menuWidth) {
53
- contextMenu.style.left = windowWidth - menuWidth + "px";
54
- }
55
-
56
- if ((windowHeight - posy) < menuHeight) {
57
- contextMenu.style.top = windowHeight - menuHeight + "px";
58
- }
59
-
60
- }
61
-
62
- function appendContextMenuOption(targetElementSelector, entryName, entryFunction) {
63
-
64
- var currentItems = menuSpecs.get(targetElementSelector);
65
-
66
- if (!currentItems) {
67
- currentItems = [];
68
- menuSpecs.set(targetElementSelector, currentItems);
69
- }
70
- let newItem = {
71
- id: targetElementSelector + '_' + uid(),
72
- name: entryName,
73
- func: entryFunction,
74
- isNew: true
75
- };
76
-
77
- currentItems.push(newItem);
78
- return newItem['id'];
79
- }
80
-
81
- function removeContextMenuOption(uid) {
82
- menuSpecs.forEach(function(v) {
83
- let index = -1;
84
- v.forEach(function(e, ei) {
85
- if (e['id'] == uid) {
86
- index = ei;
87
- }
88
- });
89
- if (index >= 0) {
90
- v.splice(index, 1);
91
- }
92
- });
93
- }
94
-
95
- function addContextMenuEventListener() {
96
- if (eventListenerApplied) {
97
- return;
98
- }
99
- gradioApp().addEventListener("click", function(e) {
100
- if (!e.isTrusted) {
101
- return;
102
- }
103
-
104
- let oldMenu = gradioApp().querySelector('#context-menu');
105
- if (oldMenu) {
106
- oldMenu.remove();
107
- }
108
- });
109
- gradioApp().addEventListener("contextmenu", function(e) {
110
- let oldMenu = gradioApp().querySelector('#context-menu');
111
- if (oldMenu) {
112
- oldMenu.remove();
113
- }
114
- menuSpecs.forEach(function(v, k) {
115
- if (e.composedPath()[0].matches(k)) {
116
- showContextMenu(e, e.composedPath()[0], v);
117
- e.preventDefault();
118
- }
119
- });
120
- });
121
- eventListenerApplied = true;
122
-
123
- }
124
-
125
- return [appendContextMenuOption, removeContextMenuOption, addContextMenuEventListener];
126
- };
127
-
128
- var initResponse = contextMenuInit();
129
- var appendContextMenuOption = initResponse[0];
130
- var removeContextMenuOption = initResponse[1];
131
- var addContextMenuEventListener = initResponse[2];
132
-
133
- let cancelGenerateForever = function() {
134
- clearInterval(window.generateOnRepeatInterval);
135
- };
136
-
137
- (function() {
138
- //Start example Context Menu Items
139
- let generateOnRepeat = function(genbuttonid, interruptbuttonid) {
140
- let genbutton = gradioApp().querySelector(genbuttonid);
141
- let interruptbutton = gradioApp().querySelector(interruptbuttonid);
142
- if (!interruptbutton.offsetParent) {
143
- genbutton.click();
144
- }
145
- clearInterval(window.generateOnRepeatInterval);
146
- window.generateOnRepeatInterval = setInterval(function() {
147
- if (!interruptbutton.offsetParent) {
148
- genbutton.click();
149
- }
150
- },
151
- 500);
152
- };
153
-
154
- let generateOnRepeatForButtons = function() {
155
- generateOnRepeat('#generate_button', '#stop_button');
156
- };
157
- appendContextMenuOption('#generate_button', 'Generate forever', generateOnRepeatForButtons);
158
-
159
- })();
160
- //End example Context Menu Items
161
-
162
- document.onreadystatechange = function () {
163
- if (document.readyState == "complete") {
164
- addContextMenuEventListener();
165
- }
166
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
javascript/edit-attention.js DELETED
@@ -1,128 +0,0 @@
1
- function updateInput(target) {
2
- let e = new Event("input", {bubbles: true});
3
- Object.defineProperty(e, "target", {value: target});
4
- target.dispatchEvent(e);
5
- }
6
-
7
- function keyupEditAttention(event) {
8
- let target = event.originalTarget || event.composedPath()[0];
9
- if (!target.matches("*:is([id*='_prompt'], .prompt) textarea")) return;
10
- if (!(event.metaKey || event.ctrlKey)) return;
11
-
12
- let isPlus = event.key == "ArrowUp";
13
- let isMinus = event.key == "ArrowDown";
14
- if (!isPlus && !isMinus) return;
15
-
16
- let selectionStart = target.selectionStart;
17
- let selectionEnd = target.selectionEnd;
18
- let text = target.value;
19
-
20
- function selectCurrentParenthesisBlock(OPEN, CLOSE) {
21
- if (selectionStart !== selectionEnd) return false;
22
-
23
- // Find opening parenthesis around current cursor
24
- const before = text.substring(0, selectionStart);
25
- let beforeParen = before.lastIndexOf(OPEN);
26
- if (beforeParen == -1) return false;
27
- let beforeParenClose = before.lastIndexOf(CLOSE);
28
- while (beforeParenClose !== -1 && beforeParenClose > beforeParen) {
29
- beforeParen = before.lastIndexOf(OPEN, beforeParen - 1);
30
- beforeParenClose = before.lastIndexOf(CLOSE, beforeParenClose - 1);
31
- }
32
-
33
- // Find closing parenthesis around current cursor
34
- const after = text.substring(selectionStart);
35
- let afterParen = after.indexOf(CLOSE);
36
- if (afterParen == -1) return false;
37
- let afterParenOpen = after.indexOf(OPEN);
38
- while (afterParenOpen !== -1 && afterParen > afterParenOpen) {
39
- afterParen = after.indexOf(CLOSE, afterParen + 1);
40
- afterParenOpen = after.indexOf(OPEN, afterParenOpen + 1);
41
- }
42
- if (beforeParen === -1 || afterParen === -1) return false;
43
-
44
- // Set the selection to the text between the parenthesis
45
- const parenContent = text.substring(beforeParen + 1, selectionStart + afterParen);
46
- const lastColon = parenContent.lastIndexOf(":");
47
- selectionStart = beforeParen + 1;
48
- selectionEnd = selectionStart + lastColon;
49
- target.setSelectionRange(selectionStart, selectionEnd);
50
- return true;
51
- }
52
-
53
- function selectCurrentWord() {
54
- if (selectionStart !== selectionEnd) return false;
55
- const delimiters = ".,\\/!?%^*;:{}=`~() \r\n\t";
56
-
57
- // seek backward until to find beggining
58
- while (!delimiters.includes(text[selectionStart - 1]) && selectionStart > 0) {
59
- selectionStart--;
60
- }
61
-
62
- // seek forward to find end
63
- while (!delimiters.includes(text[selectionEnd]) && selectionEnd < text.length) {
64
- selectionEnd++;
65
- }
66
-
67
- target.setSelectionRange(selectionStart, selectionEnd);
68
- return true;
69
- }
70
-
71
- // If the user hasn't selected anything, let's select their current parenthesis block or word
72
- if (!selectCurrentParenthesisBlock('<', '>') && !selectCurrentParenthesisBlock('(', ')')) {
73
- selectCurrentWord();
74
- }
75
-
76
- event.preventDefault();
77
-
78
- var closeCharacter = ')';
79
- var delta = 0.1;
80
-
81
- if (selectionStart > 0 && text[selectionStart - 1] == '<') {
82
- closeCharacter = '>';
83
- delta = 0.05;
84
- } else if (selectionStart == 0 || text[selectionStart - 1] != "(") {
85
-
86
- // do not include spaces at the end
87
- while (selectionEnd > selectionStart && text[selectionEnd - 1] == ' ') {
88
- selectionEnd -= 1;
89
- }
90
- if (selectionStart == selectionEnd) {
91
- return;
92
- }
93
-
94
- text = text.slice(0, selectionStart) + "(" + text.slice(selectionStart, selectionEnd) + ":1.0)" + text.slice(selectionEnd);
95
-
96
- selectionStart += 1;
97
- selectionEnd += 1;
98
- }
99
-
100
- var end = text.slice(selectionEnd + 1).indexOf(closeCharacter) + 1;
101
- var weight = parseFloat(text.slice(selectionEnd + 1, selectionEnd + 1 + end));
102
- if (isNaN(weight)) return;
103
-
104
- weight += isPlus ? delta : -delta;
105
- weight = parseFloat(weight.toPrecision(12));
106
- if (String(weight).length == 1) weight += ".0";
107
-
108
- if (closeCharacter == ')' && weight == 1) {
109
- var endParenPos = text.substring(selectionEnd).indexOf(')');
110
- text = text.slice(0, selectionStart - 1) + text.slice(selectionStart, selectionEnd) + text.slice(selectionEnd + endParenPos + 1);
111
- selectionStart--;
112
- selectionEnd--;
113
- } else {
114
- text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + end);
115
- }
116
-
117
- target.focus();
118
- target.value = text;
119
- target.selectionStart = selectionStart;
120
- target.selectionEnd = selectionEnd;
121
-
122
- updateInput(target);
123
-
124
- }
125
-
126
- addEventListener('keydown', (event) => {
127
- keyupEditAttention(event);
128
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
javascript/imageviewer.js DELETED
@@ -1,260 +0,0 @@
1
- // From A1111
2
-
3
- function closeModal() {
4
- gradioApp().getElementById("lightboxModal").style.display = "none";
5
- }
6
-
7
- function showModal(event) {
8
- const source = event.target || event.srcElement;
9
- const modalImage = gradioApp().getElementById("modalImage");
10
- const lb = gradioApp().getElementById("lightboxModal");
11
- modalImage.src = source.src;
12
- if (modalImage.style.display === 'none') {
13
- lb.style.setProperty('background-image', 'url(' + source.src + ')');
14
- }
15
- lb.style.display = "flex";
16
- lb.focus();
17
-
18
- event.stopPropagation();
19
- }
20
-
21
- function negmod(n, m) {
22
- return ((n % m) + m) % m;
23
- }
24
-
25
- function updateOnBackgroundChange() {
26
- const modalImage = gradioApp().getElementById("modalImage");
27
- if (modalImage && modalImage.offsetParent) {
28
- let currentButton = selected_gallery_button();
29
-
30
- if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) {
31
- modalImage.src = currentButton.children[0].src;
32
- if (modalImage.style.display === 'none') {
33
- const modal = gradioApp().getElementById("lightboxModal");
34
- modal.style.setProperty('background-image', `url(${modalImage.src})`);
35
- }
36
- }
37
- }
38
- }
39
-
40
- function all_gallery_buttons() {
41
- var allGalleryButtons = gradioApp().querySelectorAll('.image_gallery .thumbnails > .thumbnail-item.thumbnail-small');
42
- var visibleGalleryButtons = [];
43
- allGalleryButtons.forEach(function(elem) {
44
- if (elem.parentElement.offsetParent) {
45
- visibleGalleryButtons.push(elem);
46
- }
47
- });
48
- return visibleGalleryButtons;
49
- }
50
-
51
- function selected_gallery_button() {
52
- return all_gallery_buttons().find(elem => elem.classList.contains('selected')) ?? null;
53
- }
54
-
55
- function selected_gallery_index() {
56
- return all_gallery_buttons().findIndex(elem => elem.classList.contains('selected'));
57
- }
58
-
59
- function modalImageSwitch(offset) {
60
- var galleryButtons = all_gallery_buttons();
61
-
62
- if (galleryButtons.length > 1) {
63
- var currentButton = selected_gallery_button();
64
-
65
- var result = -1;
66
- galleryButtons.forEach(function(v, i) {
67
- if (v == currentButton) {
68
- result = i;
69
- }
70
- });
71
-
72
- if (result != -1) {
73
- var nextButton = galleryButtons[negmod((result + offset), galleryButtons.length)];
74
- nextButton.click();
75
- const modalImage = gradioApp().getElementById("modalImage");
76
- const modal = gradioApp().getElementById("lightboxModal");
77
- modalImage.src = nextButton.children[0].src;
78
- if (modalImage.style.display === 'none') {
79
- modal.style.setProperty('background-image', `url(${modalImage.src})`);
80
- }
81
- setTimeout(function() {
82
- modal.focus();
83
- }, 10);
84
- }
85
- }
86
- }
87
-
88
- function saveImage() {
89
-
90
- }
91
-
92
- function modalSaveImage(event) {
93
- event.stopPropagation();
94
- }
95
-
96
- function modalNextImage(event) {
97
- modalImageSwitch(1);
98
- event.stopPropagation();
99
- }
100
-
101
- function modalPrevImage(event) {
102
- modalImageSwitch(-1);
103
- event.stopPropagation();
104
- }
105
-
106
- function modalKeyHandler(event) {
107
- switch (event.key) {
108
- case "s":
109
- saveImage();
110
- break;
111
- case "ArrowLeft":
112
- modalPrevImage(event);
113
- break;
114
- case "ArrowRight":
115
- modalNextImage(event);
116
- break;
117
- case "Escape":
118
- closeModal();
119
- break;
120
- }
121
- }
122
-
123
- function setupImageForLightbox(e) {
124
- if (e.dataset.modded) {
125
- return;
126
- }
127
-
128
- e.dataset.modded = true;
129
- e.style.cursor = 'pointer';
130
- e.style.userSelect = 'none';
131
-
132
- var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
133
-
134
- // For Firefox, listening on click first switched to next image then shows the lightbox.
135
- // If you know how to fix this without switching to mousedown event, please.
136
- // For other browsers the event is click to make it possiblr to drag picture.
137
- var event = isFirefox ? 'mousedown' : 'click';
138
-
139
- e.addEventListener(event, function(evt) {
140
- if (evt.button == 1) {
141
- open(evt.target.src);
142
- evt.preventDefault();
143
- return;
144
- }
145
- if (evt.button != 0) return;
146
-
147
- modalZoomSet(gradioApp().getElementById('modalImage'), true);
148
- evt.preventDefault();
149
- showModal(evt);
150
- }, true);
151
-
152
- }
153
-
154
- function modalZoomSet(modalImage, enable) {
155
- if (modalImage) modalImage.classList.toggle('modalImageFullscreen', !!enable);
156
- }
157
-
158
- function modalZoomToggle(event) {
159
- var modalImage = gradioApp().getElementById("modalImage");
160
- modalZoomSet(modalImage, !modalImage.classList.contains('modalImageFullscreen'));
161
- event.stopPropagation();
162
- }
163
-
164
- function modalTileImageToggle(event) {
165
- const modalImage = gradioApp().getElementById("modalImage");
166
- const modal = gradioApp().getElementById("lightboxModal");
167
- const isTiling = modalImage.style.display === 'none';
168
- if (isTiling) {
169
- modalImage.style.display = 'block';
170
- modal.style.setProperty('background-image', 'none');
171
- } else {
172
- modalImage.style.display = 'none';
173
- modal.style.setProperty('background-image', `url(${modalImage.src})`);
174
- }
175
-
176
- event.stopPropagation();
177
- }
178
-
179
- onAfterUiUpdate(function() {
180
- var fullImg_preview = gradioApp().querySelectorAll('.image_gallery > div > img');
181
- if (fullImg_preview != null) {
182
- fullImg_preview.forEach(setupImageForLightbox);
183
- }
184
- updateOnBackgroundChange();
185
- });
186
-
187
- document.addEventListener("DOMContentLoaded", function() {
188
- //const modalFragment = document.createDocumentFragment();
189
- const modal = document.createElement('div');
190
- modal.onclick = closeModal;
191
- modal.id = "lightboxModal";
192
- modal.tabIndex = 0;
193
- modal.addEventListener('keydown', modalKeyHandler, true);
194
-
195
- const modalControls = document.createElement('div');
196
- modalControls.className = 'modalControls gradio-container';
197
- modal.append(modalControls);
198
-
199
- const modalZoom = document.createElement('span');
200
- modalZoom.className = 'modalZoom cursor';
201
- modalZoom.innerHTML = '&#10529;';
202
- modalZoom.addEventListener('click', modalZoomToggle, true);
203
- modalZoom.title = "Toggle zoomed view";
204
- modalControls.appendChild(modalZoom);
205
-
206
- // const modalTileImage = document.createElement('span');
207
- // modalTileImage.className = 'modalTileImage cursor';
208
- // modalTileImage.innerHTML = '&#8862;';
209
- // modalTileImage.addEventListener('click', modalTileImageToggle, true);
210
- // modalTileImage.title = "Preview tiling";
211
- // modalControls.appendChild(modalTileImage);
212
- //
213
- // const modalSave = document.createElement("span");
214
- // modalSave.className = "modalSave cursor";
215
- // modalSave.id = "modal_save";
216
- // modalSave.innerHTML = "&#x1F5AB;";
217
- // modalSave.addEventListener("click", modalSaveImage, true);
218
- // modalSave.title = "Save Image(s)";
219
- // modalControls.appendChild(modalSave);
220
-
221
- const modalClose = document.createElement('span');
222
- modalClose.className = 'modalClose cursor';
223
- modalClose.innerHTML = '&times;';
224
- modalClose.onclick = closeModal;
225
- modalClose.title = "Close image viewer";
226
- modalControls.appendChild(modalClose);
227
-
228
- const modalImage = document.createElement('img');
229
- modalImage.id = 'modalImage';
230
- modalImage.onclick = closeModal;
231
- modalImage.tabIndex = 0;
232
- modalImage.addEventListener('keydown', modalKeyHandler, true);
233
- modal.appendChild(modalImage);
234
-
235
- const modalPrev = document.createElement('a');
236
- modalPrev.className = 'modalPrev';
237
- modalPrev.innerHTML = '&#10094;';
238
- modalPrev.tabIndex = 0;
239
- modalPrev.addEventListener('click', modalPrevImage, true);
240
- modalPrev.addEventListener('keydown', modalKeyHandler, true);
241
- modal.appendChild(modalPrev);
242
-
243
- const modalNext = document.createElement('a');
244
- modalNext.className = 'modalNext';
245
- modalNext.innerHTML = '&#10095;';
246
- modalNext.tabIndex = 0;
247
- modalNext.addEventListener('click', modalNextImage, true);
248
- modalNext.addEventListener('keydown', modalKeyHandler, true);
249
-
250
- modal.appendChild(modalNext);
251
-
252
- try {
253
- gradioApp().appendChild(modal);
254
- } catch (e) {
255
- gradioApp().body.appendChild(modal);
256
- }
257
-
258
- document.body.appendChild(modal);
259
-
260
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
javascript/localization.js DELETED
@@ -1,144 +0,0 @@
1
- var re_num = /^[.\d]+$/;
2
-
3
- var original_lines = {};
4
- var translated_lines = {};
5
-
6
- function hasLocalization() {
7
- return window.localization && Object.keys(window.localization).length > 0;
8
- }
9
-
10
- function textNodesUnder(el) {
11
- var n, a = [], walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false);
12
- while ((n = walk.nextNode())) a.push(n);
13
- return a;
14
- }
15
-
16
- function canBeTranslated(node, text) {
17
- if (!text) return false;
18
- if (!node.parentElement) return false;
19
- var parentType = node.parentElement.nodeName;
20
- if (parentType == 'SCRIPT' || parentType == 'STYLE' || parentType == 'TEXTAREA') return false;
21
- if (re_num.test(text)) return false;
22
- return true;
23
- }
24
-
25
- function getTranslation(text) {
26
- if (!text) return undefined;
27
-
28
- if (translated_lines[text] === undefined) {
29
- original_lines[text] = 1;
30
- }
31
-
32
- var tl = localization[text];
33
- if (tl !== undefined) {
34
- translated_lines[tl] = 1;
35
- }
36
-
37
- return tl;
38
- }
39
-
40
- function processTextNode(node) {
41
- var text = node.textContent.trim();
42
-
43
- if (!canBeTranslated(node, text)) return;
44
-
45
- var tl = getTranslation(text);
46
- if (tl !== undefined) {
47
- node.textContent = tl;
48
- if (text && node.parentElement) {
49
- node.parentElement.setAttribute("data-original-text", text);
50
- }
51
- }
52
- }
53
-
54
- function processNode(node) {
55
- if (node.nodeType == 3) {
56
- processTextNode(node);
57
- return;
58
- }
59
-
60
- if (node.title) {
61
- let tl = getTranslation(node.title);
62
- if (tl !== undefined) {
63
- node.title = tl;
64
- }
65
- }
66
-
67
- if (node.placeholder) {
68
- let tl = getTranslation(node.placeholder);
69
- if (tl !== undefined) {
70
- node.placeholder = tl;
71
- }
72
- }
73
-
74
- textNodesUnder(node).forEach(function(node) {
75
- processTextNode(node);
76
- });
77
- }
78
-
79
- function refresh_style_localization() {
80
- processNode(document.querySelector('.style_selections'));
81
- }
82
-
83
- function localizeWholePage() {
84
- processNode(gradioApp());
85
-
86
- function elem(comp) {
87
- var elem_id = comp.props.elem_id ? comp.props.elem_id : "component-" + comp.id;
88
- return gradioApp().getElementById(elem_id);
89
- }
90
-
91
- for (var comp of window.gradio_config.components) {
92
- if (comp.props.webui_tooltip) {
93
- let e = elem(comp);
94
-
95
- let tl = e ? getTranslation(e.title) : undefined;
96
- if (tl !== undefined) {
97
- e.title = tl;
98
- }
99
- }
100
- if (comp.props.placeholder) {
101
- let e = elem(comp);
102
- let textbox = e ? e.querySelector('[placeholder]') : null;
103
-
104
- let tl = textbox ? getTranslation(textbox.placeholder) : undefined;
105
- if (tl !== undefined) {
106
- textbox.placeholder = tl;
107
- }
108
- }
109
- }
110
- }
111
-
112
- document.addEventListener("DOMContentLoaded", function() {
113
- if (!hasLocalization()) {
114
- return;
115
- }
116
-
117
- onUiUpdate(function(m) {
118
- m.forEach(function(mutation) {
119
- mutation.addedNodes.forEach(function(node) {
120
- processNode(node);
121
- });
122
- });
123
- });
124
-
125
- localizeWholePage();
126
-
127
- if (localization.rtl) { // if the language is from right to left,
128
- (new MutationObserver((mutations, observer) => { // wait for the style to load
129
- mutations.forEach(mutation => {
130
- mutation.addedNodes.forEach(node => {
131
- if (node.tagName === 'STYLE') {
132
- observer.disconnect();
133
-
134
- for (const x of node.sheet.rules) { // find all rtl media rules
135
- if (Array.from(x.media || []).includes('rtl')) {
136
- x.media.appendMedium('all'); // enable them
137
- }
138
- }
139
- }
140
- });
141
- });
142
- })).observe(gradioApp(), {childList: true});
143
- }
144
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
javascript/script.js DELETED
@@ -1,215 +0,0 @@
1
- // based on https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/v1.6.0/script.js
2
- function gradioApp() {
3
- const elems = document.getElementsByTagName('gradio-app');
4
- const elem = elems.length == 0 ? document : elems[0];
5
-
6
- if (elem !== document) {
7
- elem.getElementById = function(id) {
8
- return document.getElementById(id);
9
- };
10
- }
11
- return elem.shadowRoot ? elem.shadowRoot : elem;
12
- }
13
-
14
- /**
15
- * Get the currently selected top-level UI tab button (e.g. the button that says "Extras").
16
- */
17
- function get_uiCurrentTab() {
18
- return gradioApp().querySelector('#tabs > .tab-nav > button.selected');
19
- }
20
-
21
- /**
22
- * Get the first currently visible top-level UI tab content (e.g. the div hosting the "txt2img" UI).
23
- */
24
- function get_uiCurrentTabContent() {
25
- return gradioApp().querySelector('#tabs > .tabitem[id^=tab_]:not([style*="display: none"])');
26
- }
27
-
28
- var uiUpdateCallbacks = [];
29
- var uiAfterUpdateCallbacks = [];
30
- var uiLoadedCallbacks = [];
31
- var uiTabChangeCallbacks = [];
32
- var optionsChangedCallbacks = [];
33
- var uiAfterUpdateTimeout = null;
34
- var uiCurrentTab = null;
35
-
36
- /**
37
- * Register callback to be called at each UI update.
38
- * The callback receives an array of MutationRecords as an argument.
39
- */
40
- function onUiUpdate(callback) {
41
- uiUpdateCallbacks.push(callback);
42
- }
43
-
44
- /**
45
- * Register callback to be called soon after UI updates.
46
- * The callback receives no arguments.
47
- *
48
- * This is preferred over `onUiUpdate` if you don't need
49
- * access to the MutationRecords, as your function will
50
- * not be called quite as often.
51
- */
52
- function onAfterUiUpdate(callback) {
53
- uiAfterUpdateCallbacks.push(callback);
54
- }
55
-
56
- /**
57
- * Register callback to be called when the UI is loaded.
58
- * The callback receives no arguments.
59
- */
60
- function onUiLoaded(callback) {
61
- uiLoadedCallbacks.push(callback);
62
- }
63
-
64
- /**
65
- * Register callback to be called when the UI tab is changed.
66
- * The callback receives no arguments.
67
- */
68
- function onUiTabChange(callback) {
69
- uiTabChangeCallbacks.push(callback);
70
- }
71
-
72
- /**
73
- * Register callback to be called when the options are changed.
74
- * The callback receives no arguments.
75
- * @param callback
76
- */
77
- function onOptionsChanged(callback) {
78
- optionsChangedCallbacks.push(callback);
79
- }
80
-
81
- function executeCallbacks(queue, arg) {
82
- for (const callback of queue) {
83
- try {
84
- callback(arg);
85
- } catch (e) {
86
- console.error("error running callback", callback, ":", e);
87
- }
88
- }
89
- }
90
-
91
- /**
92
- * Schedule the execution of the callbacks registered with onAfterUiUpdate.
93
- * The callbacks are executed after a short while, unless another call to this function
94
- * is made before that time. IOW, the callbacks are executed only once, even
95
- * when there are multiple mutations observed.
96
- */
97
- function scheduleAfterUiUpdateCallbacks() {
98
- clearTimeout(uiAfterUpdateTimeout);
99
- uiAfterUpdateTimeout = setTimeout(function() {
100
- executeCallbacks(uiAfterUpdateCallbacks);
101
- }, 200);
102
- }
103
-
104
- var executedOnLoaded = false;
105
-
106
- document.addEventListener("DOMContentLoaded", function() {
107
- var mutationObserver = new MutationObserver(function(m) {
108
- if (!executedOnLoaded && gradioApp().querySelector('#generate_button')) {
109
- executedOnLoaded = true;
110
- executeCallbacks(uiLoadedCallbacks);
111
- }
112
-
113
- executeCallbacks(uiUpdateCallbacks, m);
114
- scheduleAfterUiUpdateCallbacks();
115
- const newTab = get_uiCurrentTab();
116
- if (newTab && (newTab !== uiCurrentTab)) {
117
- uiCurrentTab = newTab;
118
- executeCallbacks(uiTabChangeCallbacks);
119
- }
120
- });
121
- mutationObserver.observe(gradioApp(), {childList: true, subtree: true});
122
- initStylePreviewOverlay();
123
- });
124
-
125
- /**
126
- * Add a ctrl+enter as a shortcut to start a generation
127
- */
128
- document.addEventListener('keydown', function(e) {
129
- const isModifierKey = (e.metaKey || e.ctrlKey || e.altKey);
130
- const isEnterKey = (e.key == "Enter" || e.keyCode == 13);
131
-
132
- if(isModifierKey && isEnterKey) {
133
- const generateButton = gradioApp().querySelector('button:not(.hidden)[id=generate_button]');
134
- if (generateButton) {
135
- generateButton.click();
136
- e.preventDefault();
137
- return;
138
- }
139
-
140
- const stopButton = gradioApp().querySelector('button:not(.hidden)[id=stop_button]')
141
- if(stopButton) {
142
- stopButton.click();
143
- e.preventDefault();
144
- return;
145
- }
146
- }
147
- });
148
-
149
- function initStylePreviewOverlay() {
150
- let overlayVisible = false;
151
- const samplesPath = document.querySelector("meta[name='samples-path']").getAttribute("content")
152
- const overlay = document.createElement('div');
153
- overlay.id = 'stylePreviewOverlay';
154
- document.body.appendChild(overlay);
155
- document.addEventListener('mouseover', function(e) {
156
- const label = e.target.closest('.style_selections label');
157
- if (!label) return;
158
- label.removeEventListener("mouseout", onMouseLeave);
159
- label.addEventListener("mouseout", onMouseLeave);
160
- overlayVisible = true;
161
- overlay.style.opacity = "1";
162
- const originalText = label.querySelector("span").getAttribute("data-original-text");
163
- const name = originalText || label.querySelector("span").textContent;
164
- overlay.style.backgroundImage = `url("${samplesPath.replace(
165
- "fooocus_v2",
166
- name.toLowerCase().replaceAll(" ", "_")
167
- ).replaceAll("\\", "\\\\")}")`;
168
- function onMouseLeave() {
169
- overlayVisible = false;
170
- overlay.style.opacity = "0";
171
- overlay.style.backgroundImage = "";
172
- label.removeEventListener("mouseout", onMouseLeave);
173
- }
174
- });
175
- document.addEventListener('mousemove', function(e) {
176
- if(!overlayVisible) return;
177
- overlay.style.left = `${e.clientX}px`;
178
- overlay.style.top = `${e.clientY}px`;
179
- overlay.className = e.clientY > window.innerHeight / 2 ? "lower-half" : "upper-half";
180
- });
181
- }
182
-
183
- /**
184
- * checks that a UI element is not in another hidden element or tab content
185
- */
186
- function uiElementIsVisible(el) {
187
- if (el === document) {
188
- return true;
189
- }
190
-
191
- const computedStyle = getComputedStyle(el);
192
- const isVisible = computedStyle.display !== 'none';
193
-
194
- if (!isVisible) return false;
195
- return uiElementIsVisible(el.parentNode);
196
- }
197
-
198
- function uiElementInSight(el) {
199
- const clRect = el.getBoundingClientRect();
200
- const windowHeight = window.innerHeight;
201
- const isOnScreen = clRect.bottom > 0 && clRect.top < windowHeight;
202
-
203
- return isOnScreen;
204
- }
205
-
206
- function playNotification() {
207
- gradioApp().querySelector('#audio_notification audio')?.play();
208
- }
209
-
210
- function set_theme(theme) {
211
- var gradioURL = window.location.href;
212
- if (!gradioURL.includes('?__theme=')) {
213
- window.location.replace(gradioURL + '?__theme=' + theme);
214
- }
215
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
javascript/viewer.js DELETED
@@ -1,88 +0,0 @@
1
- window.main_viewer_height = 512;
2
-
3
- function refresh_grid() {
4
- let gridContainer = document.querySelector('#final_gallery .grid-container');
5
- let final_gallery = document.getElementById('final_gallery');
6
-
7
- if (gridContainer) if (final_gallery) {
8
- let rect = final_gallery.getBoundingClientRect();
9
- let cols = Math.ceil((rect.width - 16.0) / rect.height);
10
- if (cols < 2) cols = 2;
11
- gridContainer.style.setProperty('--grid-cols', cols);
12
- }
13
- }
14
-
15
- function refresh_grid_delayed() {
16
- refresh_grid();
17
- setTimeout(refresh_grid, 100);
18
- setTimeout(refresh_grid, 500);
19
- setTimeout(refresh_grid, 1000);
20
- }
21
-
22
- function resized() {
23
- let windowHeight = window.innerHeight - 260;
24
- let elements = document.getElementsByClassName('main_view');
25
-
26
- if (windowHeight > 745) windowHeight = 745;
27
-
28
- for (let i = 0; i < elements.length; i++) {
29
- elements[i].style.height = windowHeight + 'px';
30
- }
31
-
32
- window.main_viewer_height = windowHeight;
33
-
34
- refresh_grid();
35
- }
36
-
37
- function viewer_to_top(delay = 100) {
38
- setTimeout(() => window.scrollTo({top: 0, behavior: 'smooth'}), delay);
39
- }
40
-
41
- function viewer_to_bottom(delay = 100) {
42
- let element = document.getElementById('positive_prompt');
43
- let yPos = window.main_viewer_height;
44
-
45
- if (element) {
46
- yPos = element.getBoundingClientRect().top + window.scrollY;
47
- }
48
-
49
- setTimeout(() => window.scrollTo({top: yPos - 8, behavior: 'smooth'}), delay);
50
- }
51
-
52
- window.addEventListener('resize', (e) => {
53
- resized();
54
- });
55
-
56
- onUiLoaded(async () => {
57
- resized();
58
- });
59
-
60
- function on_style_selection_blur() {
61
- let target = document.querySelector("#gradio_receiver_style_selections textarea");
62
- target.value = "on_style_selection_blur " + Math.random();
63
- let e = new Event("input", {bubbles: true})
64
- Object.defineProperty(e, "target", {value: target})
65
- target.dispatchEvent(e);
66
- }
67
-
68
- onUiLoaded(async () => {
69
- let spans = document.querySelectorAll('.aspect_ratios span');
70
-
71
- spans.forEach(function (span) {
72
- span.innerHTML = span.innerHTML.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
73
- });
74
-
75
- document.querySelector('.style_selections').addEventListener('focusout', function (event) {
76
- setTimeout(() => {
77
- if (!this.contains(document.activeElement)) {
78
- on_style_selection_blur();
79
- }
80
- }, 200);
81
- });
82
-
83
- let inputs = document.querySelectorAll('.lora_weight input[type="range"]');
84
-
85
- inputs.forEach(function (input) {
86
- input.style.marginTop = '12px';
87
- });
88
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
javascript/zoom.js DELETED
@@ -1,645 +0,0 @@
1
- onUiLoaded(async() => {
2
- // Helper functions
3
-
4
- // Detect whether the element has a horizontal scroll bar
5
- function hasHorizontalScrollbar(element) {
6
- return element.scrollWidth > element.clientWidth;
7
- }
8
-
9
- // Function for defining the "Ctrl", "Shift" and "Alt" keys
10
- function isModifierKey(event, key) {
11
- switch (key) {
12
- case "Ctrl":
13
- return event.ctrlKey;
14
- case "Shift":
15
- return event.shiftKey;
16
- case "Alt":
17
- return event.altKey;
18
- default:
19
- return false;
20
- }
21
- }
22
-
23
- // Create hotkey configuration with the provided options
24
- function createHotkeyConfig(defaultHotkeysConfig) {
25
- const result = {}; // Resulting hotkey configuration
26
- for (const key in defaultHotkeysConfig) {
27
- result[key] = defaultHotkeysConfig[key];
28
- }
29
- return result;
30
- }
31
-
32
- // Default config
33
- const defaultHotkeysConfig = {
34
- canvas_hotkey_zoom: "Shift",
35
- canvas_hotkey_adjust: "Ctrl",
36
- canvas_zoom_undo_extra_key: "Ctrl",
37
- canvas_zoom_hotkey_undo: "KeyZ",
38
- canvas_hotkey_reset: "KeyR",
39
- canvas_hotkey_fullscreen: "KeyS",
40
- canvas_hotkey_move: "KeyF",
41
- canvas_show_tooltip: true,
42
- canvas_auto_expand: true,
43
- canvas_blur_prompt: true,
44
- };
45
-
46
- // Loading the configuration from opts
47
- const hotkeysConfig = createHotkeyConfig(
48
- defaultHotkeysConfig
49
- );
50
-
51
- let isMoving = false;
52
- let activeElement;
53
-
54
- const elemData = {};
55
-
56
- function applyZoomAndPan(elemId) {
57
- const targetElement = gradioApp().querySelector(elemId);
58
-
59
- if (!targetElement) {
60
- console.log("Element not found");
61
- return;
62
- }
63
-
64
- targetElement.style.transformOrigin = "0 0";
65
-
66
- elemData[elemId] = {
67
- zoom: 1,
68
- panX: 0,
69
- panY: 0
70
- };
71
-
72
- let fullScreenMode = false;
73
-
74
- // Create tooltip
75
- function createTooltip() {
76
- const toolTipElemnt =
77
- targetElement.querySelector(".image-container");
78
- const tooltip = document.createElement("div");
79
- tooltip.className = "canvas-tooltip";
80
-
81
- // Creating an item of information
82
- const info = document.createElement("i");
83
- info.className = "canvas-tooltip-info";
84
- info.textContent = "";
85
-
86
- // Create a container for the contents of the tooltip
87
- const tooltipContent = document.createElement("div");
88
- tooltipContent.className = "canvas-tooltip-content";
89
-
90
- // Define an array with hotkey information and their actions
91
- const hotkeysInfo = [
92
- {
93
- configKey: "canvas_hotkey_zoom",
94
- action: "Zoom canvas",
95
- keySuffix: " + wheel"
96
- },
97
- {
98
- configKey: "canvas_hotkey_adjust",
99
- action: "Adjust brush size",
100
- keySuffix: " + wheel"
101
- },
102
- {configKey: "canvas_zoom_hotkey_undo", action: "Undo last action", keyPrefix: `${hotkeysConfig.canvas_zoom_undo_extra_key} + ` },
103
- {configKey: "canvas_hotkey_reset", action: "Reset zoom"},
104
- {
105
- configKey: "canvas_hotkey_fullscreen",
106
- action: "Fullscreen mode"
107
- },
108
- {configKey: "canvas_hotkey_move", action: "Move canvas"}
109
- ];
110
-
111
- // Create hotkeys array based on the config values
112
- const hotkeys = hotkeysInfo.map((info) => {
113
- const configValue = hotkeysConfig[info.configKey];
114
-
115
- let key = configValue.slice(-1);
116
-
117
- if (info.keySuffix) {
118
- key = `${configValue}${info.keySuffix}`;
119
- }
120
-
121
- if (info.keyPrefix && info.keyPrefix !== "None + ") {
122
- key = `${info.keyPrefix}${configValue[3]}`;
123
- }
124
-
125
- return {
126
- key,
127
- action: info.action,
128
- };
129
- });
130
-
131
- hotkeys
132
- .forEach(hotkey => {
133
- const p = document.createElement("p");
134
- p.innerHTML = `<b>${hotkey.key}</b> - ${hotkey.action}`;
135
- tooltipContent.appendChild(p);
136
- });
137
-
138
- tooltip.append(info, tooltipContent);
139
-
140
- // Add a hint element to the target element
141
- toolTipElemnt.appendChild(tooltip);
142
- }
143
-
144
- //Show tool tip if setting enable
145
- if (hotkeysConfig.canvas_show_tooltip) {
146
- createTooltip();
147
- }
148
-
149
- // Reset the zoom level and pan position of the target element to their initial values
150
- function resetZoom() {
151
- elemData[elemId] = {
152
- zoomLevel: 1,
153
- panX: 0,
154
- panY: 0
155
- };
156
-
157
- targetElement.style.overflow = "hidden";
158
-
159
- targetElement.isZoomed = false;
160
-
161
- targetElement.style.transform = `scale(${elemData[elemId].zoomLevel}) translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px)`;
162
-
163
- const canvas = gradioApp().querySelector(
164
- `${elemId} canvas[key="interface"]`
165
- );
166
-
167
- toggleOverlap("off");
168
- fullScreenMode = false;
169
-
170
- const closeBtn = targetElement.querySelector("button[aria-label='Remove Image']");
171
- if (closeBtn) {
172
- closeBtn.addEventListener("click", resetZoom);
173
- }
174
-
175
- if (canvas) {
176
- const parentElement = targetElement.closest('[id^="component-"]');
177
- if (
178
- canvas &&
179
- parseFloat(canvas.style.width) > parentElement.offsetWidth &&
180
- parseFloat(targetElement.style.width) > parentElement.offsetWidth
181
- ) {
182
- fitToElement();
183
- return;
184
- }
185
-
186
- }
187
-
188
- targetElement.style.width = "";
189
- }
190
-
191
- // Toggle the zIndex of the target element between two values, allowing it to overlap or be overlapped by other elements
192
- function toggleOverlap(forced = "") {
193
- const zIndex1 = "0";
194
- const zIndex2 = "998";
195
-
196
- targetElement.style.zIndex =
197
- targetElement.style.zIndex !== zIndex2 ? zIndex2 : zIndex1;
198
-
199
- if (forced === "off") {
200
- targetElement.style.zIndex = zIndex1;
201
- } else if (forced === "on") {
202
- targetElement.style.zIndex = zIndex2;
203
- }
204
- }
205
-
206
- // Adjust the brush size based on the deltaY value from a mouse wheel event
207
- function adjustBrushSize(
208
- elemId,
209
- deltaY,
210
- withoutValue = false,
211
- percentage = 5
212
- ) {
213
- const input =
214
- gradioApp().querySelector(
215
- `${elemId} input[aria-label='Brush radius']`
216
- ) ||
217
- gradioApp().querySelector(
218
- `${elemId} button[aria-label="Use brush"]`
219
- );
220
-
221
- if (input) {
222
- input.click();
223
- if (!withoutValue) {
224
- const maxValue =
225
- parseFloat(input.getAttribute("max")) || 100;
226
- const changeAmount = maxValue * (percentage / 100);
227
- const newValue =
228
- parseFloat(input.value) +
229
- (deltaY > 0 ? -changeAmount : changeAmount);
230
- input.value = Math.min(Math.max(newValue, 0), maxValue);
231
- input.dispatchEvent(new Event("change"));
232
- }
233
- }
234
- }
235
-
236
- // Reset zoom when uploading a new image
237
- const fileInput = gradioApp().querySelector(
238
- `${elemId} input[type="file"][accept="image/*"].svelte-116rqfv`
239
- );
240
- fileInput.addEventListener("click", resetZoom);
241
-
242
- // Update the zoom level and pan position of the target element based on the values of the zoomLevel, panX and panY variables
243
- function updateZoom(newZoomLevel, mouseX, mouseY) {
244
- newZoomLevel = Math.max(0.1, Math.min(newZoomLevel, 15));
245
-
246
- elemData[elemId].panX +=
247
- mouseX - (mouseX * newZoomLevel) / elemData[elemId].zoomLevel;
248
- elemData[elemId].panY +=
249
- mouseY - (mouseY * newZoomLevel) / elemData[elemId].zoomLevel;
250
-
251
- targetElement.style.transformOrigin = "0 0";
252
- targetElement.style.transform = `translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px) scale(${newZoomLevel})`;
253
- targetElement.style.overflow = "visible";
254
-
255
- toggleOverlap("on");
256
-
257
- return newZoomLevel;
258
- }
259
-
260
- // Change the zoom level based on user interaction
261
- function changeZoomLevel(operation, e) {
262
- if (isModifierKey(e, hotkeysConfig.canvas_hotkey_zoom)) {
263
- e.preventDefault();
264
-
265
- let zoomPosX, zoomPosY;
266
- let delta = 0.2;
267
-
268
- if (elemData[elemId].zoomLevel > 7) {
269
- delta = 0.9;
270
- } else if (elemData[elemId].zoomLevel > 2) {
271
- delta = 0.6;
272
- }
273
-
274
- zoomPosX = e.clientX;
275
- zoomPosY = e.clientY;
276
-
277
- fullScreenMode = false;
278
- elemData[elemId].zoomLevel = updateZoom(
279
- elemData[elemId].zoomLevel +
280
- (operation === "+" ? delta : -delta),
281
- zoomPosX - targetElement.getBoundingClientRect().left,
282
- zoomPosY - targetElement.getBoundingClientRect().top
283
- );
284
-
285
- targetElement.isZoomed = true;
286
- }
287
- }
288
-
289
- /**
290
- * This function fits the target element to the screen by calculating
291
- * the required scale and offsets. It also updates the global variables
292
- * zoomLevel, panX, and panY to reflect the new state.
293
- */
294
-
295
- function fitToElement() {
296
- //Reset Zoom
297
- targetElement.style.transform = `translate(${0}px, ${0}px) scale(${1})`;
298
-
299
- let parentElement;
300
-
301
- parentElement = targetElement.closest('[id^="component-"]');
302
-
303
- // Get element and screen dimensions
304
- const elementWidth = targetElement.offsetWidth;
305
- const elementHeight = targetElement.offsetHeight;
306
-
307
- const screenWidth = parentElement.clientWidth - 24;
308
- const screenHeight = parentElement.clientHeight;
309
-
310
- // Calculate scale and offsets
311
- const scaleX = screenWidth / elementWidth;
312
- const scaleY = screenHeight / elementHeight;
313
- const scale = Math.min(scaleX, scaleY);
314
-
315
- const offsetX =0;
316
- const offsetY =0;
317
-
318
- // Apply scale and offsets to the element
319
- targetElement.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`;
320
-
321
- // Update global variables
322
- elemData[elemId].zoomLevel = scale;
323
- elemData[elemId].panX = offsetX;
324
- elemData[elemId].panY = offsetY;
325
-
326
- fullScreenMode = false;
327
- toggleOverlap("off");
328
- }
329
-
330
- // Undo last action
331
- function undoLastAction(e) {
332
- let isCtrlPressed = isModifierKey(e, hotkeysConfig.canvas_zoom_undo_extra_key)
333
- const isAuxButton = e.button >= 3;
334
-
335
- if (isAuxButton) {
336
- isCtrlPressed = true
337
- } else {
338
- if (!isModifierKey(e, hotkeysConfig.canvas_zoom_undo_extra_key)) return;
339
- }
340
-
341
- // Move undoBtn query outside the if statement to avoid unnecessary queries
342
- const undoBtn = document.querySelector(`${activeElement} button[aria-label="Undo"]`);
343
-
344
- if ((isCtrlPressed) && undoBtn ) {
345
- e.preventDefault();
346
- undoBtn.click();
347
- }
348
- }
349
-
350
- /**
351
- * This function fits the target element to the screen by calculating
352
- * the required scale and offsets. It also updates the global variables
353
- * zoomLevel, panX, and panY to reflect the new state.
354
- */
355
-
356
- // Fullscreen mode
357
- function fitToScreen() {
358
- const canvas = gradioApp().querySelector(
359
- `${elemId} canvas[key="interface"]`
360
- );
361
-
362
- if (!canvas) return;
363
-
364
- targetElement.style.width = (canvas.offsetWidth + 2) + "px";
365
- targetElement.style.overflow = "visible";
366
-
367
- if (fullScreenMode) {
368
- resetZoom();
369
- fullScreenMode = false;
370
- return;
371
- }
372
-
373
- //Reset Zoom
374
- targetElement.style.transform = `translate(${0}px, ${0}px) scale(${1})`;
375
-
376
- // Get scrollbar width to right-align the image
377
- const scrollbarWidth =
378
- window.innerWidth - document.documentElement.clientWidth;
379
-
380
- // Get element and screen dimensions
381
- const elementWidth = targetElement.offsetWidth;
382
- const elementHeight = targetElement.offsetHeight;
383
- const screenWidth = window.innerWidth - scrollbarWidth;
384
- const screenHeight = window.innerHeight;
385
-
386
- // Get element's coordinates relative to the page
387
- const elementRect = targetElement.getBoundingClientRect();
388
- const elementY = elementRect.y;
389
- const elementX = elementRect.x;
390
-
391
- // Calculate scale and offsets
392
- const scaleX = screenWidth / elementWidth;
393
- const scaleY = screenHeight / elementHeight;
394
- const scale = Math.min(scaleX, scaleY);
395
-
396
- // Get the current transformOrigin
397
- const computedStyle = window.getComputedStyle(targetElement);
398
- const transformOrigin = computedStyle.transformOrigin;
399
- const [originX, originY] = transformOrigin.split(" ");
400
- const originXValue = parseFloat(originX);
401
- const originYValue = parseFloat(originY);
402
-
403
- // Calculate offsets with respect to the transformOrigin
404
- const offsetX =
405
- (screenWidth - elementWidth * scale) / 2 -
406
- elementX -
407
- originXValue * (1 - scale);
408
- const offsetY =
409
- (screenHeight - elementHeight * scale) / 2 -
410
- elementY -
411
- originYValue * (1 - scale);
412
-
413
- // Apply scale and offsets to the element
414
- targetElement.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(${scale})`;
415
-
416
- // Update global variables
417
- elemData[elemId].zoomLevel = scale;
418
- elemData[elemId].panX = offsetX;
419
- elemData[elemId].panY = offsetY;
420
-
421
- fullScreenMode = true;
422
- toggleOverlap("on");
423
- }
424
-
425
- // Handle keydown events
426
- function handleKeyDown(event) {
427
- // Disable key locks to make pasting from the buffer work correctly
428
- if ((event.ctrlKey && event.code === 'KeyV') || (event.ctrlKey && event.code === 'KeyC') || event.code === "F5") {
429
- return;
430
- }
431
-
432
- // before activating shortcut, ensure user is not actively typing in an input field
433
- if (!hotkeysConfig.canvas_blur_prompt) {
434
- if (event.target.nodeName === 'TEXTAREA' || event.target.nodeName === 'INPUT') {
435
- return;
436
- }
437
- }
438
-
439
- const hotkeyActions = {
440
- [hotkeysConfig.canvas_hotkey_reset]: resetZoom,
441
- [hotkeysConfig.canvas_hotkey_overlap]: toggleOverlap,
442
- [hotkeysConfig.canvas_hotkey_fullscreen]: fitToScreen,
443
- [hotkeysConfig.canvas_zoom_hotkey_undo]: undoLastAction,
444
- };
445
-
446
- const action = hotkeyActions[event.code];
447
- if (action) {
448
- event.preventDefault();
449
- action(event);
450
- }
451
-
452
- if (
453
- isModifierKey(event, hotkeysConfig.canvas_hotkey_zoom) ||
454
- isModifierKey(event, hotkeysConfig.canvas_hotkey_adjust)
455
- ) {
456
- event.preventDefault();
457
- }
458
- }
459
-
460
- // Get Mouse position
461
- function getMousePosition(e) {
462
- mouseX = e.offsetX;
463
- mouseY = e.offsetY;
464
- }
465
-
466
- // Simulation of the function to put a long image into the screen.
467
- // We detect if an image has a scroll bar or not, make a fullscreen to reveal the image, then reduce it to fit into the element.
468
- // We hide the image and show it to the user when it is ready.
469
-
470
- targetElement.isExpanded = false;
471
- function autoExpand() {
472
- const canvas = document.querySelector(`${elemId} canvas[key="interface"]`);
473
- if (canvas) {
474
- if (hasHorizontalScrollbar(targetElement) && targetElement.isExpanded === false) {
475
- targetElement.style.visibility = "hidden";
476
- setTimeout(() => {
477
- fitToScreen();
478
- resetZoom();
479
- targetElement.style.visibility = "visible";
480
- targetElement.isExpanded = true;
481
- }, 10);
482
- }
483
- }
484
- }
485
-
486
- targetElement.addEventListener("mousemove", getMousePosition);
487
- targetElement.addEventListener("auxclick", undoLastAction);
488
-
489
- //observers
490
- // Creating an observer with a callback function to handle DOM changes
491
- const observer = new MutationObserver((mutationsList, observer) => {
492
- for (let mutation of mutationsList) {
493
- // If the style attribute of the canvas has changed, by observation it happens only when the picture changes
494
- if (mutation.type === 'attributes' && mutation.attributeName === 'style' &&
495
- mutation.target.tagName.toLowerCase() === 'canvas') {
496
- targetElement.isExpanded = false;
497
- setTimeout(resetZoom, 10);
498
- }
499
- }
500
- });
501
-
502
- // Apply auto expand if enabled
503
- if (hotkeysConfig.canvas_auto_expand) {
504
- targetElement.addEventListener("mousemove", autoExpand);
505
- // Set up an observer to track attribute changes
506
- observer.observe(targetElement, { attributes: true, childList: true, subtree: true });
507
- }
508
-
509
- // Handle events only inside the targetElement
510
- let isKeyDownHandlerAttached = false;
511
-
512
- function handleMouseMove() {
513
- if (!isKeyDownHandlerAttached) {
514
- document.addEventListener("keydown", handleKeyDown);
515
- isKeyDownHandlerAttached = true;
516
-
517
- activeElement = elemId;
518
- }
519
- }
520
-
521
- function handleMouseLeave() {
522
- if (isKeyDownHandlerAttached) {
523
- document.removeEventListener("keydown", handleKeyDown);
524
- isKeyDownHandlerAttached = false;
525
-
526
- activeElement = null;
527
- }
528
- }
529
-
530
- // Add mouse event handlers
531
- targetElement.addEventListener("mousemove", handleMouseMove);
532
- targetElement.addEventListener("mouseleave", handleMouseLeave);
533
-
534
- targetElement.addEventListener("wheel", e => {
535
- // change zoom level
536
- const operation = e.deltaY > 0 ? "-" : "+";
537
- changeZoomLevel(operation, e);
538
-
539
- // Handle brush size adjustment with ctrl key pressed
540
- if (isModifierKey(e, hotkeysConfig.canvas_hotkey_adjust)) {
541
- e.preventDefault();
542
-
543
- // Increase or decrease brush size based on scroll direction
544
- adjustBrushSize(elemId, e.deltaY);
545
- }
546
- });
547
-
548
- // Handle the move event for pan functionality. Updates the panX and panY variables and applies the new transform to the target element.
549
- function handleMoveKeyDown(e) {
550
-
551
- // Disable key locks to make pasting from the buffer work correctly
552
- if ((e.ctrlKey && e.code === 'KeyV') || (e.ctrlKey && e.code === 'KeyC') || e.code === "F5") {
553
- return;
554
- }
555
-
556
- // before activating shortcut, ensure user is not actively typing in an input field
557
- if (!hotkeysConfig.canvas_blur_prompt) {
558
- if (e.target.nodeName === 'TEXTAREA' || e.target.nodeName === 'INPUT') {
559
- return;
560
- }
561
- }
562
-
563
-
564
- if (e.code === hotkeysConfig.canvas_hotkey_move) {
565
- if (!e.ctrlKey && !e.metaKey && isKeyDownHandlerAttached) {
566
- e.preventDefault();
567
- document.activeElement.blur();
568
- isMoving = true;
569
- }
570
- }
571
- }
572
-
573
- function handleMoveKeyUp(e) {
574
- if (e.code === hotkeysConfig.canvas_hotkey_move) {
575
- isMoving = false;
576
- }
577
- }
578
-
579
- document.addEventListener("keydown", handleMoveKeyDown);
580
- document.addEventListener("keyup", handleMoveKeyUp);
581
-
582
- // Detect zoom level and update the pan speed.
583
- function updatePanPosition(movementX, movementY) {
584
- let panSpeed = 2;
585
-
586
- if (elemData[elemId].zoomLevel > 8) {
587
- panSpeed = 3.5;
588
- }
589
-
590
- elemData[elemId].panX += movementX * panSpeed;
591
- elemData[elemId].panY += movementY * panSpeed;
592
-
593
- // Delayed redraw of an element
594
- requestAnimationFrame(() => {
595
- targetElement.style.transform = `translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px) scale(${elemData[elemId].zoomLevel})`;
596
- toggleOverlap("on");
597
- });
598
- }
599
-
600
- function handleMoveByKey(e) {
601
- if (isMoving && elemId === activeElement) {
602
- updatePanPosition(e.movementX, e.movementY);
603
- targetElement.style.pointerEvents = "none";
604
- targetElement.style.overflow = "visible";
605
- } else {
606
- targetElement.style.pointerEvents = "auto";
607
- }
608
- }
609
-
610
- // Prevents sticking to the mouse
611
- window.onblur = function() {
612
- isMoving = false;
613
- };
614
-
615
- // Checks for extension
616
- function checkForOutBox() {
617
- const parentElement = targetElement.closest('[id^="component-"]');
618
- if (parentElement.offsetWidth < targetElement.offsetWidth && !targetElement.isExpanded) {
619
- resetZoom();
620
- targetElement.isExpanded = true;
621
- }
622
-
623
- if (parentElement.offsetWidth < targetElement.offsetWidth && elemData[elemId].zoomLevel == 1) {
624
- resetZoom();
625
- }
626
-
627
- if (parentElement.offsetWidth < targetElement.offsetWidth && targetElement.offsetWidth * elemData[elemId].zoomLevel > parentElement.offsetWidth && elemData[elemId].zoomLevel < 1 && !targetElement.isZoomed) {
628
- resetZoom();
629
- }
630
- }
631
-
632
- targetElement.addEventListener("mousemove", checkForOutBox);
633
-
634
- window.addEventListener('resize', (e) => {
635
- resetZoom();
636
-
637
- targetElement.isExpanded = false;
638
- targetElement.isZoomed = false;
639
- });
640
-
641
- gradioApp().addEventListener("mousemove", handleMoveByKey);
642
- }
643
-
644
- applyZoomAndPan("#inpaint_canvas");
645
- });