'use strict'; const VERSION = "1.1.0" var weight_helper_history = JSON.parse(localStorage.getItem("weight_helper")); var weight_helper_type = JSON.parse(localStorage.getItem("weight_helper_type")); class WeightHelper { static REGEX = /<([^:]+):([^:]+):([^>]+)>/; static SUPPORT_TYPE = new Set(["lora", "lyco"]); static weight_helper_history = JSON.parse(localStorage.getItem("weight_helper")); static last_instance = undefined; WEIGHT_SETTINGS = { te: { label: "TEnc", min: opts.weight_helper_te_min * 100, max: opts.weight_helper_te_max * 100, default: 100, step: opts.weight_helper_te_step * 100 }, unet: { label: "UNet", min: opts.weight_helper_unet_min * 100, max: opts.weight_helper_unet_max * 100, default: undefined, step: opts.weight_helper_unet_step * 100 }, dyn: { label: "Dyn", min: opts.weight_helper_dyn_min * 100, max: opts.weight_helper_dyn_max * 100, default: undefined, step: opts.weight_helper_dyn_step * 100 }, start: { label: "Start", min: 0, max: undefined, default: 0, step: 100 }, stop: { label: "Stop", min: 0, max: undefined, default: undefined, step: 100 }, lbw: { labels: ["BASE", "IN00", "IN01", "IN02", "IN03", "IN04", "IN05", "IN06", "IN07", "IN08", "IN09", "IN10", "IN11", "MID", "OUT00", "OUT01", "OUT02", "OUT03", "OUT04", "OUT05", "OUT06", "OUT07", "OUT08", "OUT09", "OUT10", "OUT11"], min: opts.weight_helper_lbw_min * 100, max: opts.weight_helper_lbw_max * 100, default: 100, step: opts.weight_helper_lbw_step * 100 } }; LBW_WEIGHT_TAGS = [ { type: "lora", label: "LoRA" }, { type: "lyco", label: "LyCORIS" } ]; LBW_WEIGHT_TYPES = [ { type: "", label: "Default" }, { type: "sdxl", label: "SDXL" }, { type: "all", label: "ALL" } ]; LBW_WEIGHT_SETTINGS = { lora: { "": { enable_blocks: [1,0,1,1,0,1,1,0,1,1,0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,1], block_points: ["BASE", "IN01-IN04", "IN05-IN08", "MID", "OUT03-OUT06", "OUT07-OUT11"] }, "sdxl": { enable_blocks: [1,0,0,0,0,1,1,0,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0], block_points: ["BASE", "IN04-IN08", "MID", "OUT00-OUT05"] }, "all": { enable_blocks: [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], block_points: ["BASE", "IN00-IN05", "IN06-IN11", "MID", "OUT00-OUT05", "OUT06-OUT11"] } }, lyco: { "": { enable_blocks: [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], block_points: ["BASE", "IN00-IN05", "IN06-IN11", "MID", "OUT00-OUT05", "OUT06-OUT11"] }, "sdxl": { enable_blocks: [1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0], block_points: ["BASE", "IN00-IN03", "IN04-IN08", "MID", "OUT00-OUT03", "OUT04-OUT08"] }, "all": { enable_blocks: [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], block_points: ["BASE", "IN00-IN05", "IN06-IN11", "MID", "OUT00-OUT05", "OUT06-OUT11"] } } }; currentDate = null; historyLimitDate = null; offsetX = 0; offsetY = 0; isDragging = false; lbwPresetsMap = {}; lbwPresetsValueKeyMap = {}; weightTag = null; weightType = ""; name = null; nameHash = null; weightData = {}; lastSelectionStart = null; lastSelectionEnd = null; lastText = null; historyIndex = 0; cleared = false; customContextMenu = null; lbwPresetSelect = null; lbwGroupWrapper = null; weightUIs = {}; usingExecCommand = false; constructor(tabId, textarea, selectionStart, selectionEnd, type, name, allWeights) { this.tabId = tabId; this.textarea = textarea; this.lastSelectionStart = selectionStart; this.lastSelectionEnd = selectionEnd; this.lastText = this.textarea.value.substring(this.lastSelectionStart, this.lastSelectionEnd); this.currentDate = this.#getCurrentDate(); this.historyLimitDate = this.#getDateBeforeDays(this.currentDate, 20); this.weightTag = type; this.name = name; this.nameHash = this.#hashCode(name); const optBlockPattern = /((BASE|MID|(IN|OUT)[0-9]{1,2}(-(IN|OUT)[0-9]{1,2})?) *(, *|$))+/; for (let weightTag of this.LBW_WEIGHT_TAGS) { for (let weightType of this.LBW_WEIGHT_TYPES) { try { const optBlockPoints = opts[`weight_helper_lbw_${weightTag.type}_${weightType.type}_block_points`] if (optBlockPattern.exec(optBlockPoints)) { const blockPoints = optBlockPoints.split(',').map(v => { return v.trim().replace(/\d+/g, match => match.length === 1 ? `0${match}` : match); }); this.LBW_WEIGHT_SETTINGS[weightTag.type][weightType.type].block_points = blockPoints; } } catch (e) { console.warn(`${weightTag.type}_${weightType.type} block definition format is invalid.`, e); } } } this.#init(allWeights); this.#initContextMenuHeader(); if (opts.weight_helper_show_preview) { (async() => { const previewPath = await postAPI("/whapi/v1/get_preview?key=" + encodeURIComponent(this.name), null); if (previewPath) { const thumb = document.getElementById("weight-helper-thumb"); thumb.style.maxHeight = opts.weight_helper_preview_max_height + "px"; switch (opts.weight_helper_preview_position) { case "Bottom Right": thumb.style.bottom = "0px"; thumb.style.left = String(this.customContextMenu.clientWidth + 6) + "px"; break; case "Top Left": thumb.style.top = "0px" thumb.style.right = String(this.customContextMenu.clientWidth + 6) + "px"; break; case "Bottom Left": thumb.style.bottom = "0px"; thumb.style.right = String(this.customContextMenu.clientWidth + 6) + "px"; break; default: thumb.style.top = "0px" thumb.style.left = String(this.customContextMenu.clientWidth + 6) + "px"; break; } thumb.src = "./sd_extra_networks/thumb?filename=" + encodeURI(previewPath); } })(); } this.#initContextMenuBody(); this.#makeLbwGroupWrapper(); if (opts.weight_helper_using_execCommand) { if (typeof document.execCommand === 'function') { this.usingExecCommand = true; } else { console.warn("execCommand is not supported."); } } } #hashCode(s) { let hash = 0; if (s.length === 0) return hash; for (let i = 0; i < s.length; i++) { const char = s.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; // Convert to 32bit integer } return hash; } #getCurrentDate() { var date = new Date(); var year = date.getFullYear(); var month = ("0" + (date.getMonth() + 1)).slice(-2); var day = ("0" + date.getDate()).slice(-2); return year + month + day; } #getDateBeforeDays(currentDate, days) { let date = new Date(currentDate.substring(0, 4), currentDate.substring(4, 6) - 1, currentDate.substring(6, 8)); date.setDate(date.getDate() - days); let year = date.getFullYear(); let month = ("0" + (date.getMonth() + 1)).slice(-2); let day = ("0" + date.getDate()).slice(-2); return year + month + day; } #init(allWeights) { if (!weight_helper_type) { weight_helper_type = {}; } const samplingSteps = gradioApp().getElementById("txt2img_steps").querySelector("input"); if (samplingSteps) { const samplingStepsValue = parseInt(samplingSteps.value) * 100; this.WEIGHT_SETTINGS.start.max = samplingStepsValue; this.WEIGHT_SETTINGS.stop.max = samplingStepsValue; this.WEIGHT_SETTINGS.stop.default = samplingStepsValue; } const lbwPreset = gradioApp().getElementById("lbw_ratiospreset").querySelector("textarea"); if (lbwPreset && lbwPreset.value) { const lbwPresets = lbwPreset.value.split("\n"); for (const weightTag of this.LBW_WEIGHT_TAGS) { this.lbwPresetsMap[weightTag.type] = {}; this.lbwPresetsValueKeyMap[weightTag.type] = {}; for (const weightType of this.LBW_WEIGHT_TYPES) { let lbwPreset = {}; let lbwPresetValueKey = {}; this.lbwPresetsMap[weightTag.type][weightType.type] = lbwPreset; this.lbwPresetsValueKeyMap[weightTag.type][weightType.type] = lbwPresetValueKey; const enableBlocks = this.LBW_WEIGHT_SETTINGS[weightTag.type][weightType.type].enable_blocks; const blockLength = enableBlocks.filter((b) => b == 1).length; for (const line of lbwPresets) { const kv = line.split(":"); if (kv.length == 2 && kv[1].split(",").length == blockLength) { lbwPreset[kv[0]] = kv[1]; lbwPresetValueKey[kv[1]] = kv[0]; } } } } } for (const weightType of Object.keys(this.WEIGHT_SETTINGS)) { this.weightData[weightType] = [] this.weightData[weightType].push(this.WEIGHT_SETTINGS[weightType].default); } this.weightData.lbw = []; this.weightData.lbwe = []; const keyTypes = ["te", "unet", "dyn"]; const weightBlocksArray = allWeights.split(":"); let isTypeDetermined = false; for (let i = 0; i < weightBlocksArray.length; i++) { let weightKeyVal = weightBlocksArray[i].split("="); let keyType; let blocks; if (weightKeyVal.length > 1) { keyType = weightKeyVal[0].toLowerCase(); blocks = weightKeyVal[1]; } else { keyType = keyTypes[i]; blocks = weightKeyVal[0]; } if (keyType === "lbw") { blocks = weightKeyVal[1].split(','); for (const weightType of this.LBW_WEIGHT_TYPES) { const lbwPresets = this.lbwPresetsMap[this.weightTag][weightType.type]; if (blocks in lbwPresets) { blocks = lbwPresets[blocks].split(','); break; } } for (const weightType of this.LBW_WEIGHT_TYPES) { const lbwWeightSetting = this.LBW_WEIGHT_SETTINGS[this.weightTag][weightType.type]; const enableBlocks = lbwWeightSetting.enable_blocks; if (blocks.length == enableBlocks.filter((b) => b == 1).length) { this.weightType = weightType.type; isTypeDetermined = true; let refIdx = 0; for (let enable of enableBlocks) { if (enable) { this.weightData.lbw.push(blocks[refIdx] * 100); refIdx++; } else { this.weightData.lbw.push(0); } } break; } } } else if (keyType === "step") { const startStop = blocks.split('-'); this.weightData.start[0] = parseInt(startStop[0]) * 100; this.weightData.stop[0] = parseInt(startStop[1]) * 100; } else if (keyType === "lbwe") { this.weightData[keyType][0] = blocks; } else { this.weightData[keyType][0] = blocks * 100; } } if (!isTypeDetermined) { if (this.nameHash in weight_helper_type) { this.weightType = weight_helper_type[this.nameHash] } } if (!this.weightData.lbw.length) { const enableBlocks = this.LBW_WEIGHT_SETTINGS[this.weightTag][this.weightType].enable_blocks; for (let _ of enableBlocks) { this.weightData.lbw.push(100); } } if (!WeightHelper.weight_helper_history) { WeightHelper.weight_helper_history = {}; } if (!(this.nameHash in WeightHelper.weight_helper_history)) { WeightHelper.weight_helper_history[this.nameHash] = []; } WeightHelper.weight_helper_history[this.nameHash] = WeightHelper.weight_helper_history[this.nameHash] .filter(v => v.VERSION == VERSION).filter(v => v.DATE >= this.historyLimitDate); if (WeightHelper.weight_helper_history[this.nameHash].length == 0) { const history = {}; this.#copyWeight(this.weightData, history); WeightHelper.weight_helper_history[this.nameHash].push(history); } this.historyIndex = WeightHelper.weight_helper_history[this.nameHash].length - 1; } #initContextMenuHeader() { this.customContextMenu = document.createElement('div'); this.customContextMenu.id = 'weight-helper'; let scale = opts.weight_helper_context_menu_scale; if (scale <= 0) { scale = 1; } this.customContextMenu.style.transform = `scale(${scale})`; const thumb = document.createElement("img"); thumb.id = "weight-helper-thumb"; this.customContextMenu.appendChild(thumb); const header = document.createElement('header'); const headerLabel = document.createElement('label'); headerLabel.textContent = this.name; header.appendChild(headerLabel); const history = document.createElement('div'); history.classList.add("history"); header.appendChild(history); const clear = document.createElement('a'); clear.classList.add("clear"); clear.textContent = "clear"; clear.addEventListener("click", () => { this.cleared = true; pageLabel.textContent = "0/0"; this.historyIndex = -1; WeightHelper.weight_helper_history[this.nameHash] = []; }); history.appendChild(clear); const pageWrapper = document.createElement('div'); pageWrapper.classList.add("page"); history.appendChild(pageWrapper); const pageLeft = document.createElement('a'); pageLeft.textContent = "<"; pageLeft.classList.add("icon"); pageWrapper.appendChild(pageLeft); pageLeft.addEventListener("click", () => { if (this.historyIndex <= 0) { return; } this.historyIndex--; pageLabel.textContent = (this.historyIndex + 1) + "/" + WeightHelper.weight_helper_history[this.nameHash].length; this.#copyWeight(WeightHelper.weight_helper_history[this.nameHash][this.historyIndex], this.weightData); Object.keys(this.weightData).map(key => { for (const idx in this.weightData[key]) { const fVal = this.weightData[key][idx]; if (key in this.weightUIs) { this.weightUIs[key].slider[idx].value = fVal; this.weightUIs[key].updown[idx].value = fVal / 100; } } }); if (!this.usingExecCommand) { const lbwValues = this.#lbwWeightData().join(","); const updatedText = this.#getUpdatedText(lbwValues); this.#update(updatedText); } }); const pageLabel = document.createElement('label'); pageLabel.textContent = (this.historyIndex + 1) + "/" + WeightHelper.weight_helper_history[this.nameHash].length; pageWrapper.appendChild(pageLabel); const pageRight = document.createElement('a'); pageRight.textContent = ">"; pageRight.classList.add("icon"); pageWrapper.appendChild(pageRight); pageRight.addEventListener("click", () => { if (this.historyIndex >= WeightHelper.weight_helper_history[this.nameHash].length - 1) { return; } this.historyIndex++; pageLabel.textContent = (this.historyIndex + 1) + "/" + WeightHelper.weight_helper_history[this.nameHash].length; this.#copyWeight(WeightHelper.weight_helper_history[this.nameHash][this.historyIndex], this.weightData); Object.keys(this.weightData).map(key => { for (const idx in this.weightData[key]) { const fVal = this.weightData[key][idx]; if (key in this.weightUIs) { this.weightUIs[key].slider[idx].value = fVal; this.weightUIs[key].updown[idx].value = fVal / 100; } } }); if (!this.usingExecCommand) { const lbwValues = this.#lbwWeightData().join(","); const updatedText = this.#getUpdatedText(lbwValues); this.#update(updatedText); } }); this.customContextMenu.appendChild(header); this.customContextMenu.addEventListener('mousedown', (e) => { if (e.target.closest('header')) { this.isDragging = true; this.offsetX = e.clientX - this.customContextMenu.getBoundingClientRect().left; this.offsetY = e.clientY - this.customContextMenu.getBoundingClientRect().top; } }); document.addEventListener('mousemove', (e) => { if (!this.isDragging) return; const x = e.clientX - this.offsetX + window.scrollX; const y = e.clientY - this.offsetY + window.scrollY; this.customContextMenu.style.left = x + 'px'; this.customContextMenu.style.top = y + 'px'; }); document.addEventListener('mouseup', () => { this.isDragging = false; }); } #initContextMenuBody() { const children = this.customContextMenu.getElementsByTagName("section"); while (children.length > 0) { children[0].parentNode.removeChild(children[0]); } const extraOpts = []; let hiddenExtraOpts = 0; for (const group of Object.keys(this.WEIGHT_SETTINGS)) { if (group == "lbw") { break; } const weightSetting = this.WEIGHT_SETTINGS[group]; this.weightUIs[group] = {slider: [], updown: []}; const section = document.createElement('section'); section.classList.add("border"); const label = document.createElement('label'); label.textContent = weightSetting.label; section.appendChild(label); const sliderContainer = document.createElement('div'); sliderContainer.classList.add('f', 'f-c', 'g-4'); this.#makeSliderComponent(sliderContainer, null, group, 0); section.appendChild(sliderContainer); if (weightSetting.label === "TEnc") { this.customContextMenu.appendChild(section); } else { extraOpts.push(section); const defVal = this.WEIGHT_SETTINGS[group].default; const weightUI = this.weightUIs[group]; if ("active_checkbox" in weightUI && !weightUI.active_checkbox.checked || defVal !== undefined && this.weightData[group][0] === defVal) { section.style.display = 'none'; hiddenExtraOpts++; } this.customContextMenu.appendChild(section); } } if (hiddenExtraOpts > 0) { const extraButton = document.createElement('button'); extraButton.classList.add("secondary", "gradio-button"); extraButton.id = "weight-helper-show-extra-opt-button"; extraButton.textContent = "show extra options"; extraButton.addEventListener("click", (e) => { e.target.remove(); for (const extra of extraOpts) { extra.style.display = ''; } }); this.customContextMenu.appendChild(extraButton); } const group = "lbw"; this.weightUIs[group] = {slider: [], updown: [], dom: []}; const lbwSection = document.createElement('section'); lbwSection.classList.add("border"); const label = document.createElement('label'); label.textContent = group.toUpperCase(); lbwSection.appendChild(label); const lbwSet = document.createElement('div'); lbwSet.classList.add('f', 'col', 'g-4', 'w-fill'); lbwSection.appendChild(lbwSet); const typeRow = document.createElement("div"); typeRow.classList.add("f", "g-2", "f-end"); const lbwTagSelect = document.createElement("select"); lbwTagSelect.style.flexGrow = 1; for (const weightTag of this.LBW_WEIGHT_TAGS) { const lbwTagOpt = document.createElement('option'); lbwTagOpt.value = weightTag.type; lbwTagOpt.text = weightTag.label; lbwTagSelect.appendChild(lbwTagOpt); } lbwTagSelect.value = this.weightTag; lbwTagSelect.addEventListener("change", (e) => { this.weightTag = e.target.value; this.#makeLbwGroupWrapper(); }); typeRow.appendChild(lbwTagSelect); const typeTypeRow = document.createElement("div"); typeTypeRow.classList.add("border", "f", "g-2", "f-end"); const typeType = document.createElement("div"); typeType.classList.add("f", "g-2", "f-end"); for (const weightType of this.LBW_WEIGHT_TYPES) { const radioId = "weight-helper-detail_" + weightType.type; const weightTypeRadio = document.createElement("input"); weightTypeRadio.id = radioId; weightTypeRadio.type = "radio"; weightTypeRadio.name = "weight-helper-detail"; weightTypeRadio.value = weightType.type; weightTypeRadio.checked = weightType.type == this.weightType; weightTypeRadio.addEventListener("change", (e) => { this.weightType = e.target.value; this.#makeLbwGroupWrapper(); }); typeType.appendChild(weightTypeRadio); const weightTypeLabel = document.createElement("label"); weightTypeLabel.classList.add("radio-label"); weightTypeLabel.textContent = weightType.label; weightTypeLabel.htmlFor = radioId; typeType.appendChild(weightTypeLabel); } typeTypeRow.appendChild(typeType); typeRow.appendChild(typeTypeRow); lbwSet.appendChild(typeRow); this.lbwPresetSelect = document.createElement('select'); lbwSet.appendChild(this.lbwPresetSelect); this.lbwPresetSelect.addEventListener("change", (e) => { if (e.target.value === "") { return; } const lbwWeightSetting = this.LBW_WEIGHT_SETTINGS[this.weightTag][this.weightType]; const enableBlocks = lbwWeightSetting.enable_blocks; const values = e.target.value.split(",").map(v => Math.round(parseFloat(v) * 100)); let refIdx = 0; for (let idx = 0; idx < enableBlocks.length; idx++) { let val = 0; if (enableBlocks[idx] === 1) { val = values[refIdx]; refIdx++; } this.weightData[group][idx] = val; this.weightUIs[group].slider[idx].value = val; this.weightUIs[group].updown[idx].value = val / 100; } if (!this.usingExecCommand) { const lbwValues = this.#lbwWeightData().join(","); const updatedText = this.#getUpdatedText(lbwValues); this.#update(updatedText); } }); for (let idx = 0; idx < this.weightData[group].length; idx++) { let lbwUnit = document.createElement('div'); lbwUnit.classList.add('lbw-unit', `lbw-u-${idx}`); lbwUnit.classList.add('f', 'g-2'); const label = document.createElement('label'); label.textContent = this.WEIGHT_SETTINGS[group].labels[idx]; lbwUnit.appendChild(label); const sliderContainer = document.createElement('div'); sliderContainer.classList.add('f', 'f-c', 'g-4'); this.#makeSliderComponent(sliderContainer, this.lbwPresetSelect, group, idx); lbwUnit.appendChild(sliderContainer); this.weightUIs.lbw.dom.push(lbwUnit); } this.lbwGroupWrapper = document.createElement('div'); this.lbwGroupWrapper.classList.add('lbw-group-wrapper', 'f', 'col', 'g-2'); lbwSet.appendChild(this.lbwGroupWrapper); this.customContextMenu.appendChild(lbwSection); } #makeLbwGroupWrapper() { while (this.lbwPresetSelect.firstChild) { this.lbwPresetSelect.removeChild(this.lbwPresetSelect.firstChild); } const opt = document.createElement('option'); opt.value = ""; opt.text = ""; this.lbwPresetSelect.appendChild(opt); if (Object.keys(this.lbwPresetsMap[this.weightTag][this.weightType]).length) { for (const key of Object.keys(this.lbwPresetsMap[this.weightTag][this.weightType])) { const opt = document.createElement('option'); opt.text = key; opt.value = this.lbwPresetsMap[this.weightTag][this.weightType][key]; this.lbwPresetSelect.appendChild(opt); } } this.lbwPresetSelect.value = this.#lbwWeightData(); while (this.lbwGroupWrapper.firstChild) { this.lbwGroupWrapper.removeChild(this.lbwGroupWrapper.firstChild); } const lbwWeightSetting = this.LBW_WEIGHT_SETTINGS[this.weightTag][this.weightType]; const labelMap = {}; for (let idx = 0; idx < this.WEIGHT_SETTINGS.lbw.labels.length; idx++) { labelMap[this.WEIGHT_SETTINGS.lbw.labels[idx]] = idx; } for (const blockPoint of lbwWeightSetting.block_points) { const points = blockPoint.split("-"); let pointStart = labelMap[points[0]]; let pointEnd = pointStart; if (points.length > 1) { pointEnd = labelMap[points[1]]; } const lbwGroup = document.createElement('div'); lbwGroup.classList.add('border', 'f', 'g-2', 'col'); for (let idx = pointStart; idx <= pointEnd; idx++) { if (lbwWeightSetting.enable_blocks[idx] == 1) { lbwGroup.appendChild(this.weightUIs.lbw.dom[idx]); } } this.lbwGroupWrapper.appendChild(lbwGroup); } } #lbwWeightData() { const lbwWeightSetting = this.LBW_WEIGHT_SETTINGS[this.weightTag][this.weightType]; const enableBlocks = lbwWeightSetting.enable_blocks; return this.weightData.lbw.filter((_, i) => enableBlocks[i] === 1).map(v => v / 100); } #copyWeight(srcWeight, destWeight) { Object.keys(srcWeight).map(key => { destWeight[key] = []; for (const idx in srcWeight[key]) { const fVal = srcWeight[key][idx]; destWeight[key][idx] = fVal; } }); destWeight.VERSION = VERSION; destWeight.DATE = this.currentDate; } #makeSlider(group, i) { const value = Math.round(this.weightData[group][i]); const min = this.WEIGHT_SETTINGS[group].min; const max = this.WEIGHT_SETTINGS[group].max; const step = this.WEIGHT_SETTINGS[group].step; const slider = document.createElement('input'); slider.classList.add('slider'); slider.type = 'range'; if (group == "start" || group == "stop") { slider.min = min; slider.max = max; } else { slider.min = value < min ? value : min; slider.max = value > max ? value : max; } slider.step = step; slider.value = value; return slider; } #makeUpdown(group, i) { const value = this.weightData[group][i]; const step = this.WEIGHT_SETTINGS[group].step; const valueText = document.createElement('input'); valueText.classList.add('value'); valueText.type = "number"; valueText.step = parseFloat(step) / 100; valueText.value = value / 100; return valueText; } #makeSliderComponent(sliderContainer, lbwPresetSelect, group, i) { if (this.WEIGHT_SETTINGS[group].default === undefined) { const unetVal = this.weightData[group][i]; const useForceCheck = document.createElement('input'); useForceCheck.type = "checkbox"; if (unetVal != null) { useForceCheck.checked = true; } else { this.weightData[group][i] = 0; } this.weightUIs[group].active_checkbox = useForceCheck; sliderContainer.appendChild(useForceCheck); } const slider = this.#makeSlider(group, i); this.weightUIs[group].slider.push(slider); sliderContainer.appendChild(slider); const updown = this.#makeUpdown(group, i); this.weightUIs[group].updown.push(updown); sliderContainer.appendChild(updown); const changedLbwValues = () => { let lbwValues = null; if (lbwPresetSelect && group === "lbw") { lbwValues = this.#lbwWeightData().join(","); if (lbwValues in this.lbwPresetsValueKeyMap[this.weightTag][this.weightType]) { lbwPresetSelect.value = lbwValues; } else { lbwPresetSelect.selectedIndex = 0; } } if ("active_checkbox" in this.weightUIs[group]) { const activeCheck = this.weightUIs[group].active_checkbox; if (!activeCheck.checked) { activeCheck.checked = true; } } if (!this.usingExecCommand) { if (!lbwValues) { lbwValues = this.#lbwWeightData().join(","); } const updatedText = this.#getUpdatedText(lbwValues); this.#update(updatedText); } } slider.addEventListener('input', (e) => { const fVal = parseFloat(e.target.value); this.weightData[group][i] = fVal; updown.value = Math.round(fVal) / 100; changedLbwValues(); }); updown.addEventListener('input', (e) => { const fVal = parseFloat(e.target.value); this.weightData[group][i] = fVal * 100; slider.value = Math.round(fVal * 100); changedLbwValues(); }); } #getUpdatedText(lbwValues) { let updatedText = `<${this.weightTag}:${this.name}`; const optionalTypes = ["te", "unet", "dyn"]; let refIdx = 0; for (let idx = 0; idx < optionalTypes.length; idx++) { const keyType = optionalTypes[idx]; if (keyType in this.weightData) { const defVal = this.WEIGHT_SETTINGS[keyType].default; const val = this.weightData[keyType]; let output = false; if (keyType === "te") { output = true; } else if ("active_checkbox" in this.weightUIs[keyType]) { if (this.weightUIs[keyType].active_checkbox.checked) { output = true; } } else if (val != defVal) { output = true; } if (output) { let rateValue = val / 100; if (idx === refIdx) { updatedText += `:${rateValue}`; } else { updatedText += `:${keyType}=${rateValue}`; } refIdx++; } } } const startDefVal = this.WEIGHT_SETTINGS.start.default; const startVal = this.weightData.start; const stopDefVal = this.WEIGHT_SETTINGS.stop.default; const stopVal = this.weightData.stop; if (startVal != startDefVal && stopVal != stopDefVal) { updatedText += `:step=${startVal / 100}-${stopVal / 100}`; } else if (startVal != startDefVal) { updatedText += `:start=${startVal / 100}`; } else if (stopVal != stopDefVal) { updatedText += `:stop=${stopVal / 100}`; } let lbwWeights = []; const enableBlocks = this.LBW_WEIGHT_SETTINGS[this.weightTag][this.weightType].enable_blocks; for (let idx = 0; idx < enableBlocks.length; idx++) { if (enableBlocks[idx]) { lbwWeights.push(this.weightData.lbw[idx]); } } if (!lbwWeights.every(val => val === this.WEIGHT_SETTINGS.lbw.default)) { let rateValues = lbwWeights.map(v => v / 100).join(","); if (lbwValues in this.lbwPresetsValueKeyMap[this.weightTag][this.weightType]) { rateValues = this.lbwPresetsValueKeyMap[this.weightTag][this.weightType][lbwValues]; } updatedText += `:lbw=${rateValues}`; } if (this.weightData.lbwe.length > 0) { updatedText += `:lbwe=${this.weightData.lbwe[0]}`; } updatedText += ">"; return updatedText; } #update(updatedText) { this.textarea.value = this.textarea.value.substring(0, this.lastSelectionStart) + updatedText + this.textarea.value.substring(this.lastSelectionEnd); this.lastSelectionEnd = this.lastSelectionStart + updatedText.length; } #updateWithExecCommand(updatedText) { this.textarea.focus(); this.textarea.setSelectionRange(this.lastSelectionStart, this.lastSelectionEnd); document.execCommand("insertText", false, updatedText); } show(top, left) { this.customContextMenu.style.top = top + 'px'; this.customContextMenu.style.left = left + 'px'; document.body.appendChild(this.customContextMenu); const diffBottom = window.innerHeight - this.customContextMenu.getBoundingClientRect().bottom; if (diffBottom < 0) { this.customContextMenu.style.top = (top + diffBottom) + 'px'; const diffTop = this.customContextMenu.getBoundingClientRect().top; if (diffTop < 0) { this.customContextMenu.style.top = window.scrollY + 'px'; } } document.body.addEventListener('click', this.close); WeightHelper.last_instance = this; } close = (e) => { if (!this.customContextMenu) { return; } if (e && e.target.id === `${this.tabId}_token_button`) { return; } if (e && this.customContextMenu.contains(e.target)) { return; } if (!e || e.target.id !== "weight-helper-show-extra-opt-button") { WeightHelper.last_instance = undefined; if (e != null && e.target.id.indexOf("_interrupt") > 0) { document.body.removeChild(this.customContextMenu); document.body.removeEventListener("click", this.close); return; } if (!this.weightType) { delete weight_helper_type[this.nameHash]; } else { weight_helper_type[this.nameHash] = this.weightType; } localStorage.setItem("weight_helper_type", JSON.stringify(weight_helper_type)); const updatedText = this.#getUpdatedText(this.#lbwWeightData().join(",")); if (!this.usingExecCommand) { this.textarea.dispatchEvent(new InputEvent('input', { bubbles: true, cancelable: true })); if (this.cleared || this.lastText != updatedText) { this.weightData.VERSION = VERSION; this.weightData.DATE = this.currentDate; WeightHelper.weight_helper_history[this.nameHash].push(this.weightData); localStorage.setItem("weight_helper", JSON.stringify(WeightHelper.weight_helper_history)); } } else { if (this.cleared || this.lastText != updatedText) { let tacActiveInOrg = undefined; if (typeof TAC_CFG !== 'undefined' && TAC_CFG) { tacActiveInOrg = TAC_CFG.activeIn.global TAC_CFG.activeIn.global = false; } this.#updateWithExecCommand(updatedText); if (typeof TAC_CFG !== 'undefined' && TAC_CFG) { TAC_CFG.activeIn.global = tacActiveInOrg; } this.weightData.VERSION = VERSION; this.weightData.DATE = this.currentDate; WeightHelper.weight_helper_history[this.nameHash].push(this.weightData); localStorage.setItem("weight_helper", JSON.stringify(WeightHelper.weight_helper_history)); } } document.body.removeChild(this.customContextMenu); document.body.removeEventListener("click", this.close); } }; } async function postAPI(url, body) { let response = await fetch(url, { method: "POST", body: body }); if (response.status != 200) { console.error(`Error posting to API endpoint "${url}": ` + response.status, response.statusText); return null; } return await response.json(); } async function getTab(tabName) { let tab = null; while (!tab) { tab = gradioApp().getElementById(`tab_${tabName}`); if (!tab) { await new Promise((resolve) => setTimeout(resolve, 200)); } } return tab; } document.addEventListener('DOMContentLoaded', function() { (async() => { const tabId = "txt2img"; await postAPI("/whapi/v1/init", null); init(await getTab(tabId), tabId); })(); }); function init(_, tabId) { let textColor = getComputedStyle(document.documentElement).getPropertyValue('--body-text-color').trim(); let textColorRgb = textColor.slice(1).match(/.{1,2}/g).map(hex => parseInt(hex, 16)); let textColorRgba = [...textColorRgb, 0.2]; document.documentElement.style.setProperty('--weight-helper-shadow', `rgba(${textColorRgba.join(",")})`); const genButtons = document.querySelectorAll("button:is([id*='_generate'])"); genButtons.forEach((button) => { button.addEventListener('click', function(e) { if (WeightHelper.last_instance) { WeightHelper.last_instance.close(); } }, true); }); const textareas = document.querySelectorAll("*:is([id*='_toprow'] [id*='_prompt'], .prompt) textarea"); const lbwPreset = gradioApp().getElementById("lbw_ratiospreset"); textareas.forEach((textarea) => { textarea.addEventListener('contextmenu', function(e) { if (!lbwPreset) { return; } if (!opts.weight_helper_enabled) { return; } if (WeightHelper.last_instance) { e.preventDefault(); WeightHelper.last_instance.close(); return; } let selectedText = window.getSelection().toString(); if (selectedText) { return; } const prompt = e.target.value; let tmpSelectionStart = e.target.selectionStart; const lCar = prompt.lastIndexOf("<", tmpSelectionStart - 1); const rCar = prompt.indexOf(">", tmpSelectionStart); if (lCar < 0 || rCar < 0) { return; } selectedText = prompt.substring(lCar, rCar + 1); if ((selectedText.match(//g) || []).length != 1) { return; } tmpSelectionStart = lCar; const match = WeightHelper.REGEX.exec(selectedText); if (match) { const type = match[1].toLowerCase(); const name = match[2]; const weights = match[3]; if (WeightHelper.SUPPORT_TYPE.has(type)) { e.preventDefault(); const selectionStart = tmpSelectionStart + match.index; const selectionEnd = selectionStart + match.input.trim().length; const lastWeightInfo = new WeightHelper(tabId, e.target, selectionStart, selectionEnd, type, name, weights); lastWeightInfo.show(e.pageY + 15, e.pageX); } } }); }) }