|
|
'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; |
|
|
} |
|
|
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 || (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); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}) |
|
|
} |
|
|
|