From 0cc05fc492a9360d3b2f1b3f64c7d74f9041f74e Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Sun, 21 May 2023 00:41:41 +0300 Subject: work on startup profile display --- javascript/profilerVisualization.js | 91 +++++++++++++++++++++++++++++++++++++ javascript/ui_settings_hints.js | 2 +- 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 javascript/profilerVisualization.js (limited to 'javascript') diff --git a/javascript/profilerVisualization.js b/javascript/profilerVisualization.js new file mode 100644 index 00000000..1bd75986 --- /dev/null +++ b/javascript/profilerVisualization.js @@ -0,0 +1,91 @@ + +function createRow(table, cellName, items) { + var tr = document.createElement('tr'); + var res = []; + + items.forEach(function(x) { + var td = document.createElement(cellName); + td.textContent = x; + tr.appendChild(td); + res.push(td); + }); + + table.appendChild(tr); + + return res; +} + +function showProfile(path, cutoff = 0.0005) { + requestGet(path, {}, function(data) { + var table = document.createElement('table'); + table.className = 'popup-table'; + + data.records['total'] = data.total; + var keys = Object.keys(data.records).sort(function(a, b) { + return data.records[b] - data.records[a]; + }); + var items = keys.map(function(x) { + return {key: x, parts: x.split('/'), time: data.records[x]}; + }); + var maxLength = items.reduce(function(a, b) { + return Math.max(a, b.parts.length); + }, 0); + + var cols = createRow(table, 'th', ['record', 'seconds']); + cols[0].colSpan = maxLength; + + function arraysEqual(a, b) { + return !(a < b || b < a); + } + + var addLevel = function(level, parent) { + var matching = items.filter(function(x) { + return x.parts[level] && !x.parts[level + 1] && arraysEqual(x.parts.slice(0, level), parent); + }); + var sorted = matching.sort(function(a, b) { + return b.time - a.time; + }); + var othersTime = 0; + var othersList = []; + sorted.forEach(function(x) { + if (x.time < cutoff) { + othersTime += x.time; + othersList.push(x.parts[level]); + return; + } + + var cells = []; + for (var i = 0; i < maxLength; i++) { + cells.push(x.parts[i]); + } + cells.push(x.time.toFixed(3)); + var cols = createRow(table, 'td', cells); + for (i = 0; i < level; i++) { + cols[i].className = 'muted'; + } + + addLevel(level + 1, parent.concat([x.parts[level]])); + }); + + if (othersTime > 0) { + var cells = []; + for (var i = 0; i < maxLength; i++) { + cells.push(parent[i]); + } + cells.push(othersTime.toFixed(3)); + var cols = createRow(table, 'td', cells); + for (i = 0; i < level; i++) { + cols[i].className = 'muted'; + } + + cols[level].textContent = 'others'; + cols[level].title = othersList.join(", "); + } + }; + + addLevel(0, []); + + popup(table); + }); +} + diff --git a/javascript/ui_settings_hints.js b/javascript/ui_settings_hints.js index e216852b..d088f949 100644 --- a/javascript/ui_settings_hints.js +++ b/javascript/ui_settings_hints.js @@ -42,7 +42,7 @@ onOptionsChanged(function() { function settingsHintsShowQuicksettings() { requestGet("./internal/quicksettings-hint", {}, function(data) { var table = document.createElement('table'); - table.className = 'settings-value-table'; + table.className = 'popup-table'; data.forEach(function(obj) { var tr = document.createElement('tr'); -- cgit v1.2.1 From 5ed970b94972004961ecada3bc1c936ef6017f3c Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Sun, 21 May 2023 23:16:14 +0300 Subject: Move token counters to separate JS file, fix names --- javascript/token-counters.js | 75 ++++++++++++++++++++++++++++++++++++++++++++ javascript/ui.js | 71 +---------------------------------------- 2 files changed, 76 insertions(+), 70 deletions(-) create mode 100644 javascript/token-counters.js (limited to 'javascript') diff --git a/javascript/token-counters.js b/javascript/token-counters.js new file mode 100644 index 00000000..0b74658c --- /dev/null +++ b/javascript/token-counters.js @@ -0,0 +1,75 @@ +let promptTokenCountDebounceTime = 800; +let promptTokenCountTimeouts = {}; +var promptTokenCountUpdateFunctions = {}; + +function update_txt2img_tokens(...args) { + // Called from Gradio + update_token_counter("txt2img_token_button"); + if (args.length == 2) { + return args[0]; + } + return args; +} + +function update_img2img_tokens(...args) { + // Called from Gradio + update_token_counter("img2img_token_button"); + if (args.length == 2) { + return args[0]; + } + return args; +} + +function update_token_counter(button_id) { + if (promptTokenCountTimeouts[button_id]) { + clearTimeout(promptTokenCountTimeouts[button_id]); + } + promptTokenCountTimeouts[button_id] = setTimeout( + () => gradioApp().getElementById(button_id)?.click(), + promptTokenCountDebounceTime, + ); +} + + +function recalculatePromptTokens(name) { + promptTokenCountUpdateFunctions[name]?.(); +} + +function recalculate_prompts_txt2img() { + // Called from Gradio + recalculatePromptTokens('txt2img_prompt'); + recalculatePromptTokens('txt2img_neg_prompt'); + return Array.from(arguments); +} + +function recalculate_prompts_img2img() { + // Called from Gradio + recalculatePromptTokens('img2img_prompt'); + recalculatePromptTokens('img2img_neg_prompt'); + return Array.from(arguments); +} + +function setupTokenCounting(id, id_counter, id_button) { + var prompt = gradioApp().getElementById(id); + var counter = gradioApp().getElementById(id_counter); + var textarea = gradioApp().querySelector(`#${id} > label > textarea`); + + if (counter.parentElement == prompt.parentElement) { + return; + } + + prompt.parentElement.insertBefore(counter, prompt); + prompt.parentElement.style.position = "relative"; + + promptTokenCountUpdateFunctions[id] = function() { + update_token_counter(id_button); + }; + textarea.addEventListener("input", promptTokenCountUpdateFunctions[id]); +} + +function setupTokenCounters() { + setupTokenCounting('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button'); + setupTokenCounting('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button'); + setupTokenCounting('img2img_prompt', 'img2img_token_counter', 'img2img_token_button'); + setupTokenCounting('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button'); +} diff --git a/javascript/ui.js b/javascript/ui.js index 648a5290..800a2ae6 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -248,27 +248,6 @@ function confirm_clear_prompt(prompt, negative_prompt) { } -var promptTokecountUpdateFuncs = {}; - -function recalculatePromptTokens(name) { - if (promptTokecountUpdateFuncs[name]) { - promptTokecountUpdateFuncs[name](); - } -} - -function recalculate_prompts_txt2img() { - recalculatePromptTokens('txt2img_prompt'); - recalculatePromptTokens('txt2img_neg_prompt'); - return Array.from(arguments); -} - -function recalculate_prompts_img2img() { - recalculatePromptTokens('img2img_prompt'); - recalculatePromptTokens('img2img_neg_prompt'); - return Array.from(arguments); -} - - var opts = {}; onUiUpdate(function() { if (Object.keys(opts).length != 0) return; @@ -302,28 +281,7 @@ onUiUpdate(function() { json_elem.parentElement.style.display = "none"; - function registerTextarea(id, id_counter, id_button) { - var prompt = gradioApp().getElementById(id); - var counter = gradioApp().getElementById(id_counter); - var textarea = gradioApp().querySelector("#" + id + " > label > textarea"); - - if (counter.parentElement == prompt.parentElement) { - return; - } - - prompt.parentElement.insertBefore(counter, prompt); - prompt.parentElement.style.position = "relative"; - - promptTokecountUpdateFuncs[id] = function() { - update_token_counter(id_button); - }; - textarea.addEventListener("input", promptTokecountUpdateFuncs[id]); - } - - registerTextarea('txt2img_prompt', 'txt2img_token_counter', 'txt2img_token_button'); - registerTextarea('txt2img_neg_prompt', 'txt2img_negative_token_counter', 'txt2img_negative_token_button'); - registerTextarea('img2img_prompt', 'img2img_token_counter', 'img2img_token_button'); - registerTextarea('img2img_neg_prompt', 'img2img_negative_token_counter', 'img2img_negative_token_button'); + setupTokenCounters(); var show_all_pages = gradioApp().getElementById('settings_show_all_pages'); var settings_tabs = gradioApp().querySelector('#settings div'); @@ -354,33 +312,6 @@ onOptionsChanged(function() { }); let txt2img_textarea, img2img_textarea = undefined; -let wait_time = 800; -let token_timeouts = {}; - -function update_txt2img_tokens(...args) { - update_token_counter("txt2img_token_button"); - if (args.length == 2) { - return args[0]; - } - return args; -} - -function update_img2img_tokens(...args) { - update_token_counter( - "img2img_token_button" - ); - if (args.length == 2) { - return args[0]; - } - return args; -} - -function update_token_counter(button_id) { - if (token_timeouts[button_id]) { - clearTimeout(token_timeouts[button_id]); - } - token_timeouts[button_id] = setTimeout(() => gradioApp().getElementById(button_id)?.click(), wait_time); -} function restart_reload() { document.body.innerHTML = '

Reloading...

'; -- cgit v1.2.1 From 618c59b01d8b90794df0aea625de1c1d5d94d407 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Sun, 21 May 2023 23:20:50 +0300 Subject: Add option to disable prompt token counters --- javascript/token-counters.js | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'javascript') diff --git a/javascript/token-counters.js b/javascript/token-counters.js index 0b74658c..9d81a723 100644 --- a/javascript/token-counters.js +++ b/javascript/token-counters.js @@ -21,6 +21,9 @@ function update_img2img_tokens(...args) { } function update_token_counter(button_id) { + if (opts.disable_token_counters) { + return; + } if (promptTokenCountTimeouts[button_id]) { clearTimeout(promptTokenCountTimeouts[button_id]); } @@ -54,6 +57,11 @@ function setupTokenCounting(id, id_counter, id_button) { var counter = gradioApp().getElementById(id_counter); var textarea = gradioApp().querySelector(`#${id} > label > textarea`); + if (opts.disable_token_counters) { + counter.style.display = "none"; + return; + } + if (counter.parentElement == prompt.parentElement) { return; } -- cgit v1.2.1 From a862428902c4aecde8852761c3a4d95c196885cb Mon Sep 17 00:00:00 2001 From: missionfloyd Date: Sun, 21 May 2023 18:17:32 -0600 Subject: Fix dragging text to prompt --- javascript/dragdrop.js | 4 ++-- javascript/imageParams.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'javascript') diff --git a/javascript/dragdrop.js b/javascript/dragdrop.js index fe008924..90cdd507 100644 --- a/javascript/dragdrop.js +++ b/javascript/dragdrop.js @@ -51,7 +51,7 @@ function dropReplaceImage( imgWrap, files ) { window.document.addEventListener('dragover', e => { const target = e.composedPath()[0]; const imgWrap = target.closest('[data-testid="image"]'); - if ( !imgWrap && target.placeholder && target.placeholder.indexOf("Prompt") == -1) { + if (e.dataTransfer.files.length == 0 || (!imgWrap && target.placeholder && target.placeholder.indexOf("Prompt") == -1)) { return; } e.stopPropagation(); @@ -61,7 +61,7 @@ window.document.addEventListener('dragover', e => { window.document.addEventListener('drop', e => { const target = e.composedPath()[0]; - if (target.placeholder.indexOf("Prompt") == -1) { + if (e.dataTransfer.files.length == 0 || target.placeholder.indexOf("Prompt") == -1) { return; } const imgWrap = target.closest('[data-testid="image"]'); diff --git a/javascript/imageParams.js b/javascript/imageParams.js index 64aee93b..ed0df939 100644 --- a/javascript/imageParams.js +++ b/javascript/imageParams.js @@ -1,7 +1,7 @@ window.onload = (function(){ window.addEventListener('drop', e => { const target = e.composedPath()[0]; - if (target.placeholder.indexOf("Prompt") == -1) return; + if (e.dataTransfer.files.length == 0 || target.placeholder.indexOf("Prompt") == -1) return; let prompt_target = get_tab_index('tabs') == 1 ? "img2img_prompt_image" : "txt2img_prompt_image"; -- cgit v1.2.1 From ee65e729319e4184fc0d49552657e98aa0e28f17 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 22 May 2023 09:49:51 +0300 Subject: repair file paste for Firefox from #10615 remove animation when pasting files into prompt rework two dragdrop js files into one --- javascript/dragdrop.js | 53 ++++++++++++++++++++++++++++++++++++----------- javascript/imageParams.js | 18 ---------------- 2 files changed, 41 insertions(+), 30 deletions(-) delete mode 100644 javascript/imageParams.js (limited to 'javascript') diff --git a/javascript/dragdrop.js b/javascript/dragdrop.js index fd6b3154..aa79871a 100644 --- a/javascript/dragdrop.js +++ b/javascript/dragdrop.js @@ -48,12 +48,27 @@ function dropReplaceImage(imgWrap, files) { } } +function eventHasFiles(e) { + if (!e.dataTransfer || !e.dataTransfer.files) return false; + if (e.dataTransfer.files.length > 0) return true; + if (e.dataTransfer.items.length > 0 && e.dataTransfer.items[0].kind == "file") return true; + + return false; +} + +function dragDropTargetIsPrompt(target) { + if (!(target?.placeholder?.indexOf("Prompt") >= 0)) return true; + if (target?.parentNode?.parentNode) return true; + return false; +} + window.document.addEventListener('dragover', e => { const target = e.composedPath()[0]; - const imgWrap = target.closest('[data-testid="image"]'); - if (e.dataTransfer.files.length == 0 || (!imgWrap && target.placeholder && target.placeholder.indexOf("Prompt") == -1)) { - return; - } + if (!eventHasFiles(e)) return; + + var targetImage = target.closest('[data-testid="image"]'); + if (!dragDropTargetIsPrompt(target) && !targetImage) return; + e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; @@ -61,17 +76,31 @@ window.document.addEventListener('dragover', e => { window.document.addEventListener('drop', e => { const target = e.composedPath()[0]; - if (e.dataTransfer.files.length == 0 || target.placeholder.indexOf("Prompt") == -1) { - return; + if (!eventHasFiles(e)) return; + + if (dragDropTargetIsPrompt(target)) { + e.stopPropagation(); + e.preventDefault(); + + let prompt_target = get_tab_index('tabs') == 1 ? "img2img_prompt_image" : "txt2img_prompt_image"; + + const imgParent = gradioApp().getElementById(prompt_target); + const files = e.dataTransfer.files; + const fileInput = imgParent.querySelector('input[type="file"]'); + if (fileInput) { + fileInput.files = files; + fileInput.dispatchEvent(new Event('change')); + } } - const imgWrap = target.closest('[data-testid="image"]'); - if (!imgWrap) { + + var targetImage = target.closest('[data-testid="image"]'); + if (targetImage) { + e.stopPropagation(); + e.preventDefault(); + const files = e.dataTransfer.files; + dropReplaceImage(targetImage, files); return; } - e.stopPropagation(); - e.preventDefault(); - const files = e.dataTransfer.files; - dropReplaceImage(imgWrap, files); }); window.addEventListener('paste', e => { diff --git a/javascript/imageParams.js b/javascript/imageParams.js deleted file mode 100644 index 0cdd717a..00000000 --- a/javascript/imageParams.js +++ /dev/null @@ -1,18 +0,0 @@ -window.onload = (function() { - window.addEventListener('drop', e => { - const target = e.composedPath()[0]; - if (e.dataTransfer.files.length == 0 || target.placeholder.indexOf("Prompt") == -1) return; - - let prompt_target = get_tab_index('tabs') == 1 ? "img2img_prompt_image" : "txt2img_prompt_image"; - - e.stopPropagation(); - e.preventDefault(); - const imgParent = gradioApp().getElementById(prompt_target); - const files = e.dataTransfer.files; - const fileInput = imgParent.querySelector('input[type="file"]'); - if (fileInput) { - fileInput.files = files; - fileInput.dispatchEvent(new Event('change')); - } - }); -}); -- cgit v1.2.1 From cc2f6e3b7b8d720a8e0fb2732751e34b7f41c2e9 Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Mon, 22 May 2023 15:40:10 +0300 Subject: fix error in dragdrop logic --- javascript/dragdrop.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'javascript') diff --git a/javascript/dragdrop.js b/javascript/dragdrop.js index aa79871a..5803daea 100644 --- a/javascript/dragdrop.js +++ b/javascript/dragdrop.js @@ -57,8 +57,8 @@ function eventHasFiles(e) { } function dragDropTargetIsPrompt(target) { - if (!(target?.placeholder?.indexOf("Prompt") >= 0)) return true; - if (target?.parentNode?.parentNode) return true; + if (target?.placeholder && target?.placeholder.indexOf("Prompt") >= 0) return true; + if (target?.parentNode?.parentNode?.className?.indexOf("prompt") > 0) return true; return false; } -- cgit v1.2.1 From d66c64b9d76553a9518ae6a3141714519d65d796 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 24 May 2023 20:19:16 +0300 Subject: Optimize tooltip checks * Instead of traversing tens of thousands of text nodes, only look at elements and their children * Debounce the checks to happen only every one second --- javascript/hints.js | 61 +++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 28 deletions(-) (limited to 'javascript') diff --git a/javascript/hints.js b/javascript/hints.js index 46f342cb..a8c72976 100644 --- a/javascript/hints.js +++ b/javascript/hints.js @@ -116,17 +116,17 @@ var titles = { "Negative Guidance minimum sigma": "Skip negative prompt for steps where image is already mostly denoised; the higher this value, the more skips there will be; provides increased performance in exchange for minor quality reduction." }; -function updateTooltipForSpan(span) { - if (span.title) return; // already has a title +function updateTooltip(element) { + if (element.title) return; // already has a title - let tooltip = localization[titles[span.textContent]] || titles[span.textContent]; + let tooltip = localization[titles[element.textContent]] || titles[element.textContent]; if (!tooltip) { - tooltip = localization[titles[span.value]] || titles[span.value]; + tooltip = localization[titles[element.value]] || titles[element.value]; } if (!tooltip) { - for (const c of span.classList) { + for (const c of element.classList) { if (c in titles) { tooltip = localization[titles[c]] || titles[c]; break; @@ -135,34 +135,39 @@ function updateTooltipForSpan(span) { } if (tooltip) { - span.title = tooltip; + element.title = tooltip; } } -function updateTooltipForSelect(select) { - if (select.onchange != null) return; +// Nodes to check for adding tooltips. +const tooltipCheckNodes = new Set(); +// Timer for debouncing tooltip check. +let tooltipCheckTimer = null; - select.onchange = function() { - select.title = localization[titles[select.value]] || titles[select.value] || ""; - }; +function processTooltipCheckNodes() { + for (const node of tooltipCheckNodes) { + updateTooltip(node); + } + tooltipCheckNodes.clear(); } -var observedTooltipElements = {SPAN: 1, BUTTON: 1, SELECT: 1, P: 1}; - -onUiUpdate(function(m) { - m.forEach(function(record) { - record.addedNodes.forEach(function(node) { - if (observedTooltipElements[node.tagName]) { - updateTooltipForSpan(node); - } - if (node.tagName == "SELECT") { - updateTooltipForSelect(node); - } - - if (node.querySelectorAll) { - node.querySelectorAll('span, button, select, p').forEach(updateTooltipForSpan); - node.querySelectorAll('select').forEach(updateTooltipForSelect); +onUiUpdate(function(mutationRecords) { + for (const record of mutationRecords) { + for (const node of record.addedNodes) { + if (node.nodeType === Node.ELEMENT_NODE && !node.classList.contains("hide")) { + if ( + node.tagName === "SPAN" || + node.tagName === "BUTTON" || + node.tagName === "P" + ) { + tooltipCheckNodes.add(node); + } + node.querySelectorAll('span, button, p').forEach(n => tooltipCheckNodes.add(n)); } - }); - }); + } + } + if (tooltipCheckNodes.size) { + clearTimeout(tooltipCheckTimer); + tooltipCheckTimer = setTimeout(processTooltipCheckNodes, 1000); + } }); -- cgit v1.2.1 From b82d4a65fe9b025e9da1b8c7a72ed9d56b96315d Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 24 May 2023 20:34:57 +0300 Subject: Restore support for dropdown tooltips --- javascript/hints.js | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'javascript') diff --git a/javascript/hints.js b/javascript/hints.js index a8c72976..7f8885bc 100644 --- a/javascript/hints.js +++ b/javascript/hints.js @@ -153,14 +153,27 @@ function processTooltipCheckNodes() { onUiUpdate(function(mutationRecords) { for (const record of mutationRecords) { + if (record.type === "childList" && record.target.classList.contains("options")) { + // This smells like a Gradio dropdown menu having changed, + // so let's enqueue an update for the input element that shows the current value. + let wrap = record.target.parentNode; + let input = wrap?.querySelector("input"); + if (input) { + input.title = ""; // So we'll even have a chance to update it. + tooltipCheckNodes.add(input); + } + } for (const node of record.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE && !node.classList.contains("hide")) { - if ( - node.tagName === "SPAN" || - node.tagName === "BUTTON" || - node.tagName === "P" - ) { - tooltipCheckNodes.add(node); + if (!node.title) { + if ( + node.tagName === "SPAN" || + node.tagName === "BUTTON" || + node.tagName === "P" || + node.tagName === "INPUT" + ) { + tooltipCheckNodes.add(node); + } } node.querySelectorAll('span, button, p').forEach(n => tooltipCheckNodes.add(n)); } -- cgit v1.2.1 From 32b0f7c9bbb908b870c2e0d488bd63a9c71ba078 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Wed, 24 May 2023 20:45:05 +0300 Subject: Add support for tooltips on dropdown options --- javascript/hints.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'javascript') diff --git a/javascript/hints.js b/javascript/hints.js index 7f8885bc..05ae5f22 100644 --- a/javascript/hints.js +++ b/javascript/hints.js @@ -119,10 +119,18 @@ var titles = { function updateTooltip(element) { if (element.title) return; // already has a title - let tooltip = localization[titles[element.textContent]] || titles[element.textContent]; + let text = element.textContent; + let tooltip = localization[titles[text]] || titles[text]; if (!tooltip) { - tooltip = localization[titles[element.value]] || titles[element.value]; + let value = element.value; + if (value) tooltip = localization[titles[value]] || titles[value]; + } + + if (!tooltip) { + // Gradio dropdown options have `data-value`. + let dataValue = element.dataset.value; + if (dataValue) tooltip = localization[titles[dataValue]] || titles[dataValue]; } if (!tooltip) { @@ -170,7 +178,8 @@ onUiUpdate(function(mutationRecords) { node.tagName === "SPAN" || node.tagName === "BUTTON" || node.tagName === "P" || - node.tagName === "INPUT" + node.tagName === "INPUT" || + (node.tagName === "LI" && node.classList.contains("item")) // Gradio dropdown item ) { tooltipCheckNodes.add(node); } -- cgit v1.2.1 From dc7a1bbb1c70ba7585ca64c0a96e1bcba4d2302f Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 25 May 2023 09:09:13 +0300 Subject: Use onAfterUiUpdate where possible --- javascript/aspectRatioOverlay.js | 2 +- javascript/contextMenus.js | 4 +--- javascript/generationParams.js | 2 +- javascript/imageMaskFix.js | 2 +- javascript/imageviewer.js | 2 +- javascript/notification.js | 2 +- javascript/ui.js | 2 +- 7 files changed, 7 insertions(+), 9 deletions(-) (limited to 'javascript') diff --git a/javascript/aspectRatioOverlay.js b/javascript/aspectRatioOverlay.js index 1c08a1a9..2cf2d571 100644 --- a/javascript/aspectRatioOverlay.js +++ b/javascript/aspectRatioOverlay.js @@ -81,7 +81,7 @@ function dimensionChange(e, is_width, is_height) { } -onUiUpdate(function() { +onAfterUiUpdate(function() { var arPreviewRect = gradioApp().querySelector('#imageARPreview'); if (arPreviewRect) { arPreviewRect.style.display = 'none'; diff --git a/javascript/contextMenus.js b/javascript/contextMenus.js index f14af1d4..d60a10c4 100644 --- a/javascript/contextMenus.js +++ b/javascript/contextMenus.js @@ -167,6 +167,4 @@ var addContextMenuEventListener = initResponse[2]; })(); //End example Context Menu Items -onUiUpdate(function() { - addContextMenuEventListener(); -}); +onAfterUiUpdate(addContextMenuEventListener); diff --git a/javascript/generationParams.js b/javascript/generationParams.js index a877f8a5..7c0fd221 100644 --- a/javascript/generationParams.js +++ b/javascript/generationParams.js @@ -1,7 +1,7 @@ // attaches listeners to the txt2img and img2img galleries to update displayed generation param text when the image changes let txt2img_gallery, img2img_gallery, modal = undefined; -onUiUpdate(function() { +onAfterUiUpdate(function() { if (!txt2img_gallery) { txt2img_gallery = attachGalleryListeners("txt2img"); } diff --git a/javascript/imageMaskFix.js b/javascript/imageMaskFix.js index 3c9b8a6f..900c56f3 100644 --- a/javascript/imageMaskFix.js +++ b/javascript/imageMaskFix.js @@ -39,5 +39,5 @@ function imageMaskResize() { }); } -onUiUpdate(imageMaskResize); +onAfterUiUpdate(imageMaskResize); window.addEventListener('resize', imageMaskResize); diff --git a/javascript/imageviewer.js b/javascript/imageviewer.js index 78e24eb9..677e95c1 100644 --- a/javascript/imageviewer.js +++ b/javascript/imageviewer.js @@ -170,7 +170,7 @@ function modalTileImageToggle(event) { event.stopPropagation(); } -onUiUpdate(function() { +onAfterUiUpdate(function() { var fullImg_preview = gradioApp().querySelectorAll('.gradio-gallery > div > img'); if (fullImg_preview != null) { fullImg_preview.forEach(setupImageForLightbox); diff --git a/javascript/notification.js b/javascript/notification.js index a68a76f2..76c5715d 100644 --- a/javascript/notification.js +++ b/javascript/notification.js @@ -4,7 +4,7 @@ let lastHeadImg = null; let notificationButton = null; -onUiUpdate(function() { +onAfterUiUpdate(function() { if (notificationButton == null) { notificationButton = gradioApp().getElementById('request_notifications'); diff --git a/javascript/ui.js b/javascript/ui.js index 800a2ae6..d70a681b 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -249,7 +249,7 @@ function confirm_clear_prompt(prompt, negative_prompt) { var opts = {}; -onUiUpdate(function() { +onAfterUiUpdate(function() { if (Object.keys(opts).length != 0) return; var json_elem = gradioApp().getElementById('settings_json'); -- cgit v1.2.1 From df59b74cedf6db12419de43f3b45c71cf457896e Mon Sep 17 00:00:00 2001 From: missionfloyd Date: Sun, 28 May 2023 20:42:47 -0600 Subject: Only poll gamepads while connected --- javascript/imageviewerGamepad.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'javascript') diff --git a/javascript/imageviewerGamepad.js b/javascript/imageviewerGamepad.js index 31d226de..0510c02a 100644 --- a/javascript/imageviewerGamepad.js +++ b/javascript/imageviewerGamepad.js @@ -1,7 +1,9 @@ +let gamepads = []; + window.addEventListener('gamepadconnected', (e) => { const index = e.gamepad.index; let isWaiting = false; - setInterval(async() => { + gamepads[index] = setInterval(async() => { if (!opts.js_modal_lightbox_gamepad || isWaiting) return; const gamepad = navigator.getGamepads()[index]; const xValue = gamepad.axes[0]; @@ -22,6 +24,7 @@ window.addEventListener('gamepadconnected', (e) => { isWaiting = false; } }, 10); + window.addEventListener('gamepaddisconnected', (e) => clearInterval(gamepads[e.gamepad.index])) }); /* -- cgit v1.2.1 From 679e8738759b9aa2678a40d518bf6d67915e98fe Mon Sep 17 00:00:00 2001 From: missionfloyd Date: Sun, 28 May 2023 20:49:46 -0600 Subject: Update imageviewerGamepad.js --- javascript/imageviewerGamepad.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'javascript') diff --git a/javascript/imageviewerGamepad.js b/javascript/imageviewerGamepad.js index 0510c02a..45cc4cbf 100644 --- a/javascript/imageviewerGamepad.js +++ b/javascript/imageviewerGamepad.js @@ -24,7 +24,7 @@ window.addEventListener('gamepadconnected', (e) => { isWaiting = false; } }, 10); - window.addEventListener('gamepaddisconnected', (e) => clearInterval(gamepads[e.gamepad.index])) + window.addEventListener('gamepaddisconnected', (e) => clearInterval(gamepads[e.gamepad.index])); }); /* -- cgit v1.2.1 From baa81126c485434211cb6d58292f77de00dc2432 Mon Sep 17 00:00:00 2001 From: missionfloyd Date: Mon, 29 May 2023 23:52:19 -0600 Subject: Move gamepaddisconnected listener --- javascript/imageviewerGamepad.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'javascript') diff --git a/javascript/imageviewerGamepad.js b/javascript/imageviewerGamepad.js index 45cc4cbf..a22c7e6e 100644 --- a/javascript/imageviewerGamepad.js +++ b/javascript/imageviewerGamepad.js @@ -24,7 +24,10 @@ window.addEventListener('gamepadconnected', (e) => { isWaiting = false; } }, 10); - window.addEventListener('gamepaddisconnected', (e) => clearInterval(gamepads[e.gamepad.index])); +}); + +window.addEventListener('gamepaddisconnected', (e) => { + clearInterval(gamepads[e.gamepad.index]); }); /* -- cgit v1.2.1 From a5e851028e23e411c392a66e7c791e388b3e4aba Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Thu, 1 Jun 2023 10:01:42 +0300 Subject: add hiding and a colspans to startup profile table --- javascript/profilerVisualization.js | 84 ++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 11 deletions(-) (limited to 'javascript') diff --git a/javascript/profilerVisualization.js b/javascript/profilerVisualization.js index 1bd75986..9d8e5f42 100644 --- a/javascript/profilerVisualization.js +++ b/javascript/profilerVisualization.js @@ -3,11 +3,29 @@ function createRow(table, cellName, items) { var tr = document.createElement('tr'); var res = []; - items.forEach(function(x) { + items.forEach(function(x, i) { + if (x === undefined) { + res.push(null); + return; + } + var td = document.createElement(cellName); td.textContent = x; tr.appendChild(td); res.push(td); + + var colspan = 1; + for (var n = i + 1; n < items.length; n++) { + if (items[n] !== undefined) { + break; + } + + colspan += 1; + } + + if (colspan > 1) { + td.colSpan = colspan; + } }); table.appendChild(tr); @@ -15,7 +33,7 @@ function createRow(table, cellName, items) { return res; } -function showProfile(path, cutoff = 0.0005) { +function showProfile(path, cutoff = 0.05) { requestGet(path, {}, function(data) { var table = document.createElement('table'); table.className = 'popup-table'; @@ -38,7 +56,7 @@ function showProfile(path, cutoff = 0.0005) { return !(a < b || b < a); } - var addLevel = function(level, parent) { + var addLevel = function(level, parent, hide) { var matching = items.filter(function(x) { return x.parts[level] && !x.parts[level + 1] && arraysEqual(x.parts.slice(0, level), parent); }); @@ -47,12 +65,10 @@ function showProfile(path, cutoff = 0.0005) { }); var othersTime = 0; var othersList = []; + var othersRows = []; + var childrenRows = []; sorted.forEach(function(x) { - if (x.time < cutoff) { - othersTime += x.time; - othersList.push(x.parts[level]); - return; - } + var visible = x.time >= cutoff && !hide; var cells = []; for (var i = 0; i < maxLength; i++) { @@ -64,7 +80,32 @@ function showProfile(path, cutoff = 0.0005) { cols[i].className = 'muted'; } - addLevel(level + 1, parent.concat([x.parts[level]])); + var tr = cols[0].parentNode; + if (!visible) { + tr.classList.add("hidden"); + } + + if (x.time >= cutoff) { + childrenRows.push(tr); + } else { + othersTime += x.time; + othersList.push(x.parts[level]); + othersRows.push(tr); + } + + var children = addLevel(level + 1, parent.concat([x.parts[level]]), true); + if (children.length > 0) { + var cell = cols[level]; + var onclick = function() { + cell.classList.remove("link"); + cell.removeEventListener("click", onclick); + children.forEach(function(x) { + x.classList.remove("hidden"); + }); + }; + cell.classList.add("link"); + cell.addEventListener("click", onclick); + } }); if (othersTime > 0) { @@ -73,14 +114,35 @@ function showProfile(path, cutoff = 0.0005) { cells.push(parent[i]); } cells.push(othersTime.toFixed(3)); + cells[level] = 'others'; var cols = createRow(table, 'td', cells); for (i = 0; i < level; i++) { cols[i].className = 'muted'; } - cols[level].textContent = 'others'; - cols[level].title = othersList.join(", "); + var cell = cols[level]; + var tr = cell.parentNode; + var onclick = function() { + tr.classList.add("hidden"); + cell.classList.remove("link"); + cell.removeEventListener("click", onclick); + othersRows.forEach(function(x) { + x.classList.remove("hidden"); + }); + }; + + cell.title = othersList.join(", "); + cell.classList.add("link"); + cell.addEventListener("click", onclick); + + if (hide) { + tr.classList.add("hidden"); + } + + childrenRows.push(tr); } + + return childrenRows; }; addLevel(0, []); -- cgit v1.2.1 From 7dca8e7698101fd5f610675f21569eba628883f8 Mon Sep 17 00:00:00 2001 From: catboxanon <122327233+catboxanon@users.noreply.github.com> Date: Fri, 2 Jun 2023 04:08:45 +0000 Subject: Support dynamic sort of extra networks --- javascript/extraNetworks.js | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'javascript') diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index aafe0a00..58bc7f1d 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -3,10 +3,17 @@ function setupExtraNetworksForTab(tabname) { var tabs = gradioApp().querySelector('#' + tabname + '_extra_tabs > div'); var search = gradioApp().querySelector('#' + tabname + '_extra_search textarea'); + var sort = gradioApp().getElementById(tabname + '_extra_sort'); + var sortOrder = gradioApp().getElementById(tabname + '_extra_sortorder'); var refresh = gradioApp().getElementById(tabname + '_extra_refresh'); search.classList.add('search'); + sort.classList.add('sort'); + sortOrder.classList.add('sortorder'); + sort.dataset.sortkey = 'sortDefault' tabs.appendChild(search); + tabs.appendChild(sort); + tabs.appendChild(sortOrder); tabs.appendChild(refresh); var applyFilter = function() { @@ -26,8 +33,48 @@ function setupExtraNetworksForTab(tabname) { }); }; + var applySort = function() { + var reverse = sortOrder.classList.contains("sortReverse"); + var sortKey = sort.querySelector("input").value.toLowerCase().replace("sort","").replaceAll(" ", "_").replace(/_+$/, "").trim(); + sortKey = sortKey ? "sort" + sortKey.charAt(0).toUpperCase() + sortKey.slice(1) : "" + var sortKeyStore = sortKey ? sortKey + (reverse ? "Reverse" : "") : "" + if (!sortKey || sortKeyStore == sort.dataset.sortkey) + return; + + sort.dataset.sortkey = sortKeyStore; + + var cards = gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card') + cards.forEach(function(card) { + card.originalParentElement = card.parentElement; + }) + var sortedCards = Array.from(cards); + sortedCards.sort(function(cardA, cardB) { + var a = cardA.dataset[sortKey]; + var b = cardB.dataset[sortKey]; + if (!isNaN(a) && !isNaN(b)) + return parseInt(a) - parseInt(b); + + return (a < b ? -1 : (a > b ? 1 : 0)); + }) + if (reverse) + sortedCards.reverse(); + cards.forEach(function(card) { + card.remove(); + }) + sortedCards.forEach(function(card) { + card.originalParentElement.appendChild(card); + }) + } + search.addEventListener("input", applyFilter); applyFilter(); + ["change", "blur", "click"].forEach(function(evt) { + sort.querySelector("input").addEventListener(evt, applySort); + }) + sortOrder.addEventListener("click", function() { + sortOrder.classList.toggle("sortReverse"); + applySort(); + }); extraNetworksApplyFilter[tabname] = applyFilter; } -- cgit v1.2.1 From 4cc0cede6d4cae74779b1b4cfc4b7bf7bfdaeaa6 Mon Sep 17 00:00:00 2001 From: catboxanon <122327233+catboxanon@users.noreply.github.com> Date: Fri, 2 Jun 2023 04:12:08 +0000 Subject: lint fixes --- javascript/extraNetworks.js | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'javascript') diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index 58bc7f1d..b87bca3e 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -10,7 +10,7 @@ function setupExtraNetworksForTab(tabname) { search.classList.add('search'); sort.classList.add('sort'); sortOrder.classList.add('sortorder'); - sort.dataset.sortkey = 'sortDefault' + sort.dataset.sortkey = 'sortDefault'; tabs.appendChild(search); tabs.appendChild(sort); tabs.appendChild(sortOrder); @@ -35,42 +35,45 @@ function setupExtraNetworksForTab(tabname) { var applySort = function() { var reverse = sortOrder.classList.contains("sortReverse"); - var sortKey = sort.querySelector("input").value.toLowerCase().replace("sort","").replaceAll(" ", "_").replace(/_+$/, "").trim(); - sortKey = sortKey ? "sort" + sortKey.charAt(0).toUpperCase() + sortKey.slice(1) : "" - var sortKeyStore = sortKey ? sortKey + (reverse ? "Reverse" : "") : "" - if (!sortKey || sortKeyStore == sort.dataset.sortkey) + var sortKey = sort.querySelector("input").value.toLowerCase().replace("sort", "").replaceAll(" ", "_").replace(/_+$/, "").trim(); + sortKey = sortKey ? "sort" + sortKey.charAt(0).toUpperCase() + sortKey.slice(1) : ""; + var sortKeyStore = sortKey ? sortKey + (reverse ? "Reverse" : "") : ""; + if (!sortKey || sortKeyStore == sort.dataset.sortkey) { return; + } sort.dataset.sortkey = sortKeyStore; - var cards = gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card') + var cards = gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card'); cards.forEach(function(card) { card.originalParentElement = card.parentElement; - }) + }); var sortedCards = Array.from(cards); sortedCards.sort(function(cardA, cardB) { var a = cardA.dataset[sortKey]; var b = cardB.dataset[sortKey]; - if (!isNaN(a) && !isNaN(b)) + if (!isNaN(a) && !isNaN(b)) { return parseInt(a) - parseInt(b); + } return (a < b ? -1 : (a > b ? 1 : 0)); - }) - if (reverse) + }); + if (reverse) { sortedCards.reverse(); + } cards.forEach(function(card) { card.remove(); - }) + }); sortedCards.forEach(function(card) { card.originalParentElement.appendChild(card); - }) - } + }); + }; search.addEventListener("input", applyFilter); applyFilter(); ["change", "blur", "click"].forEach(function(evt) { sort.querySelector("input").addEventListener(evt, applySort); - }) + }); sortOrder.addEventListener("click", function() { sortOrder.classList.toggle("sortReverse"); applySort(); -- cgit v1.2.1 From 46e4777fd60cb589ac3fba4d6b8c76076cb7d27f Mon Sep 17 00:00:00 2001 From: w-e-w <40751091+w-e-w@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:48:45 +0900 Subject: Generate Forever during generation Generate Forever during generation --- javascript/contextMenus.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'javascript') diff --git a/javascript/contextMenus.js b/javascript/contextMenus.js index d60a10c4..ccae242f 100644 --- a/javascript/contextMenus.js +++ b/javascript/contextMenus.js @@ -148,12 +148,18 @@ var addContextMenuEventListener = initResponse[2]; 500); }; - appendContextMenuOption('#txt2img_generate', 'Generate forever', function() { + let generateOnRepeat_txt2img = function() { generateOnRepeat('#txt2img_generate', '#txt2img_interrupt'); - }); - appendContextMenuOption('#img2img_generate', 'Generate forever', function() { + }; + + let generateOnRepeat_img2img = function() { generateOnRepeat('#img2img_generate', '#img2img_interrupt'); - }); + }; + + appendContextMenuOption('#txt2img_generate', 'Generate forever', generateOnRepeat_txt2img); + appendContextMenuOption('#txt2img_interrupt', 'Generate forever', generateOnRepeat_txt2img); + appendContextMenuOption('#img2img_generate', 'Generate forever', generateOnRepeat_img2img); + appendContextMenuOption('#img2img_interrupt', 'Generate forever', generateOnRepeat_img2img); let cancelGenerateForever = function() { clearInterval(window.generateOnRepeatInterval); -- cgit v1.2.1 From f7ae0e68c9c91cd95e28552ef930299286026cd7 Mon Sep 17 00:00:00 2001 From: zhtttylz Date: Sun, 18 Jun 2023 15:46:08 +0800 Subject: Fix Typo of hints.js --- javascript/hints.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'javascript') diff --git a/javascript/hints.js b/javascript/hints.js index 46f342cb..a2f222e5 100644 --- a/javascript/hints.js +++ b/javascript/hints.js @@ -15,7 +15,7 @@ var titles = { "CFG Scale": "Classifier Free Guidance Scale - how strongly the image should conform to prompt - lower values produce more creative results", "Seed": "A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result", "\u{1f3b2}\ufe0f": "Set seed to -1, which will cause a new random number to be used every time", - "\u267b\ufe0f": "Reuse seed from last generation, mostly useful if it was randomed", + "\u267b\ufe0f": "Reuse seed from last generation, mostly useful if it was randomized", "\u2199\ufe0f": "Read generation parameters from prompt or last generation if prompt is empty into user interface.", "\u{1f4c2}": "Open images output directory", "\u{1f4be}": "Save style", @@ -112,7 +112,7 @@ var titles = { "Resize height to": "Resizes image to this height. If 0, height is inferred from either of two nearby sliders.", "Multiplier for extra networks": "When adding extra network such as Hypernetwork or Lora to prompt, use this multiplier for it.", "Discard weights with matching name": "Regular expression; if weights's name matches it, the weights is not written to the resulting checkpoint. Use ^model_ema to discard EMA weights.", - "Extra networks tab order": "Comma-separated list of tab names; tabs listed here will appear in the extra networks UI first and in order lsited.", + "Extra networks tab order": "Comma-separated list of tab names; tabs listed here will appear in the extra networks UI first and in order listed.", "Negative Guidance minimum sigma": "Skip negative prompt for steps where image is already mostly denoised; the higher this value, the more skips there will be; provides increased performance in exchange for minor quality reduction." }; -- cgit v1.2.1 From dd268c48c9099c4cf308eb04590bd201c9b64253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20=28Netux=29=20Rodr=C3=ADguez?= Date: Sun, 25 Jun 2023 00:30:08 -0300 Subject: feat(extensions): add toggle all checkbox to Installed tab Small QoL addition. While there is the option to disable all extensions with the radio buttons at the top, that only acts as an added flag and doesn't really change the state of the extensions in the UI. An use case for this checkbox is to disable all extensions except for a few, which is important for debugging extensions. You could do that before, but you'd have to uncheck and recheck every extension one by one. --- javascript/extensions.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'javascript') diff --git a/javascript/extensions.js b/javascript/extensions.js index efeaf3a5..1f7254c5 100644 --- a/javascript/extensions.js +++ b/javascript/extensions.js @@ -72,3 +72,21 @@ function config_state_confirm_restore(_, config_state_name, config_restore_type) } return [confirmed, config_state_name, config_restore_type]; } + +function toggle_all_extensions(event) { + gradioApp().querySelectorAll('#extensions .extension_toggle').forEach(function(checkbox_el) { + checkbox_el.checked = event.target.checked; + }); +} + +function toggle_extension() { + let all_extensions_toggled = true; + for (const checkbox_el of gradioApp().querySelectorAll('#extensions .extension_toggle')) { + if (!checkbox_el.checked) { + all_extensions_toggled = false; + break; + } + } + + gradioApp().querySelector('#extensions .all_extensions_toggle').checked = all_extensions_toggled; +} -- cgit v1.2.1 From 0b0767939d4cc0868a10b6c0978f7b2d963dea1a Mon Sep 17 00:00:00 2001 From: missionfloyd Date: Wed, 28 Jun 2023 17:51:27 -0600 Subject: Correctly remove end parenthesis with ctrl+up/down --- javascript/edit-attention.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'javascript') diff --git a/javascript/edit-attention.js b/javascript/edit-attention.js index ffa73147..8906c892 100644 --- a/javascript/edit-attention.js +++ b/javascript/edit-attention.js @@ -100,11 +100,12 @@ function keyupEditAttention(event) { if (String(weight).length == 1) weight += ".0"; if (closeCharacter == ')' && weight == 1) { - text = text.slice(0, selectionStart - 1) + text.slice(selectionStart, selectionEnd) + text.slice(selectionEnd + 5); + var endParenPos = text.substring(selectionEnd).indexOf(')'); + text = text.slice(0, selectionStart - 1) + text.slice(selectionStart, selectionEnd) + text.slice(selectionEnd + endParenPos + 1); selectionStart--; selectionEnd--; } else { - text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + 1 + end - 1); + text = text.slice(0, selectionEnd + 1) + weight + text.slice(selectionEnd + end); } target.focus(); -- cgit v1.2.1