Public
Edited
Apr 22
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof photo = ImageTagAdder();
Insert cell
photo
Insert cell
function ImageTagAdder() {

// Input image
const inputFile = Inputs.file({
label: "Image to Upload",
accept: ".jpg, .jpeg, .png"
});

// Input tags
const inputTags = Inputs.textarea({
label: "Tags to Add (use comma to separate)",
submit: true
})
const thumbsHolder = htl.html`<output></output>`;

let imageData = {
file: inputFile.value,
tags: []
};
const target = htl.html`<div>
${inputFile}
<div>
<style>
img {
max-width: 400px;
max-height: 400px;
}
.tag {
display: inline-block;
background: #def;
border-radius: 4px;
padding: 2px 6px;
margin: 2px;
font-family: sans-serif;
font-size: 0.9em;
}
</style>
${inputTags}
${thumbsHolder}
</div>
</div>`;

async function showValue() {
thumbsHolder.innerHTML = "";
try {
const image = await htl.html`<div>${await widget.value.file.image()}</div>`;
thumbsHolder.appendChild(image);
try {
if (imageData.tags.length > 0) {
const tagContainer = htl.html`<div>
${imageData.tags.map(tag => htl.html`<span class="tag">${tag}</span>`)}
</div>`;
thumbsHolder.appendChild(tagContainer);
}
} catch (error) {
console.error("Tags error");
}
} catch (error) {
console.error("Image error");
}
}

const widget = ReactiveWidget(target, {
value: imageData,
showValue
});

inputFile.oninput = (evt) => {
evt.stopPropagation();
evt.preventDefault();

const file = inputFile.value;
if (file) {
imageData.file = file;
imageData.tags = [];
// widget.setValue(imageData);
}
};

inputTags.addEventListener("submit", () => {
if (!imageData.file) return;

const newTags = inputTags.value
.split(",")
.map(tag => tag.trim())
.filter(tag => tag.length > 0);

if (newTags.length > 0) {
imageData.tags = [...new Set([...imageData.tags, ...newTags])];
// widget.setValue(imageData);
}
});

// showValue();
return widget;
}
Insert cell
import {ReactiveWidget} from "@john-guerra/reactive-widgets"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more