function gradioCustomJS() {
console.log("gradioCustomJS Started")
// MARK: berechne Helligkeit der Akzentfarbe
function berechneHelligkeit(rgb) {
const match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/)
if (!match) {
throw new Error("Ungültiges Farbformat")
}
const r = parseInt(match[1]) / 255
const g = parseInt(match[2]) / 255
const b = parseInt(match[3]) / 255
const rLin = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4)
const gLin = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4)
const bLin = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4)
const luminanz = 0.2126 * rLin + 0.7152 * gLin + 0.0722 * bLin
return luminanz
}
// MARK: Textfarbe bestimmen
function anpasseTextfarbe(farbe) {
const luminanz = berechneHelligkeit(farbe)
const textFarbe = luminanz > 0.4 ? "var(--neutral-950)" : "var(--neutral-50)"
console.log("Luminanz: " + luminanz + " Text-Farbe: " + textFarbe)
return textFarbe
}
const body = document.querySelector("body")
body.className = "dark"
// Catppuccin colors
const rosewater = "245, 224, 220"
const flamingo = "242, 205, 205"
const pink = "245, 194, 231"
const mauve = "203, 166, 247"
const red = "243, 139, 168"
const maroon = "235, 160, 172"
const peach = "250, 179, 135"
const yellow = "249, 226, 175"
const green = "166, 227, 161"
const teal = "148, 226, 213"
const sky = "137, 220, 235"
const sapphire = "116, 199, 236"
const blue = "137, 180, 250"
let colors = [rosewater, flamingo, pink, mauve, red, maroon, peach, yellow, green, teal, sky, sapphire, blue]
let usedColor = `rgb(${colors[Math.floor(Math.random() * colors.length)]})`
body.style.setProperty("--cat-rosewater", "rgb(" + rosewater + ")")
body.style.setProperty("--cat-flamingo", "rgb(" + flamingo + ")")
body.style.setProperty("--cat-pink", "rgb(" + pink + ")")
body.style.setProperty("--cat-mauve", "rgb(" + mauve + ")")
body.style.setProperty("--cat-red", "rgb(" + red + ")")
body.style.setProperty("--cat-maroon", "rgb(" + maroon + ")")
body.style.setProperty("--cat-peach", "rgb(" + peach + ")")
body.style.setProperty("--cat-yellow", "rgb(" + yellow + ")")
body.style.setProperty("--cat-green", "rgb(" + green + ")")
body.style.setProperty("--cat-teal", "rgb(" + teal + ")")
body.style.setProperty("--cat-sky", "rgb(" + sky + ")")
body.style.setProperty("--cat-sapphire", "rgb(" + sapphire + ")")
body.style.setProperty("--cat-blue", "rgb(" + blue + ")")
body.style.setProperty("--primary-600", usedColor)
body.style.setProperty("--primary-50", "color-mix(in srgb, var(--primary-600) 5%, white)")
body.style.setProperty("--primary-100", "color-mix(in srgb, var(--primary-600) 10%, white)")
body.style.setProperty("--primary-200", "color-mix(in srgb, var(--primary-600) 20%, white)")
body.style.setProperty("--primary-300", "color-mix(in srgb, var(--primary-600) 60%, white)")
body.style.setProperty("--primary-400", "color-mix(in srgb, var(--primary-600) 70%, white)")
body.style.setProperty("--primary-500", "color-mix(in srgb, var(--primary-600) 80%, white)")
body.style.setProperty("--primary-700", "color-mix(in srgb, var(--primary-600) 80%, black)")
body.style.setProperty("--primary-800", "color-mix(in srgb, var(--primary-600) 65%, black)")
body.style.setProperty("--primary-900", "color-mix(in srgb, var(--primary-600) 40%, black)")
body.style.setProperty("--primary-950", "color-mix(in srgb, var(--primary-600) 30%, black)")
body.style.setProperty("--button-primary-background-fill", "var(--primary-600)")
body.style.setProperty("--button-primary-background-fill-hover", "var(--primary-500)")
body.style.setProperty("--blur-value", "0px")
body.style.setProperty("--text-color-by-luminance", anpasseTextfarbe(usedColor))
// MARK: Selectors & Elements
const gradioApp = document.querySelector("gradio-app")
const gradioContainer = document.querySelector("body > gradio-app > div.gradio-container")
const dominantColorField = document.querySelector("#dominant_image_color > label > textarea")
const outputImageElem = document.querySelector("#output_image > div.image-container.svelte-1p15vfy > button > div > img")
const alertModalElem = document.createElement("div")
const alertModalElemP = document.createElement("p")
const alertModalElemI = document.createElement("i")
alertModalElemI.className = "fas fa-exclamation-circle"
const alertModalElemSpan = document.createElement("span")
alertModalElemSpan.id = "alertModalText"
const alertModalElemButton = document.createElement("button")
alertModalElemButton.className = "lg primary run-btn svelte-cmf5ev"
alertModalElemButton.id = "alertModalBtn"
alertModalElemButton.textContent = "Ok"
alertModalElemP.id = "alertModalP"
alertModalElemP.append(alertModalElemI, alertModalElemSpan)
alertModalElem.id = "alertModal"
alertModalElem.style.display = "none"
alertModalElem.append(alertModalElemP, alertModalElemButton)
//alertModalElem.innerHTML = '
'
gradioApp.appendChild(alertModalElem)
alertModalElemButton.addEventListener("click", () => {
oldText = alertModalElemSpan.textContent
alertModalElemButton.disabled = true
if (alertModalElemButton.textContent == "Noch mal?") {
alertModalElemSpan.innerHTML = 'Na gut, noch mal.
Der "Ok" ... ne, der "Noch mal?" Button ändert nur diesen Text. 😉 In 10 Sekunden wird wieder die ursprüngliche Meldung gezeigt. Cool oder?'
setTimeout(() => {
alertModalElemSpan.textContent = oldText
alertModalElemButton.disabled = false
alertModalElemButton.textContent = "Noch mal?"
}, 10000)
} else if (alertModalElemButton.textContent == "Ok") {
alertModalElemSpan.innerHTML = 'Der "Ok" Button ändert nur diesen Text. 🫢
In 6 Sekunden wird wieder die ursprüngliche Meldung gezeigt. Cool oder?'
setTimeout(() => {
alertModalElemSpan.textContent = oldText
alertModalElemButton.disabled = false
alertModalElemButton.textContent = "Noch mal?"
}, 6000)
}
})
const prompt_input = document.querySelector("#prompt_input")
prompt_input.setAttribute("autocomplete", "off")
prompt_input.setAttribute("autocorrect", "off")
prompt_input.setAttribute("autocapitalize", "off")
prompt_input.setAttribute("spellcheck", "false")
const switch_width_height = document.querySelector("#switch_width_height")
const random_prompt_btn = document.querySelector("#random_prompt_btn")
const switch_ratio_btns = document.querySelectorAll("#image_ratio_buttons label")
// MARK: DOM Change Detection
function onDominantImageColorChange(callback) {
const observer = new MutationObserver(callback)
observer.observe(document.querySelector("#dominant_image_color"), {
childList: true,
subtree: true,
})
}
function onImageRatioButtonsChange(callback) {
const observer = new MutationObserver(callback)
observer.observe(document.querySelector("#image_ratio_buttons"), {
childList: true,
subtree: true,
})
}
function onDomElemChange(selector) {
return new Promise((resolve) => {
const element = document.querySelector(selector)
if (!element) {
console.error(`Element nicht gefunden: ${selector}`)
return
}
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === "childList" || mutation.type === "attributes") {
resolve(element)
}
})
})
observer.observe(element, {
childList: true,
subtree: true,
attributes: true,
})
// Wiederholt aufgerufen werden
function watch() {
observer.disconnect()
observer.observe(element, {
childList: true,
subtree: true,
attributes: true,
})
setTimeout(watch, 100)
}
watch()
})
}
onDominantImageColorChange(() => {
console.log("changed: " + document.querySelector("#dominant_image_color > label > textarea").value)
if (document.querySelector("#dominant_image_color > label > textarea").value.match(/^rgb\((\d{1,3}),(\s\d{1,3}),(\s\d{1,3})\)$/) && document.querySelector("#output_image > div.image-container.svelte-1p15vfy > button > div > img").src) {
document.querySelector("#output_image > div.image-container.svelte-1p15vfy > button > div > img").style.opacity = "0"
document.querySelector("body > gradio-app > div").classList.add("fade-bg")
document.querySelector("gradio-app").style.opacity = "0"
setTimeout(() => {
usedColor = document.querySelector("#dominant_image_color > label > textarea").value
body.style.setProperty("--primary-600", document.querySelector("#dominant_image_color > label > textarea").value)
body.style.setProperty("--text-color-by-luminance", anpasseTextfarbe(document.querySelector("#dominant_image_color > label > textarea").value))
gradioApp.classList.add("has-bg-image")
body.style.setProperty("--bg-image-path", `url("${document.querySelector("#output_image > div.image-container.svelte-1p15vfy > button > div > img").src}")`)
}, 400)
setTimeout(() => {
gradioApp.style.opacity = "1"
document.querySelector("#output_image > div.image-container.svelte-1p15vfy > button > div > img").style.opacity = "1"
document.querySelector("#dominant_image_color > label > textarea").value = ""
}, 800)
setTimeout(() => {
//document.querySelector("body > gradio-app > div").classList.remove("fade-bg")
}, 2000)
}
})
// MARK: SVGs
winking_hand__emoji =
''
random_prompt_btn.innerHTML =
''
const enhance_prompt_btn = document.querySelector("#enhance_prompt_btn")
enhance_prompt_btn.innerHTML =
''
const run_btn = document.querySelector("#run_btn")
run_btn.innerHTML =
''
// switch_width_height.innerHTML =
// ''
const switch_width_height_inner = document.createElement("div")
switch_width_height_inner.id = "switch_width_height_inner"
switch_width_height_inner.setAttribute("data-aspect-ratio", "9-16")
switch_width_height_inner.className = "hochformat"
switch_width_height.append(switch_width_height_inner)
const switch_width_height_btn_inner = document.querySelector("div#switch_width_height_inner")
switch_width_height.addEventListener("click", () => {
//switch_width_height_btn_inner.className = document.querySelector("#image_ratio_buttons > span").textContent.toLocaleLowerCase()
})
switch_ratio_btns.forEach((_) => {
_.querySelector("input").addEventListener("click", (e) => {
switch_width_height_btn_inner.setAttribute("data-aspect-ratio", e.target.value.replace(":", "-").trim())
})
})
onImageRatioButtonsChange(() => {
switch_width_height_btn_inner.className = document.querySelector("#image_ratio_buttons > span").textContent.toLocaleLowerCase()
const selected_ratio = document.querySelector("#image_ratio_buttons label.selected input").value.replace(":", "-").trim()
if (switch_width_height_btn_inner.getAttribute("data-aspect-ratio") != selected_ratio) {
switch_width_height_btn_inner.setAttribute("data-aspect-ratio", selected_ratio)
}
})
// MARK: Element-Ready function
function elementReady(selector) {
return new Promise((resolve, reject) => {
const el = document.querySelector(selector)
if (el) {
resolve(el)
}
new MutationObserver((mutationRecords, observer) => {
Array.from(document.querySelectorAll(selector)).forEach((element) => {
resolve(element)
observer.disconnect()
})
}).observe(document.documentElement, {
childList: true,
subtree: true,
})
})
}
// MARK: Mobile Check
function istMobile() {
// Überprüfen, ob das Gerät ein Touchscreen hat
if ("ontouchstart" in window || (navigator.maxTouchPoints && window.innerWidth < 768)) {
gradioContainer.classList.add("blur-container")
body.style.setProperty("--blur-value", "12px")
gradioApp.style.height = "calc(100vh - 120px)"
alertModalElem.style.display = ""
alertModalElemSpan.textContent = "Diese Seite ist nicht für mobile Geräte optimiert. Bitte besuche diese Seite von einem Desktop-Computer aus."
} else if (window.innerWidth < 1024) {
gradioContainer.classList.add("blur-container")
body.style.setProperty("--blur-value", "12px")
gradioApp.style.height = "calc(100vh - 120px)"
alertModalElem.style.display = ""
alertModalElemSpan.textContent = "Bildschirm Auflösung oder Fensterbreite zu gering. Bitte besuche diese Seite von einem Desktop-Computer aus."
} else {
gradioContainer.classList.remove("blur-container")
body.style.setProperty("--blur-value", "0px")
gradioApp.style.height = ""
alertModalElem.style.display = "none"
alertModalElemSpan.textContent = ""
}
}
// MARK: Event Listeners
window.addEventListener("resize", () => {
console.log("Event Window resize.")
istMobile()
})
elementReady("body > gradio-app > div.gradio-container").then((element) => {
console.log("Element exist: " + element)
istMobile()
})
return "Custom Gradio JS"
}